aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2013-11-30 20:44:23 -0500
committerPaul Gilbert2013-11-30 20:44:23 -0500
commitede418b67a0f14e4f17a2b03f5362741badd5532 (patch)
tree07de039fac5c303f1b9fce372afe5fa19854f547
parent66d1f7a8de2ff5a21ad013f45924c406f4833e9a (diff)
parent3e859768770a0b385e21c4528cd546b33ed9a55d (diff)
downloadscummvm-rg350-ede418b67a0f14e4f17a2b03f5362741badd5532.tar.gz
scummvm-rg350-ede418b67a0f14e4f17a2b03f5362741badd5532.tar.bz2
scummvm-rg350-ede418b67a0f14e4f17a2b03f5362741badd5532.zip
VOYEUR: Merge of upstream
-rw-r--r--.gitignore17
-rw-r--r--AUTHORS412
-rw-r--r--Makefile20
-rw-r--r--Makefile.common15
-rw-r--r--NEWS15
-rw-r--r--audio/midiparser.cpp138
-rw-r--r--audio/midiparser.h6
-rw-r--r--audio/mixer.cpp21
-rw-r--r--audio/softsynth/fluidsynth.cpp2
-rw-r--r--audio/softsynth/mt32.cpp6
-rw-r--r--audio/softsynth/mt32/AReverbModel.cpp277
-rw-r--r--audio/softsynth/mt32/AReverbModel.h87
-rw-r--r--audio/softsynth/mt32/BReverbModel.cpp129
-rw-r--r--audio/softsynth/mt32/BReverbModel.h24
-rw-r--r--audio/softsynth/mt32/DelayReverb.cpp142
-rw-r--r--audio/softsynth/mt32/DelayReverb.h50
-rw-r--r--audio/softsynth/mt32/FreeverbModel.cpp78
-rw-r--r--audio/softsynth/mt32/FreeverbModel.h44
-rw-r--r--audio/softsynth/mt32/LA32FloatWaveGenerator.cpp (renamed from audio/softsynth/mt32/LegacyWaveGenerator.cpp)36
-rw-r--r--audio/softsynth/mt32/LA32FloatWaveGenerator.h (renamed from audio/softsynth/mt32/LegacyWaveGenerator.h)6
-rw-r--r--audio/softsynth/mt32/LA32WaveGenerator.cpp60
-rw-r--r--audio/softsynth/mt32/LA32WaveGenerator.h8
-rw-r--r--audio/softsynth/mt32/Part.cpp49
-rw-r--r--audio/softsynth/mt32/Part.h4
-rw-r--r--audio/softsynth/mt32/Partial.cpp141
-rw-r--r--audio/softsynth/mt32/Partial.h38
-rw-r--r--audio/softsynth/mt32/PartialManager.cpp62
-rw-r--r--audio/softsynth/mt32/PartialManager.h12
-rw-r--r--audio/softsynth/mt32/Poly.cpp49
-rw-r--r--audio/softsynth/mt32/Poly.h6
-rw-r--r--audio/softsynth/mt32/Structures.h6
-rw-r--r--audio/softsynth/mt32/Synth.cpp663
-rw-r--r--audio/softsynth/mt32/Synth.h209
-rw-r--r--audio/softsynth/mt32/TVA.cpp6
-rw-r--r--audio/softsynth/mt32/TVP.cpp2
-rw-r--r--audio/softsynth/mt32/Tables.h5
-rw-r--r--audio/softsynth/mt32/freeverb.cpp324
-rw-r--r--audio/softsynth/mt32/freeverb.h189
-rw-r--r--audio/softsynth/mt32/module.mk9
-rw-r--r--audio/softsynth/mt32/mt32emu.h35
-rw-r--r--backends/audiocd/audiocd.h2
-rw-r--r--backends/base-backend.cpp4
-rw-r--r--backends/events/default/default-events.cpp5
-rw-r--r--backends/events/sdl/sdl-events.cpp15
-rw-r--r--backends/fs/abstract-fs.h2
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp14
-rw-r--r--backends/graphics/graphics.h21
-rw-r--r--backends/graphics/opengl/debug.cpp65
-rw-r--r--backends/graphics/opengl/debug.h39
-rw-r--r--backends/graphics/opengl/extensions.cpp48
-rw-r--r--backends/graphics/opengl/extensions.h41
-rw-r--r--backends/graphics/opengl/gltexture.cpp225
-rw-r--r--backends/graphics/opengl/gltexture.h131
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp1829
-rw-r--r--backends/graphics/opengl/opengl-graphics.h490
-rw-r--r--backends/graphics/opengl/opengl-sys.h (renamed from backends/graphics/opengl/glerrorcheck.cpp)50
-rw-r--r--backends/graphics/opengl/texture.cpp371
-rw-r--r--backends/graphics/opengl/texture.h175
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp909
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h132
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp9
-rw-r--r--backends/graphics/sdl/sdl-graphics.h3
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp85
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h7
-rw-r--r--backends/keymapper/keymapper.h2
-rw-r--r--backends/midi/timidity.cpp2
-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.mk34
-rw-r--r--backends/mutex/sdl/sdl-mutex.cpp6
-rw-r--r--backends/platform/android/android.cpp5
-rw-r--r--backends/platform/android/android.h3
-rw-r--r--backends/platform/android/android.mk8
-rw-r--r--backends/platform/android/events.cpp111
-rw-r--r--backends/platform/android/gfx.cpp4
-rw-r--r--backends/platform/android/org/scummvm/scummvm/MouseHelper.java18
-rw-r--r--backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java8
-rw-r--r--backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java36
-rw-r--r--backends/platform/android/texture.cpp10
-rw-r--r--backends/platform/bada/application.cpp111
-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/display.cpp6
-rw-r--r--backends/platform/dc/selector.cpp2
-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.cpp25
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h2
-rw-r--r--backends/platform/gph/gph-backend.cpp2
-rw-r--r--backends/platform/iphone/iphone_video.mm6
-rw-r--r--backends/platform/iphone/osys_main.cpp6
-rw-r--r--backends/platform/iphone/osys_main.h2
-rw-r--r--backends/platform/iphone/osys_video.mm22
-rw-r--r--backends/platform/maemo/debian/changelog10
-rw-r--r--backends/platform/n64/osys_n64.h2
-rw-r--r--backends/platform/n64/osys_n64_base.cpp8
-rw-r--r--backends/platform/null/null.cpp2
-rw-r--r--backends/platform/openpandora/op-backend.cpp2
-rw-r--r--backends/platform/ps2/Gs2dScreen.cpp8
-rw-r--r--backends/platform/ps2/systemps2.cpp2
-rw-r--r--backends/platform/ps2/systemps2.h2
-rw-r--r--backends/platform/psp/audio.cpp2
-rw-r--r--backends/platform/psp/default_display_client.cpp7
-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/posix/posix.cpp11
-rw-r--r--backends/platform/sdl/sdl-sys.h3
-rw-r--r--backends/platform/sdl/sdl.cpp359
-rw-r--r--backends/platform/sdl/sdl.h18
-rw-r--r--backends/platform/symbian/AdaptAllMMPs.pl40
-rw-r--r--backends/platform/symbian/BuildPackageUpload_AllVersions.pl7
-rw-r--r--backends/platform/symbian/BuildPackageUpload_LocalSettings.pl108
-rw-r--r--backends/platform/symbian/README12
-rw-r--r--backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg38
-rw-r--r--backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg39
-rw-r--r--backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg2
-rw-r--r--backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg2
-rw-r--r--backends/platform/symbian/mmp/scummvm_avalanche.mmp.in62
-rw-r--r--backends/platform/symbian/mmp/scummvm_base.mmp.in9
-rw-r--r--backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in62
-rw-r--r--backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in62
-rw-r--r--backends/platform/symbian/mmp/scummvm_kyra.mmp.in7
-rw-r--r--backends/platform/symbian/mmp/scummvm_mohawk.mmp.in19
-rw-r--r--backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in62
-rw-r--r--backends/platform/symbian/mmp/scummvm_neverhood.mmp.in61
-rw-r--r--backends/platform/symbian/mmp/scummvm_sci.mmp.in8
-rw-r--r--backends/platform/symbian/mmp/scummvm_sword25.mmp.in63
-rw-r--r--backends/platform/symbian/mmp/scummvm_testbed.mmp.in62
-rw-r--r--backends/platform/symbian/mmp/scummvm_zvision.mmp.in62
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp5
-rw-r--r--backends/platform/symbian/src/portdefs.h2
-rw-r--r--backends/platform/tizen/README.TXT (renamed from backends/platform/bada/README.TXT)116
-rw-r--r--backends/platform/tizen/application.cpp144
-rw-r--r--backends/platform/tizen/application.h69
-rw-r--r--backends/platform/tizen/audio.cpp (renamed from backends/platform/bada/audio.cpp)119
-rw-r--r--backends/platform/tizen/audio.h (renamed from backends/platform/bada/audio.h)41
-rw-r--r--backends/platform/tizen/form.cpp432
-rw-r--r--backends/platform/tizen/form.h120
-rw-r--r--backends/platform/tizen/fs.cpp (renamed from backends/platform/bada/fs.cpp)293
-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)195
-rw-r--r--backends/platform/tizen/graphics.h (renamed from backends/platform/bada/graphics.h)38
-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)2
-rw-r--r--backends/platform/tizen/system.cpp (renamed from backends/platform/bada/system.cpp)291
-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/platform/wii/osystem_gfx.cpp11
-rw-r--r--backends/platform/wince/wince-sdl.cpp5
-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--backends/vkeybd/virtual-keyboard-gui.cpp42
-rw-r--r--backends/vkeybd/virtual-keyboard-gui.h6
-rw-r--r--backends/vkeybd/virtual-keyboard.h4
-rw-r--r--base/commandLine.cpp38
-rw-r--r--base/main.cpp52
-rw-r--r--base/plugins.h2
-rw-r--r--base/version.cpp8
-rw-r--r--common/EventDispatcher.cpp14
-rw-r--r--common/EventRecorder.cpp428
-rw-r--r--common/EventRecorder.h110
-rw-r--r--common/archive.cpp6
-rw-r--r--common/archive.h6
-rw-r--r--common/c++11-compat.h2
-rw-r--r--common/config-manager.h27
-rw-r--r--common/coroutines.h3
-rw-r--r--common/cosinetables.cpp6
-rw-r--r--common/cosinetables.h9
-rw-r--r--common/dcl.cpp6
-rw-r--r--common/debug.h4
-rw-r--r--common/events.h12
-rw-r--r--common/ini-file.cpp (renamed from common/config-file.cpp)60
-rw-r--r--common/ini-file.h (renamed from common/config-file.h)29
-rw-r--r--common/macresman.cpp98
-rw-r--r--common/macresman.h25
-rw-r--r--common/math.h8
-rw-r--r--common/memstream.h37
-rw-r--r--common/module.mk9
-rw-r--r--common/random.cpp13
-rw-r--r--common/rdft.h36
-rw-r--r--common/recorderfile.cpp716
-rw-r--r--common/recorderfile.h180
-rw-r--r--common/scummsys.h63
-rw-r--r--common/sinetables.cpp12
-rw-r--r--common/sinetables.h7
-rw-r--r--common/str.cpp19
-rw-r--r--common/str.h12
-rw-r--r--common/system.cpp17
-rw-r--r--common/system.h18
-rw-r--r--common/unarj.cpp11
-rw-r--r--common/ustr.cpp329
-rw-r--r--common/ustr.h194
-rw-r--r--common/util.h8
-rw-r--r--common/winexe.cpp2
-rw-r--r--common/winexe_ne.cpp32
-rw-r--r--common/winexe_ne.h50
-rw-r--r--common/zlib.cpp22
-rwxr-xr-xconfigure404
-rw-r--r--devtools/README7
-rw-r--r--devtools/convbdf.cpp4
-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.cpp275
-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/menudata.h143
-rw-r--r--devtools/create_mortdat/module.mk11
-rw-r--r--devtools/create_neverhood/create_neverhood.cpp105
-rw-r--r--devtools/create_neverhood/md5.cpp273
-rw-r--r--devtools/create_neverhood/md5.h41
-rw-r--r--devtools/create_neverhood/module.mk1
-rw-r--r--devtools/create_neverhood/tables.h2
-rw-r--r--devtools/create_project/codeblocks.cpp6
-rw-r--r--devtools/create_project/config.h1
-rw-r--r--devtools/create_project/create_project.cpp474
-rw-r--r--devtools/create_project/create_project.h72
-rw-r--r--devtools/create_project/msbuild.cpp124
-rw-r--r--devtools/create_project/msbuild.h4
-rw-r--r--devtools/create_project/msvc.cpp30
-rw-r--r--devtools/create_project/msvc.h9
-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.cpp67
-rw-r--r--devtools/create_project/visualstudio.h2
-rw-r--r--devtools/create_project/xcode.cpp31
-rw-r--r--devtools/create_teenagent/static_tables.h2
-rw-r--r--devtools/create_translations/create_translations.cpp3
-rw-r--r--devtools/create_translations/create_translations.h4
-rwxr-xr-xdevtools/credits.pl58
-rw-r--r--devtools/extract_mort/extract_mort.cpp428
-rw-r--r--devtools/extract_mort/module.mk11
-rw-r--r--devtools/scumm-md5.txt9
-rw-r--r--devtools/skycpt/cptcompiler.cpp3
-rw-r--r--dists/android/AndroidManifest.xml1
-rw-r--r--dists/android/AndroidManifest.xml.in1
-rw-r--r--dists/android/res-ouya/values-television/margins.xml5
-rw-r--r--dists/android/res/drawable-xhdpi/ouya_icon.pngbin0 -> 110822 bytes
-rw-r--r--dists/android/res/layout/main.xml4
-rw-r--r--dists/android/res/values/margins.xml5
-rw-r--r--dists/engine-data/README5
-rw-r--r--dists/engine-data/mort.datbin0 -> 76151 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/redhat/scummvm.spec2
-rw-r--r--dists/redhat/scummvm.spec.in2
-rw-r--r--dists/scummvm.rc9
-rw-r--r--dists/scummvm.rc.in9
-rw-r--r--engines/advancedDetector.cpp13
-rw-r--r--engines/advancedDetector.h6
-rw-r--r--engines/agi/POTFILES2
-rw-r--r--engines/agi/agi.cpp4
-rw-r--r--engines/agi/configure.engine3
-rw-r--r--engines/agi/detection_tables.h2
-rw-r--r--engines/agi/loader_v1.cpp2
-rw-r--r--engines/agi/loader_v2.cpp2
-rw-r--r--engines/agi/loader_v3.cpp2
-rw-r--r--engines/agi/opcodes.cpp24
-rw-r--r--engines/agi/preagi_mickey.cpp2
-rw-r--r--engines/agi/preagi_troll.cpp2
-rw-r--r--engines/agi/preagi_winnie.cpp1
-rw-r--r--engines/agi/wagparser.cpp2
-rw-r--r--engines/agi/words.cpp23
-rw-r--r--engines/agos/POTFILES2
-rw-r--r--engines/agos/agos.h24
-rw-r--r--engines/agos/animation.cpp8
-rw-r--r--engines/agos/charset-fontdata.cpp8
-rw-r--r--engines/agos/charset.cpp2
-rw-r--r--engines/agos/configure.engine4
-rw-r--r--engines/agos/draw.cpp30
-rw-r--r--engines/agos/event.cpp2
-rw-r--r--engines/agos/gfx.cpp64
-rw-r--r--engines/agos/icons.cpp22
-rw-r--r--engines/agos/menus.cpp4
-rw-r--r--engines/agos/saveload.cpp99
-rw-r--r--engines/agos/script_pn.cpp14
-rw-r--r--engines/agos/verb.cpp2
-rw-r--r--engines/agos/vga.cpp11
-rw-r--r--engines/agos/vga_e2.cpp10
-rw-r--r--engines/agos/vga_pn.cpp4
-rw-r--r--engines/agos/vga_s2.cpp5
-rw-r--r--engines/agos/vga_ww.cpp2
-rw-r--r--engines/agos/window.cpp4
-rw-r--r--engines/avalanche/animation.cpp1498
-rw-r--r--engines/avalanche/animation.h171
-rw-r--r--engines/avalanche/avalanche.cpp629
-rw-r--r--engines/avalanche/avalanche.h348
-rw-r--r--engines/avalanche/avalot.cpp1755
-rw-r--r--engines/avalanche/avalot.h104
-rw-r--r--engines/avalanche/background.cpp370
-rw-r--r--engines/avalanche/background.h79
-rw-r--r--engines/avalanche/closing.cpp75
-rw-r--r--engines/avalanche/closing.h62
-rw-r--r--engines/avalanche/configure.engine3
-rw-r--r--engines/avalanche/console.cpp53
-rw-r--r--engines/avalanche/console.h51
-rw-r--r--engines/avalanche/detection.cpp209
-rw-r--r--engines/avalanche/dialogs.cpp1212
-rw-r--r--engines/avalanche/dialogs.h116
-rw-r--r--engines/avalanche/enums.h132
-rw-r--r--engines/avalanche/graphics.cpp767
-rw-r--r--engines/avalanche/graphics.h142
-rw-r--r--engines/avalanche/menu.cpp844
-rw-r--r--engines/avalanche/menu.h182
-rw-r--r--engines/avalanche/module.mk27
-rw-r--r--engines/avalanche/nim.cpp177
-rw-r--r--engines/avalanche/nim.h76
-rw-r--r--engines/avalanche/parser.cpp2481
-rw-r--r--engines/avalanche/parser.h153
-rw-r--r--engines/avalanche/pingo.cpp106
-rw-r--r--engines/avalanche/pingo.h59
-rw-r--r--engines/avalanche/sequence.cpp230
-rw-r--r--engines/avalanche/sequence.h80
-rw-r--r--engines/avalanche/sound.cpp88
-rw-r--r--engines/avalanche/sound.h53
-rw-r--r--engines/avalanche/timer.cpp693
-rw-r--r--engines/avalanche/timer.h178
-rw-r--r--engines/cge/cge.cpp1
-rw-r--r--engines/cge/cge.h6
-rw-r--r--engines/cge/cge_main.cpp8
-rw-r--r--engines/cge/configure.engine3
-rw-r--r--engines/cge/detection.cpp119
-rw-r--r--engines/cge/snail.cpp2
-rw-r--r--engines/cge/text.cpp5
-rw-r--r--engines/cge/vga13h.cpp9
-rw-r--r--engines/cine/configure.engine3
-rw-r--r--engines/cine/script_fw.cpp3
-rw-r--r--engines/cine/sound.cpp6
-rw-r--r--engines/composer/composer.cpp25
-rw-r--r--engines/composer/composer.h4
-rw-r--r--engines/composer/configure.engine3
-rw-r--r--engines/composer/graphics.cpp10
-rw-r--r--engines/configure.engines54
-rw-r--r--engines/cruise/POTFILES1
-rw-r--r--engines/cruise/configure.engine3
-rw-r--r--engines/cruise/cruise.h4
-rw-r--r--engines/cruise/detection.cpp37
-rw-r--r--engines/draci/barchive.cpp12
-rw-r--r--engines/draci/configure.engine3
-rw-r--r--engines/draci/draci.cpp26
-rw-r--r--engines/draci/game.cpp55
-rw-r--r--engines/draci/screen.cpp4
-rw-r--r--engines/draci/script.cpp110
-rw-r--r--engines/draci/sprite.cpp4
-rw-r--r--engines/draci/surface.cpp4
-rw-r--r--engines/draci/walking.cpp6
-rw-r--r--engines/draci/walking.h12
-rw-r--r--engines/drascula/POTFILES2
-rw-r--r--engines/drascula/actors.cpp16
-rw-r--r--engines/drascula/animation.cpp22
-rw-r--r--engines/drascula/configure.engine3
-rw-r--r--engines/drascula/console.cpp2
-rw-r--r--engines/drascula/converse.cpp22
-rw-r--r--engines/drascula/detection.cpp126
-rw-r--r--engines/drascula/drascula.cpp188
-rw-r--r--engines/drascula/drascula.h16
-rw-r--r--engines/drascula/graphics.cpp32
-rw-r--r--engines/drascula/interface.cpp8
-rw-r--r--engines/drascula/objects.cpp77
-rw-r--r--engines/drascula/rooms.cpp60
-rw-r--r--engines/drascula/saveload.cpp24
-rw-r--r--engines/drascula/sound.cpp16
-rw-r--r--engines/drascula/talk.cpp54
-rw-r--r--engines/dreamweb/POTFILES1
-rw-r--r--engines/dreamweb/configure.engine3
-rw-r--r--engines/dreamweb/dreamweb.cpp44
-rw-r--r--engines/dreamweb/dreamweb.h3
-rw-r--r--engines/dreamweb/monitor.cpp10
-rw-r--r--engines/dreamweb/print.cpp2
-rw-r--r--engines/engine.cpp2
-rw-r--r--engines/engines.mk248
-rw-r--r--engines/fullpipe/behavior.cpp334
-rw-r--r--engines/fullpipe/behavior.h88
-rw-r--r--engines/fullpipe/configure.engine3
-rw-r--r--engines/fullpipe/constants.h296
-rw-r--r--engines/fullpipe/detection.cpp112
-rw-r--r--engines/fullpipe/floaters.cpp45
-rw-r--r--engines/fullpipe/floaters.h67
-rw-r--r--engines/fullpipe/fullpipe.cpp451
-rw-r--r--engines/fullpipe/fullpipe.h262
-rw-r--r--engines/fullpipe/gameloader.cpp513
-rw-r--r--engines/fullpipe/gameloader.h117
-rw-r--r--engines/fullpipe/gfx.cpp1250
-rw-r--r--engines/fullpipe/gfx.h218
-rw-r--r--engines/fullpipe/init.cpp247
-rw-r--r--engines/fullpipe/input.cpp277
-rw-r--r--engines/fullpipe/input.h77
-rw-r--r--engines/fullpipe/interaction.cpp528
-rw-r--r--engines/fullpipe/interaction.h98
-rw-r--r--engines/fullpipe/inventory.cpp437
-rw-r--r--engines/fullpipe/inventory.h132
-rw-r--r--engines/fullpipe/lift.cpp108
-rw-r--r--engines/fullpipe/messagehandlers.cpp743
-rw-r--r--engines/fullpipe/messages.cpp791
-rw-r--r--engines/fullpipe/messages.h181
-rw-r--r--engines/fullpipe/modal.cpp242
-rw-r--r--engines/fullpipe/modal.h80
-rw-r--r--engines/fullpipe/module.mk39
-rw-r--r--engines/fullpipe/motion.cpp1611
-rw-r--r--engines/fullpipe/motion.h372
-rw-r--r--engines/fullpipe/ngiarchive.cpp156
-rw-r--r--engines/fullpipe/ngiarchive.h69
-rw-r--r--engines/fullpipe/objectnames.h250
-rw-r--r--engines/fullpipe/objects.h97
-rw-r--r--engines/fullpipe/scene.cpp691
-rw-r--r--engines/fullpipe/scene.h107
-rw-r--r--engines/fullpipe/scenes.cpp712
-rw-r--r--engines/fullpipe/scenes.h132
-rw-r--r--engines/fullpipe/scenes/scene01.cpp117
-rw-r--r--engines/fullpipe/scenes/scene02.cpp137
-rw-r--r--engines/fullpipe/scenes/scene03.cpp294
-rw-r--r--engines/fullpipe/scenes/scene04.cpp731
-rw-r--r--engines/fullpipe/scenes/sceneDbg.cpp107
-rw-r--r--engines/fullpipe/scenes/sceneIntro.cpp109
-rw-r--r--engines/fullpipe/sound.cpp140
-rw-r--r--engines/fullpipe/sound.h62
-rw-r--r--engines/fullpipe/stateloader.cpp321
-rw-r--r--engines/fullpipe/statics.cpp1910
-rw-r--r--engines/fullpipe/statics.h257
-rw-r--r--engines/fullpipe/utils.cpp501
-rw-r--r--engines/fullpipe/utils.h155
-rw-r--r--engines/gob/POTFILES3
-rw-r--r--engines/gob/configure.engine3
-rw-r--r--engines/gob/iniconfig.cpp4
-rw-r--r--engines/gob/iniconfig.h4
-rw-r--r--engines/gob/surface.cpp18
-rw-r--r--engines/gob/videoplayer.cpp6
-rw-r--r--engines/groovie/POTFILES2
-rw-r--r--engines/groovie/configure.engine4
-rw-r--r--engines/groovie/font.cpp4
-rw-r--r--engines/groovie/font.h6
-rw-r--r--engines/groovie/graphics.cpp6
-rw-r--r--engines/groovie/roq.cpp28
-rw-r--r--engines/groovie/script.cpp4
-rw-r--r--engines/groovie/stuffit.cpp2
-rw-r--r--engines/groovie/vdx.cpp14
-rw-r--r--engines/hopkins/computer.cpp86
-rw-r--r--engines/hopkins/computer.h2
-rw-r--r--engines/hopkins/configure.engine3
-rw-r--r--engines/hopkins/detection.cpp5
-rw-r--r--engines/hopkins/detection_tables.h134
-rw-r--r--engines/hopkins/dialogs.cpp15
-rw-r--r--engines/hopkins/events.cpp2
-rw-r--r--engines/hopkins/globals.cpp4
-rw-r--r--engines/hopkins/graphics.cpp14
-rw-r--r--engines/hopkins/graphics.h2
-rw-r--r--engines/hopkins/hopkins.cpp136
-rw-r--r--engines/hopkins/hopkins.h4
-rw-r--r--engines/hopkins/lines.cpp1
-rw-r--r--engines/hopkins/menu.cpp38
-rw-r--r--engines/hopkins/saveload.cpp61
-rw-r--r--engines/hopkins/saveload.h6
-rw-r--r--engines/hopkins/script.cpp31
-rw-r--r--engines/hopkins/sound.cpp57
-rw-r--r--engines/hopkins/talk.cpp13
-rw-r--r--engines/hugo/configure.engine3
-rw-r--r--engines/hugo/dialogs.cpp12
-rw-r--r--engines/hugo/display.cpp8
-rw-r--r--engines/hugo/file.cpp6
-rw-r--r--engines/hugo/hugo.cpp48
-rw-r--r--engines/hugo/hugo.h5
-rw-r--r--engines/hugo/intro.cpp22
-rw-r--r--engines/hugo/inventory.cpp4
-rw-r--r--engines/hugo/mouse.cpp6
-rw-r--r--engines/hugo/object.cpp42
-rw-r--r--engines/hugo/parser.cpp26
-rw-r--r--engines/hugo/route.cpp13
-rw-r--r--engines/hugo/route.h4
-rw-r--r--engines/hugo/schedule.cpp62
-rw-r--r--engines/hugo/sound.cpp5
-rw-r--r--engines/hugo/text.cpp31
-rw-r--r--engines/kyra/POTFILES3
-rw-r--r--engines/kyra/animator_lok.cpp2
-rw-r--r--engines/kyra/chargen.cpp4
-rw-r--r--engines/kyra/configure.engine5
-rw-r--r--engines/kyra/gui_mr.cpp2
-rw-r--r--engines/kyra/kyra_rpg.cpp2
-rw-r--r--engines/kyra/resource.cpp8
-rw-r--r--engines/kyra/scene_mr.cpp1
-rw-r--r--engines/kyra/screen.cpp11
-rw-r--r--engines/kyra/screen_v2.cpp2
-rw-r--r--engines/kyra/sequences_lok.cpp3
-rw-r--r--engines/kyra/sound_towns.cpp1
-rw-r--r--engines/kyra/text_rpg.cpp2
-rw-r--r--engines/lastexpress/configure.engine3
-rw-r--r--engines/lastexpress/data/animation.cpp2
-rw-r--r--engines/lastexpress/data/scene.h14
-rw-r--r--engines/lastexpress/data/sequence.cpp12
-rw-r--r--engines/lastexpress/debug.cpp8
-rw-r--r--engines/lastexpress/entities/entity.h136
-rw-r--r--engines/lastexpress/entities/servers0.cpp4
-rw-r--r--engines/lastexpress/entities/verges.cpp2
-rw-r--r--engines/lastexpress/game/entities.h8
-rw-r--r--engines/lastexpress/game/inventory.cpp2
-rw-r--r--engines/lastexpress/game/logic.cpp4
-rw-r--r--engines/lastexpress/game/logic.h2
-rw-r--r--engines/lastexpress/game/object.cpp7
-rw-r--r--engines/lastexpress/game/savegame.h2
-rw-r--r--engines/lastexpress/game/scenes.cpp4
-rw-r--r--engines/lastexpress/game/state.h13
-rw-r--r--engines/lastexpress/graphics.cpp12
-rw-r--r--engines/lastexpress/lastexpress.cpp4
-rw-r--r--engines/lure/configure.engine3
-rw-r--r--engines/lure/debugger.cpp4
-rw-r--r--engines/lure/hotspots.cpp198
-rw-r--r--engines/lure/menu.cpp3
-rw-r--r--engines/made/configure.engine3
-rw-r--r--engines/made/detection.cpp114
-rw-r--r--engines/made/graphics.cpp4
-rw-r--r--engines/made/made.cpp6
-rw-r--r--engines/made/pmvplayer.cpp2
-rw-r--r--engines/made/screen.cpp8
-rw-r--r--engines/made/screenfx.cpp6
-rw-r--r--engines/made/scriptfuncs.cpp2
-rw-r--r--engines/made/sound.cpp2
-rw-r--r--engines/mohawk/POTFILES3
-rw-r--r--engines/mohawk/bitmap.cpp10
-rw-r--r--engines/mohawk/configure.engine6
-rw-r--r--engines/mohawk/cstime.cpp9
-rw-r--r--engines/mohawk/cstime_game.cpp2
-rw-r--r--engines/mohawk/cstime_ui.cpp2
-rw-r--r--engines/mohawk/cstime_ui.h3
-rw-r--r--engines/mohawk/cursors.cpp4
-rw-r--r--engines/mohawk/livingbooks.cpp16
-rw-r--r--engines/mohawk/livingbooks.h4
-rw-r--r--engines/mohawk/livingbooks_lbx.cpp10
-rw-r--r--engines/mohawk/myst.cpp1
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp1
-rw-r--r--engines/mohawk/riven_graphics.cpp8
-rw-r--r--engines/mohawk/video.cpp2
-rw-r--r--engines/mortevielle/actions.cpp1674
-rw-r--r--engines/mortevielle/configure.engine3
-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.cpp115
-rw-r--r--engines/mortevielle/detection_tables.h116
-rw-r--r--engines/mortevielle/dialogs.cpp472
-rw-r--r--engines/mortevielle/dialogs.h65
-rw-r--r--engines/mortevielle/graphics.cpp1167
-rw-r--r--engines/mortevielle/graphics.h117
-rw-r--r--engines/mortevielle/menu.cpp792
-rw-r--r--engines/mortevielle/menu.h125
-rw-r--r--engines/mortevielle/module.mk23
-rw-r--r--engines/mortevielle/mortevielle.cpp458
-rw-r--r--engines/mortevielle/mortevielle.h494
-rw-r--r--engines/mortevielle/mouse.cpp271
-rw-r--r--engines/mortevielle/mouse.h53
-rw-r--r--engines/mortevielle/outtext.cpp308
-rw-r--r--engines/mortevielle/outtext.h49
-rw-r--r--engines/mortevielle/saveload.cpp332
-rw-r--r--engines/mortevielle/saveload.h73
-rw-r--r--engines/mortevielle/sound.cpp800
-rw-r--r--engines/mortevielle/sound.h106
-rw-r--r--engines/mortevielle/utils.cpp3405
-rw-r--r--engines/neverhood/POTFILES2
-rw-r--r--engines/neverhood/background.cpp6
-rw-r--r--engines/neverhood/blbarchive.cpp19
-rw-r--r--engines/neverhood/configure.engine3
-rw-r--r--engines/neverhood/console.cpp269
-rw-r--r--engines/neverhood/console.h51
-rw-r--r--engines/neverhood/detection.cpp34
-rw-r--r--engines/neverhood/diskplayerscene.cpp56
-rw-r--r--engines/neverhood/diskplayerscene.h7
-rw-r--r--engines/neverhood/entity.cpp20
-rw-r--r--engines/neverhood/entity.h18
-rw-r--r--engines/neverhood/gamemodule.cpp51
-rw-r--r--engines/neverhood/gamemodule.h7
-rw-r--r--engines/neverhood/gamevars.cpp7
-rw-r--r--engines/neverhood/gamevars.h6
-rw-r--r--engines/neverhood/graphics.cpp32
-rw-r--r--engines/neverhood/graphics.h16
-rw-r--r--engines/neverhood/klaymen.cpp3525
-rw-r--r--engines/neverhood/klaymen.h429
-rw-r--r--engines/neverhood/menumodule.cpp229
-rw-r--r--engines/neverhood/menumodule.h11
-rw-r--r--engines/neverhood/microtiles.cpp4
-rw-r--r--engines/neverhood/module.cpp4
-rw-r--r--engines/neverhood/module.h4
-rw-r--r--engines/neverhood/module.mk19
-rw-r--r--engines/neverhood/modules/module1000.cpp1034
-rw-r--r--engines/neverhood/modules/module1000.h190
-rw-r--r--engines/neverhood/modules/module1000_sprites.cpp1632
-rw-r--r--engines/neverhood/modules/module1000_sprites.h262
-rw-r--r--engines/neverhood/modules/module1100.cpp248
-rw-r--r--engines/neverhood/modules/module1100.h51
-rw-r--r--engines/neverhood/modules/module1100_sprites.cpp265
-rw-r--r--engines/neverhood/modules/module1100_sprites.h88
-rw-r--r--engines/neverhood/modules/module1200.cpp688
-rw-r--r--engines/neverhood/modules/module1200.h136
-rw-r--r--engines/neverhood/modules/module1200_sprites.cpp810
-rw-r--r--engines/neverhood/modules/module1200_sprites.h187
-rw-r--r--engines/neverhood/modules/module1300.cpp678
-rw-r--r--engines/neverhood/modules/module1300.h129
-rw-r--r--engines/neverhood/modules/module1300_sprites.cpp935
-rw-r--r--engines/neverhood/modules/module1300_sprites.h200
-rw-r--r--engines/neverhood/modules/module1400.cpp910
-rw-r--r--engines/neverhood/modules/module1400.h151
-rw-r--r--engines/neverhood/modules/module1400_sprites.cpp1129
-rw-r--r--engines/neverhood/modules/module1400_sprites.h198
-rw-r--r--engines/neverhood/modules/module1500.cpp8
-rw-r--r--engines/neverhood/modules/module1600.cpp857
-rw-r--r--engines/neverhood/modules/module1600.h91
-rw-r--r--engines/neverhood/modules/module1600_sprites.cpp934
-rw-r--r--engines/neverhood/modules/module1600_sprites.h126
-rw-r--r--engines/neverhood/modules/module1700.cpp54
-rw-r--r--engines/neverhood/modules/module1700.h17
-rw-r--r--engines/neverhood/modules/module1700_sprites.cpp156
-rw-r--r--engines/neverhood/modules/module1700_sprites.h55
-rw-r--r--engines/neverhood/modules/module1800.cpp11
-rw-r--r--engines/neverhood/modules/module1900.cpp419
-rw-r--r--engines/neverhood/modules/module1900.h73
-rw-r--r--engines/neverhood/modules/module1900_sprites.cpp456
-rw-r--r--engines/neverhood/modules/module1900_sprites.h107
-rw-r--r--engines/neverhood/modules/module2000.cpp13
-rw-r--r--engines/neverhood/modules/module2000.h3
-rw-r--r--engines/neverhood/modules/module2000_sprites.cpp92
-rw-r--r--engines/neverhood/modules/module2000_sprites.h41
-rw-r--r--engines/neverhood/modules/module2100.cpp141
-rw-r--r--engines/neverhood/modules/module2100.h32
-rw-r--r--engines/neverhood/modules/module2100_sprites.cpp260
-rw-r--r--engines/neverhood/modules/module2100_sprites.h75
-rw-r--r--engines/neverhood/modules/module2200.cpp958
-rw-r--r--engines/neverhood/modules/module2200.h178
-rw-r--r--engines/neverhood/modules/module2200_sprites.cpp1429
-rw-r--r--engines/neverhood/modules/module2200_sprites.h275
-rw-r--r--engines/neverhood/modules/module2300.cpp14
-rw-r--r--engines/neverhood/modules/module2400.cpp371
-rw-r--r--engines/neverhood/modules/module2400.h70
-rw-r--r--engines/neverhood/modules/module2400_sprites.cpp741
-rw-r--r--engines/neverhood/modules/module2400_sprites.h139
-rw-r--r--engines/neverhood/modules/module2500.cpp84
-rw-r--r--engines/neverhood/modules/module2500.h18
-rw-r--r--engines/neverhood/modules/module2500_sprites.cpp127
-rw-r--r--engines/neverhood/modules/module2500_sprites.h51
-rw-r--r--engines/neverhood/modules/module2600.cpp95
-rw-r--r--engines/neverhood/modules/module2600.h18
-rw-r--r--engines/neverhood/modules/module2600_sprites.cpp115
-rw-r--r--engines/neverhood/modules/module2600_sprites.h54
-rw-r--r--engines/neverhood/modules/module2700.cpp184
-rw-r--r--engines/neverhood/modules/module2700.h37
-rw-r--r--engines/neverhood/modules/module2700_sprites.cpp178
-rw-r--r--engines/neverhood/modules/module2700_sprites.h74
-rw-r--r--engines/neverhood/modules/module2800.cpp1162
-rw-r--r--engines/neverhood/modules/module2800.h238
-rw-r--r--engines/neverhood/modules/module2800_sprites.cpp1626
-rw-r--r--engines/neverhood/modules/module2800_sprites.h337
-rw-r--r--engines/neverhood/modules/module2900.cpp219
-rw-r--r--engines/neverhood/modules/module2900.h36
-rw-r--r--engines/neverhood/modules/module2900_sprites.cpp232
-rw-r--r--engines/neverhood/modules/module2900_sprites.h72
-rw-r--r--engines/neverhood/modules/module3000.cpp764
-rw-r--r--engines/neverhood/modules/module3000.h162
-rw-r--r--engines/neverhood/modules/module3000_sprites.cpp763
-rw-r--r--engines/neverhood/modules/module3000_sprites.h185
-rw-r--r--engines/neverhood/mouse.cpp52
-rw-r--r--engines/neverhood/mouse.h2
-rw-r--r--engines/neverhood/navigationscene.cpp47
-rw-r--r--engines/neverhood/navigationscene.h2
-rw-r--r--engines/neverhood/neverhood.cpp53
-rw-r--r--engines/neverhood/neverhood.h22
-rw-r--r--engines/neverhood/palette.cpp19
-rw-r--r--engines/neverhood/resource.cpp74
-rw-r--r--engines/neverhood/resource.h4
-rw-r--r--engines/neverhood/resourceman.cpp56
-rw-r--r--engines/neverhood/resourceman.h2
-rw-r--r--engines/neverhood/saveload.cpp29
-rw-r--r--engines/neverhood/scene.cpp97
-rw-r--r--engines/neverhood/scene.h62
-rw-r--r--engines/neverhood/screen.cpp61
-rw-r--r--engines/neverhood/screen.h1
-rw-r--r--engines/neverhood/smackerplayer.cpp56
-rw-r--r--engines/neverhood/smackerplayer.h3
-rw-r--r--engines/neverhood/smackerscene.cpp8
-rw-r--r--engines/neverhood/smackerscene.h1
-rw-r--r--engines/neverhood/sound.cpp89
-rw-r--r--engines/neverhood/sound.h36
-rw-r--r--engines/neverhood/sprite.cpp34
-rw-r--r--engines/neverhood/sprite.h27
-rw-r--r--engines/neverhood/staticdata.cpp26
-rw-r--r--engines/neverhood/todo.txt45
-rw-r--r--engines/parallaction/POTFILES1
-rw-r--r--engines/parallaction/configure.engine3
-rw-r--r--engines/parallaction/debug.cpp4
-rw-r--r--engines/parallaction/disk_br.cpp8
-rw-r--r--engines/parallaction/disk_ns.cpp6
-rw-r--r--engines/parallaction/exec.h2
-rw-r--r--engines/parallaction/exec_ns.cpp4
-rw-r--r--engines/parallaction/font.cpp3
-rw-r--r--engines/parallaction/graphics.cpp24
-rw-r--r--engines/parallaction/graphics.h4
-rw-r--r--engines/parallaction/gui.h2
-rw-r--r--engines/parallaction/gui_br.cpp5
-rw-r--r--engines/parallaction/gui_ns.cpp3
-rw-r--r--engines/parallaction/input.cpp2
-rw-r--r--engines/parallaction/input.h2
-rw-r--r--engines/parallaction/inventory.h2
-rw-r--r--engines/parallaction/objects.h6
-rw-r--r--engines/parallaction/parallaction.cpp30
-rw-r--r--engines/parallaction/parallaction.h4
-rw-r--r--engines/parallaction/parallaction_br.cpp12
-rw-r--r--engines/parallaction/parallaction_ns.cpp12
-rw-r--r--engines/parallaction/parser.h11
-rw-r--r--engines/parallaction/sound.h6
-rw-r--r--engines/parallaction/sound_br.cpp1
-rw-r--r--engines/parallaction/sound_ns.cpp1
-rw-r--r--engines/pegasus/POTFILES1
-rw-r--r--engines/pegasus/configure.engine3
-rw-r--r--engines/pegasus/cursor.cpp6
-rw-r--r--engines/pegasus/graphics.cpp2
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria.cpp4
-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/delta/globegame.cpp10
-rw-r--r--engines/pegasus/neighborhood/norad/delta/noraddelta.cpp5
-rw-r--r--engines/pegasus/neighborhood/norad/norad.cpp4
-rw-r--r--engines/pegasus/neighborhood/tsa/fulltsa.cpp1
-rw-r--r--engines/pegasus/neighborhood/tsa/tinytsa.cpp1
-rw-r--r--engines/pegasus/neighborhood/wsc/wsc.cpp13
-rw-r--r--engines/pegasus/pegasus.cpp10
-rw-r--r--engines/pegasus/timers.cpp5
-rw-r--r--engines/pegasus/transition.cpp2
-rw-r--r--engines/plugins_table.h121
-rw-r--r--engines/queen/POTFILES1
-rw-r--r--engines/queen/configure.engine3
-rw-r--r--engines/saga/animation.cpp4
-rw-r--r--engines/saga/configure.engine5
-rw-r--r--engines/saga/events.cpp3
-rw-r--r--engines/saga/gfx.h2
-rw-r--r--engines/saga/introproc_ihnm.cpp8
-rw-r--r--engines/saga/introproc_ite.cpp4
-rw-r--r--engines/saga/introproc_saga2.cpp2
-rw-r--r--engines/saga/music.cpp2
-rw-r--r--engines/saga/saga.h2
-rw-r--r--engines/saga/scene.cpp6
-rw-r--r--engines/saga/shorten.cpp2
-rw-r--r--engines/saga/sndres.cpp6
-rw-r--r--engines/saga/sprite.cpp28
-rw-r--r--engines/sci/POTFILES2
-rw-r--r--engines/sci/configure.engine4
-rw-r--r--engines/sci/console.cpp13
-rw-r--r--engines/sci/detection.cpp5
-rw-r--r--engines/sci/detection_tables.h834
-rw-r--r--engines/sci/engine/features.cpp6
-rw-r--r--engines/sci/engine/kernel.cpp12
-rw-r--r--engines/sci/engine/kernel.h4
-rw-r--r--engines/sci/engine/kernel_tables.h2
-rw-r--r--engines/sci/engine/kfile.cpp2
-rw-r--r--engines/sci/engine/kpathing.cpp2
-rw-r--r--engines/sci/engine/kstring.cpp2
-rw-r--r--engines/sci/engine/kvideo.cpp4
-rw-r--r--engines/sci/engine/savegame.cpp7
-rw-r--r--engines/sci/engine/savegame.h3
-rw-r--r--engines/sci/engine/script.cpp2
-rw-r--r--engines/sci/engine/script.h10
-rw-r--r--engines/sci/engine/script_patches.cpp2686
-rw-r--r--engines/sci/engine/seg_manager.cpp10
-rw-r--r--engines/sci/engine/seg_manager.h2
-rw-r--r--engines/sci/engine/vm.cpp17
-rw-r--r--engines/sci/engine/vm_types.cpp32
-rw-r--r--engines/sci/engine/vm_types.h2
-rw-r--r--engines/sci/engine/workarounds.cpp33
-rw-r--r--engines/sci/engine/workarounds.h1
-rw-r--r--engines/sci/graphics/frameout.cpp12
-rw-r--r--engines/sci/graphics/maciconbar.cpp6
-rw-r--r--engines/sci/graphics/picture.cpp17
-rw-r--r--engines/sci/graphics/ports.cpp4
-rw-r--r--engines/sci/graphics/screen.cpp18
-rw-r--r--engines/sci/resource.h2
-rw-r--r--engines/sci/sci.cpp73
-rw-r--r--engines/sci/sci.h50
-rw-r--r--engines/sci/sound/midiparser_sci.cpp286
-rw-r--r--engines/sci/sound/midiparser_sci.h5
-rw-r--r--engines/sci/sound/music.cpp3
-rw-r--r--engines/sci/sound/music.h2
-rw-r--r--engines/sci/sound/soundcmd.cpp43
-rw-r--r--engines/sci/video/robot_decoder.cpp2
-rw-r--r--engines/sci/video/seq_decoder.cpp4
-rw-r--r--engines/scumm/POTFILES3
-rw-r--r--engines/scumm/actor.cpp2
-rw-r--r--engines/scumm/akos.cpp6
-rw-r--r--engines/scumm/base-costume.cpp8
-rw-r--r--engines/scumm/bomp.cpp5
-rw-r--r--engines/scumm/charset.cpp10
-rw-r--r--engines/scumm/configure.engine5
-rw-r--r--engines/scumm/costume.cpp6
-rw-r--r--engines/scumm/cursor.cpp10
-rw-r--r--engines/scumm/debugger.cpp2
-rw-r--r--engines/scumm/detection.cpp26
-rw-r--r--engines/scumm/detection_tables.h11
-rw-r--r--engines/scumm/gfx.cpp29
-rw-r--r--engines/scumm/gfx_towns.cpp2
-rw-r--r--engines/scumm/he/animation_he.cpp4
-rw-r--r--engines/scumm/he/intern_he.h1
-rw-r--r--engines/scumm/he/logic/moonbase.cpp2
-rw-r--r--engines/scumm/he/script_v100he.cpp2
-rw-r--r--engines/scumm/he/script_v70he.cpp2
-rw-r--r--engines/scumm/he/script_v72he.cpp7
-rw-r--r--engines/scumm/he/script_v80he.cpp6
-rw-r--r--engines/scumm/imuse/imuse.cpp54
-rw-r--r--engines/scumm/imuse/imuse_internal.h1
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp5
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp13
-rw-r--r--engines/scumm/input.cpp2
-rw-r--r--engines/scumm/insane/insane_enemy.cpp4
-rw-r--r--engines/scumm/module.mk33
-rw-r--r--engines/scumm/nut_renderer.cpp10
-rw-r--r--engines/scumm/object.cpp2
-rw-r--r--engines/scumm/players/player_ad.cpp959
-rw-r--r--engines/scumm/players/player_ad.h190
-rw-r--r--engines/scumm/players/player_apple2.cpp (renamed from engines/scumm/player_apple2.cpp)2
-rw-r--r--engines/scumm/players/player_apple2.h (renamed from engines/scumm/player_apple2.h)4
-rw-r--r--engines/scumm/players/player_mac.cpp (renamed from engines/scumm/player_mac.cpp)12
-rw-r--r--engines/scumm/players/player_mac.h (renamed from engines/scumm/player_mac.h)4
-rw-r--r--engines/scumm/players/player_mod.cpp (renamed from engines/scumm/player_mod.cpp)2
-rw-r--r--engines/scumm/players/player_mod.h (renamed from engines/scumm/player_mod.h)4
-rw-r--r--engines/scumm/players/player_nes.cpp (renamed from engines/scumm/player_nes.cpp)2
-rw-r--r--engines/scumm/players/player_nes.h (renamed from engines/scumm/player_nes.h)4
-rw-r--r--engines/scumm/players/player_pce.cpp (renamed from engines/scumm/player_pce.cpp)2
-rw-r--r--engines/scumm/players/player_pce.h (renamed from engines/scumm/player_pce.h)4
-rw-r--r--engines/scumm/players/player_sid.cpp (renamed from engines/scumm/player_sid.cpp)2
-rw-r--r--engines/scumm/players/player_sid.h (renamed from engines/scumm/player_sid.h)4
-rw-r--r--engines/scumm/players/player_towns.cpp (renamed from engines/scumm/player_towns.cpp)2
-rw-r--r--engines/scumm/players/player_towns.h (renamed from engines/scumm/player_towns.h)4
-rw-r--r--engines/scumm/players/player_v1.cpp (renamed from engines/scumm/player_v1.cpp)2
-rw-r--r--engines/scumm/players/player_v1.h (renamed from engines/scumm/player_v1.h)6
-rw-r--r--engines/scumm/players/player_v2.cpp (renamed from engines/scumm/player_v2.cpp)2
-rw-r--r--engines/scumm/players/player_v2.h (renamed from engines/scumm/player_v2.h)6
-rw-r--r--engines/scumm/players/player_v2a.cpp (renamed from engines/scumm/player_v2a.cpp)2
-rw-r--r--engines/scumm/players/player_v2a.h (renamed from engines/scumm/player_v2a.h)6
-rw-r--r--engines/scumm/players/player_v2base.cpp (renamed from engines/scumm/player_v2base.cpp)2
-rw-r--r--engines/scumm/players/player_v2base.h (renamed from engines/scumm/player_v2base.h)4
-rw-r--r--engines/scumm/players/player_v2cms.cpp (renamed from engines/scumm/player_v2cms.cpp)2
-rw-r--r--engines/scumm/players/player_v2cms.h (renamed from engines/scumm/player_v2cms.h)6
-rw-r--r--engines/scumm/players/player_v3a.cpp (renamed from engines/scumm/player_v3a.cpp)2
-rw-r--r--engines/scumm/players/player_v3a.h (renamed from engines/scumm/player_v3a.h)6
-rw-r--r--engines/scumm/players/player_v3m.cpp (renamed from engines/scumm/player_v3m.cpp)4
-rw-r--r--engines/scumm/players/player_v3m.h (renamed from engines/scumm/player_v3m.h)6
-rw-r--r--engines/scumm/players/player_v4a.cpp (renamed from engines/scumm/player_v4a.cpp)2
-rw-r--r--engines/scumm/players/player_v4a.h (renamed from engines/scumm/player_v4a.h)4
-rw-r--r--engines/scumm/players/player_v5m.cpp (renamed from engines/scumm/player_v5m.cpp)2
-rw-r--r--engines/scumm/players/player_v5m.h (renamed from engines/scumm/player_v5m.h)6
-rw-r--r--engines/scumm/saveload.cpp101
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script_v5.cpp2
-rw-r--r--engines/scumm/script_v6.cpp2
-rw-r--r--engines/scumm/scumm-md5.h11
-rw-r--r--engines/scumm/scumm.cpp36
-rw-r--r--engines/scumm/scumm.h10
-rw-r--r--engines/scumm/sound.cpp26
-rw-r--r--engines/scumm/vars.cpp6
-rw-r--r--engines/sky/POTFILES2
-rw-r--r--engines/sky/configure.engine3
-rw-r--r--engines/sky/music/musicbase.cpp5
-rw-r--r--engines/sky/sky.cpp7
-rw-r--r--engines/sword1/POTFILES4
-rw-r--r--engines/sword1/animation.cpp62
-rw-r--r--engines/sword1/animation.h3
-rw-r--r--engines/sword1/configure.engine3
-rw-r--r--engines/sword1/music.cpp6
-rw-r--r--engines/sword1/music.h2
-rw-r--r--engines/sword1/screen.cpp24
-rw-r--r--engines/sword1/sound.cpp3
-rw-r--r--engines/sword1/sword1.cpp11
-rw-r--r--engines/sword2/POTFILES2
-rw-r--r--engines/sword2/animation.cpp59
-rw-r--r--engines/sword2/animation.h3
-rw-r--r--engines/sword2/configure.engine3
-rw-r--r--engines/sword25/configure.engine3
-rw-r--r--engines/sword25/fmv/movieplayer.cpp4
-rw-r--r--engines/sword25/gfx/animation.cpp20
-rw-r--r--engines/sword25/gfx/animation.h12
-rw-r--r--engines/sword25/gfx/animationdescription.cpp4
-rw-r--r--engines/sword25/gfx/animationdescription.h8
-rw-r--r--engines/sword25/gfx/animationresource.cpp2
-rw-r--r--engines/sword25/gfx/animationtemplate.cpp4
-rw-r--r--engines/sword25/gfx/animationtemplateregistry.cpp6
-rw-r--r--engines/sword25/gfx/bitmap.h6
-rw-r--r--engines/sword25/gfx/dynamicbitmap.cpp4
-rw-r--r--engines/sword25/gfx/image/art.cpp3
-rw-r--r--engines/sword25/gfx/image/image.h2
-rw-r--r--engines/sword25/gfx/image/imgloader.cpp2
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp143
-rw-r--r--engines/sword25/gfx/image/renderedimage.h3
-rw-r--r--engines/sword25/gfx/microtiles.cpp3
-rw-r--r--engines/sword25/gfx/panel.cpp4
-rw-r--r--engines/sword25/gfx/panel.h2
-rw-r--r--engines/sword25/gfx/renderobject.cpp40
-rw-r--r--engines/sword25/gfx/renderobject.h52
-rw-r--r--engines/sword25/gfx/renderobjectmanager.cpp31
-rw-r--r--engines/sword25/gfx/screenshot.cpp4
-rw-r--r--engines/sword25/gfx/staticbitmap.cpp2
-rw-r--r--engines/sword25/gfx/text.cpp12
-rw-r--r--engines/sword25/gfx/text.h10
-rw-r--r--engines/sword25/input/inputengine.cpp8
-rw-r--r--engines/sword25/kernel/inputpersistenceblock.cpp10
-rw-r--r--engines/sword25/kernel/inputpersistenceblock.h4
-rw-r--r--engines/sword25/kernel/objectregistry.h6
-rw-r--r--engines/sword25/kernel/outputpersistenceblock.cpp8
-rw-r--r--engines/sword25/kernel/outputpersistenceblock.h4
-rw-r--r--engines/sword25/kernel/persistenceservice.cpp2
-rw-r--r--engines/sword25/math/polygon.cpp8
-rw-r--r--engines/sword25/math/polygon.h2
-rw-r--r--engines/sword25/math/region.cpp20
-rw-r--r--engines/sword25/math/regionregistry.cpp6
-rw-r--r--engines/sword25/math/walkregion.cpp22
-rw-r--r--engines/sword25/sfx/soundengine.cpp15
-rw-r--r--engines/sword25/sfx/soundengine.h8
-rw-r--r--engines/sword25/util/lua/lcode.cpp2
-rw-r--r--engines/sword25/util/lua/ldebug.cpp5
-rw-r--r--engines/sword25/util/lua/lfunc.cpp2
-rw-r--r--engines/sword25/util/lua/lgc.cpp2
-rw-r--r--engines/sword25/util/lua/llimits.h3
-rw-r--r--engines/sword25/util/lua/lmem.cpp2
-rw-r--r--engines/sword25/util/lua/lopcodes.cpp3
-rw-r--r--engines/sword25/util/lua/lparser.cpp2
-rw-r--r--engines/sword25/util/lua/lstate.cpp2
-rw-r--r--engines/sword25/util/lua/lstring.cpp2
-rw-r--r--engines/sword25/util/lua/lstrlib.cpp6
-rw-r--r--engines/sword25/util/lua/ltablib.cpp2
-rw-r--r--engines/sword25/util/lua/lua.h2
-rw-r--r--engines/sword25/util/pluto/pluto.cpp539
-rw-r--r--engines/teenagent/POTFILES1
-rw-r--r--engines/teenagent/callbacks.cpp6
-rw-r--r--engines/teenagent/configure.engine3
-rw-r--r--engines/teenagent/dialog.cpp2
-rw-r--r--engines/teenagent/font.cpp2
-rw-r--r--engines/teenagent/resources.cpp5
-rw-r--r--engines/teenagent/scene.cpp12
-rw-r--r--engines/teenagent/teenagent.cpp2
-rw-r--r--engines/testbed/config-params.cpp2
-rw-r--r--engines/testbed/config.cpp8
-rw-r--r--engines/testbed/config.h6
-rw-r--r--engines/testbed/configure.engine3
-rw-r--r--engines/testbed/events.cpp5
-rw-r--r--engines/testbed/graphics.cpp22
-rw-r--r--engines/testbed/midi.cpp2
-rw-r--r--engines/tinsel/POTFILES1
-rw-r--r--engines/tinsel/bmv.cpp2
-rw-r--r--engines/tinsel/configure.engine3
-rw-r--r--engines/tinsel/detection.cpp2
-rw-r--r--engines/tinsel/detection_tables.h43
-rw-r--r--engines/tinsel/graphics.cpp2
-rw-r--r--engines/tinsel/handle.cpp2
-rw-r--r--engines/tinsel/music.cpp35
-rw-r--r--engines/tinsel/rince.cpp3
-rw-r--r--engines/tinsel/scene.cpp20
-rw-r--r--engines/tinsel/sound.cpp10
-rw-r--r--engines/tinsel/tinsel.cpp6
-rw-r--r--engines/tinsel/tinsel.h8
-rw-r--r--engines/toltecs/POTFILES2
-rw-r--r--engines/toltecs/configure.engine3
-rw-r--r--engines/toltecs/detection.cpp14
-rw-r--r--engines/toltecs/menu.cpp4
-rw-r--r--engines/toltecs/render.cpp2
-rw-r--r--engines/toltecs/saveload.cpp2
-rw-r--r--engines/toltecs/screen.cpp6
-rw-r--r--engines/toltecs/script.cpp10
-rw-r--r--engines/toltecs/segmap.cpp2
-rw-r--r--engines/toltecs/toltecs.cpp8
-rw-r--r--engines/tony/configure.engine3
-rw-r--r--engines/tony/detection.cpp29
-rw-r--r--engines/tony/detection_tables.h34
-rw-r--r--engines/tony/game.cpp3
-rw-r--r--engines/tony/gfxcore.cpp3
-rw-r--r--engines/tony/gfxcore.h6
-rw-r--r--engines/tony/gfxengine.cpp9
-rw-r--r--engines/tony/mpal/mpal.cpp38
-rw-r--r--engines/tony/mpal/mpal.h2
-rw-r--r--engines/tony/sound.cpp6
-rw-r--r--engines/tony/window.cpp8
-rw-r--r--engines/toon/anim.cpp14
-rw-r--r--engines/toon/audio.cpp3
-rw-r--r--engines/toon/character.cpp10
-rw-r--r--engines/toon/character.h1
-rw-r--r--engines/toon/configure.engine3
-rw-r--r--engines/toon/font.cpp5
-rw-r--r--engines/toon/movie.cpp11
-rw-r--r--engines/toon/movie.h3
-rw-r--r--engines/toon/path.cpp2
-rw-r--r--engines/toon/picture.cpp11
-rw-r--r--engines/toon/resource.cpp1
-rw-r--r--engines/toon/resource.h1
-rw-r--r--engines/toon/script.cpp5
-rw-r--r--engines/toon/script_func.cpp6
-rw-r--r--engines/toon/state.cpp4
-rw-r--r--engines/toon/tools.cpp7
-rw-r--r--engines/toon/toon.cpp54
-rw-r--r--engines/touche/configure.engine3
-rw-r--r--engines/touche/touche.cpp79
-rw-r--r--engines/touche/touche.h2
-rw-r--r--engines/tsage/blue_force/blueforce_logic.cpp42
-rw-r--r--engines/tsage/blue_force/blueforce_logic.h18
-rw-r--r--engines/tsage/blue_force/blueforce_scenes0.cpp12
-rw-r--r--engines/tsage/blue_force/blueforce_scenes0.h2
-rw-r--r--engines/tsage/blue_force/blueforce_scenes1.cpp22
-rw-r--r--engines/tsage/blue_force/blueforce_scenes2.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.cpp91
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.h6
-rw-r--r--engines/tsage/blue_force/blueforce_scenes4.cpp122
-rw-r--r--engines/tsage/blue_force/blueforce_scenes4.h12
-rw-r--r--engines/tsage/blue_force/blueforce_scenes5.cpp41
-rw-r--r--engines/tsage/blue_force/blueforce_scenes5.h6
-rw-r--r--engines/tsage/blue_force/blueforce_scenes6.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_scenes7.cpp2
-rw-r--r--engines/tsage/blue_force/blueforce_scenes8.cpp32
-rw-r--r--engines/tsage/blue_force/blueforce_scenes8.h3
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.cpp69
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.h1
-rw-r--r--engines/tsage/blue_force/blueforce_speakers.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_speakers.h2
-rw-r--r--engines/tsage/configure.engine3
-rw-r--r--engines/tsage/converse.cpp202
-rw-r--r--engines/tsage/converse.h14
-rw-r--r--engines/tsage/core.cpp280
-rw-r--r--engines/tsage/core.h26
-rw-r--r--engines/tsage/debugger.cpp98
-rw-r--r--engines/tsage/detection.cpp1
-rw-r--r--engines/tsage/detection_tables.h2
-rw-r--r--engines/tsage/dialogs.cpp78
-rw-r--r--engines/tsage/events.cpp17
-rw-r--r--engines/tsage/events.h1
-rw-r--r--engines/tsage/globals.cpp425
-rw-r--r--engines/tsage/globals.h116
-rw-r--r--engines/tsage/graphics.cpp192
-rw-r--r--engines/tsage/graphics.h9
-rw-r--r--engines/tsage/ringworld/ringworld_logic.cpp5
-rw-r--r--engines/tsage/ringworld/ringworld_scenes1.cpp691
-rw-r--r--engines/tsage/ringworld/ringworld_scenes1.h82
-rw-r--r--engines/tsage/ringworld/ringworld_scenes10.cpp2
-rw-r--r--engines/tsage/ringworld/ringworld_scenes5.cpp3
-rw-r--r--engines/tsage/ringworld/ringworld_scenes5.h1
-rw-r--r--engines/tsage/ringworld/ringworld_scenes6.cpp11
-rw-r--r--engines/tsage/ringworld/ringworld_scenes6.h6
-rw-r--r--engines/tsage/ringworld/ringworld_scenes8.cpp8
-rw-r--r--engines/tsage/ringworld/ringworld_scenes8.h2
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.cpp39
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.h3
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp1438
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.h285
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp3044
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.h293
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp10364
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.h836
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.cpp3169
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.h481
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp4983
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.h587
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.cpp977
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.h179
-rw-r--r--engines/tsage/saveload.cpp11
-rw-r--r--engines/tsage/saveload.h17
-rw-r--r--engines/tsage/scenes.cpp21
-rw-r--r--engines/tsage/sound.cpp254
-rw-r--r--engines/tsage/sound.h48
-rw-r--r--engines/tsage/staticres.cpp210
-rw-r--r--engines/tsage/staticres.h21
-rw-r--r--engines/tsage/tsage.cpp5
-rw-r--r--engines/tsage/user_interface.cpp44
-rw-r--r--engines/tsage/user_interface.h4
-rw-r--r--engines/tucker/configure.engine3
-rw-r--r--engines/tucker/sequences.cpp4
-rw-r--r--engines/tucker/tucker.cpp13
-rw-r--r--engines/voyeur/animation.cpp10
-rw-r--r--engines/voyeur/configure.engine3
-rw-r--r--engines/voyeur/events.cpp2
-rw-r--r--engines/voyeur/graphics.cpp8
-rw-r--r--engines/voyeur/voyeur.cpp8
-rw-r--r--engines/wintermute/ad/ad_actor.cpp86
-rw-r--r--engines/wintermute/ad/ad_actor.h6
-rw-r--r--engines/wintermute/ad/ad_entity.cpp88
-rw-r--r--engines/wintermute/ad/ad_entity.h6
-rw-r--r--engines/wintermute/ad/ad_game.cpp66
-rw-r--r--engines/wintermute/ad/ad_game.h6
-rw-r--r--engines/wintermute/ad/ad_inventory.cpp4
-rw-r--r--engines/wintermute/ad/ad_inventory.h2
-rw-r--r--engines/wintermute/ad/ad_inventory_box.cpp58
-rw-r--r--engines/wintermute/ad/ad_inventory_box.h4
-rw-r--r--engines/wintermute/ad/ad_item.cpp70
-rw-r--r--engines/wintermute/ad/ad_item.h6
-rw-r--r--engines/wintermute/ad/ad_layer.cpp42
-rw-r--r--engines/wintermute/ad/ad_layer.h4
-rw-r--r--engines/wintermute/ad/ad_node_state.cpp14
-rw-r--r--engines/wintermute/ad/ad_node_state.h2
-rw-r--r--engines/wintermute/ad/ad_object.cpp38
-rw-r--r--engines/wintermute/ad/ad_object.h4
-rw-r--r--engines/wintermute/ad/ad_path.cpp6
-rw-r--r--engines/wintermute/ad/ad_path.h2
-rw-r--r--engines/wintermute/ad/ad_path_point.cpp6
-rw-r--r--engines/wintermute/ad/ad_path_point.h2
-rw-r--r--engines/wintermute/ad/ad_region.cpp46
-rw-r--r--engines/wintermute/ad/ad_region.h4
-rw-r--r--engines/wintermute/ad/ad_response.cpp12
-rw-r--r--engines/wintermute/ad/ad_response.h2
-rw-r--r--engines/wintermute/ad/ad_response_box.cpp124
-rw-r--r--engines/wintermute/ad/ad_response_box.h4
-rw-r--r--engines/wintermute/ad/ad_response_context.cpp6
-rw-r--r--engines/wintermute/ad/ad_response_context.h2
-rw-r--r--engines/wintermute/ad/ad_rot_level.cpp20
-rw-r--r--engines/wintermute/ad/ad_rot_level.h4
-rw-r--r--engines/wintermute/ad/ad_scale_level.cpp20
-rw-r--r--engines/wintermute/ad/ad_scale_level.h4
-rw-r--r--engines/wintermute/ad/ad_scene.cpp151
-rw-r--r--engines/wintermute/ad/ad_scene.h4
-rw-r--r--engines/wintermute/ad/ad_scene_node.cpp4
-rw-r--r--engines/wintermute/ad/ad_scene_state.cpp4
-rw-r--r--engines/wintermute/ad/ad_scene_state.h2
-rw-r--r--engines/wintermute/ad/ad_sentence.cpp28
-rw-r--r--engines/wintermute/ad/ad_sentence.h2
-rw-r--r--engines/wintermute/ad/ad_sprite_set.cpp32
-rw-r--r--engines/wintermute/ad/ad_sprite_set.h4
-rw-r--r--engines/wintermute/ad/ad_talk_def.cpp22
-rw-r--r--engines/wintermute/ad/ad_talk_def.h4
-rw-r--r--engines/wintermute/ad/ad_talk_holder.cpp2
-rw-r--r--engines/wintermute/ad/ad_talk_holder.h2
-rw-r--r--engines/wintermute/ad/ad_talk_node.cpp34
-rw-r--r--engines/wintermute/ad/ad_talk_node.h4
-rw-r--r--engines/wintermute/ad/ad_types.h2
-rw-r--r--engines/wintermute/ad/ad_waypoint_group.cpp32
-rw-r--r--engines/wintermute/ad/ad_waypoint_group.h4
-rw-r--r--engines/wintermute/base/base.cpp20
-rw-r--r--engines/wintermute/base/base.h6
-rw-r--r--engines/wintermute/base/base_active_rect.cpp6
-rw-r--r--engines/wintermute/base/base_active_rect.h2
-rw-r--r--engines/wintermute/base/base_dynamic_buffer.cpp2
-rw-r--r--engines/wintermute/base/base_dynamic_buffer.h2
-rw-r--r--engines/wintermute/base/base_engine.cpp15
-rw-r--r--engines/wintermute/base/base_engine.h12
-rw-r--r--engines/wintermute/base/base_fader.cpp22
-rw-r--r--engines/wintermute/base/base_fader.h2
-rw-r--r--engines/wintermute/base/base_file_manager.cpp85
-rw-r--r--engines/wintermute/base/base_file_manager.h2
-rw-r--r--engines/wintermute/base/base_frame.cpp28
-rw-r--r--engines/wintermute/base/base_frame.h4
-rw-r--r--engines/wintermute/base/base_game.cpp182
-rw-r--r--engines/wintermute/base/base_game.h18
-rw-r--r--engines/wintermute/base/base_game_music.cpp124
-rw-r--r--engines/wintermute/base/base_game_music.h8
-rw-r--r--engines/wintermute/base/base_game_settings.cpp92
-rw-r--r--engines/wintermute/base/base_game_settings.h6
-rw-r--r--engines/wintermute/base/base_keyboard_state.cpp28
-rw-r--r--engines/wintermute/base/base_keyboard_state.h4
-rw-r--r--engines/wintermute/base/base_named_object.cpp2
-rw-r--r--engines/wintermute/base/base_named_object.h2
-rw-r--r--engines/wintermute/base/base_object.cpp80
-rw-r--r--engines/wintermute/base/base_object.h4
-rw-r--r--engines/wintermute/base/base_parser.cpp6
-rw-r--r--engines/wintermute/base/base_parser.h2
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp128
-rw-r--r--engines/wintermute/base/base_persistence_manager.h29
-rw-r--r--engines/wintermute/base/base_point.cpp6
-rw-r--r--engines/wintermute/base/base_point.h2
-rw-r--r--engines/wintermute/base/base_quick_msg.cpp12
-rw-r--r--engines/wintermute/base/base_quick_msg.h10
-rw-r--r--engines/wintermute/base/base_region.cpp44
-rw-r--r--engines/wintermute/base/base_region.h4
-rw-r--r--engines/wintermute/base/base_script_holder.cpp26
-rw-r--r--engines/wintermute/base/base_script_holder.h4
-rw-r--r--engines/wintermute/base/base_scriptable.cpp4
-rw-r--r--engines/wintermute/base/base_scriptable.h2
-rw-r--r--engines/wintermute/base/base_sprite.cpp78
-rw-r--r--engines/wintermute/base/base_sprite.h13
-rw-r--r--engines/wintermute/base/base_string_table.cpp2
-rw-r--r--engines/wintermute/base/base_string_table.h2
-rw-r--r--engines/wintermute/base/base_sub_frame.cpp106
-rw-r--r--engines/wintermute/base/base_sub_frame.h4
-rw-r--r--engines/wintermute/base/base_surface_storage.cpp2
-rw-r--r--engines/wintermute/base/base_surface_storage.h2
-rw-r--r--engines/wintermute/base/base_transition_manager.cpp2
-rw-r--r--engines/wintermute/base/base_transition_manager.h2
-rw-r--r--engines/wintermute/base/base_viewport.cpp13
-rw-r--r--engines/wintermute/base/base_viewport.h2
-rw-r--r--engines/wintermute/base/file/base_disk_file.cpp15
-rw-r--r--engines/wintermute/base/file/base_disk_file.h2
-rw-r--r--engines/wintermute/base/file/base_file.cpp2
-rw-r--r--engines/wintermute/base/file/base_file.h2
-rw-r--r--engines/wintermute/base/file/base_file_entry.cpp2
-rw-r--r--engines/wintermute/base/file/base_file_entry.h2
-rw-r--r--engines/wintermute/base/file/base_package.cpp2
-rw-r--r--engines/wintermute/base/file/base_package.h2
-rw-r--r--engines/wintermute/base/file/base_save_thumb_file.cpp2
-rw-r--r--engines/wintermute/base/file/base_save_thumb_file.h2
-rw-r--r--engines/wintermute/base/file/dcpackage.h2
-rw-r--r--engines/wintermute/base/font/base_font.cpp8
-rw-r--r--engines/wintermute/base/font/base_font.h2
-rw-r--r--engines/wintermute/base/font/base_font_bitmap.cpp33
-rw-r--r--engines/wintermute/base/font/base_font_bitmap.h4
-rw-r--r--engines/wintermute/base/font/base_font_storage.cpp2
-rw-r--r--engines/wintermute/base/font/base_font_storage.h2
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp103
-rw-r--r--engines/wintermute/base/font/base_font_truetype.h17
-rw-r--r--engines/wintermute/base/gfx/base_image.cpp2
-rw-r--r--engines/wintermute/base/gfx/base_image.h2
-rw-r--r--engines/wintermute/base/gfx/base_renderer.cpp32
-rw-r--r--engines/wintermute/base/gfx/base_renderer.h4
-rw-r--r--engines/wintermute/base/gfx/base_surface.cpp6
-rw-r--r--engines/wintermute/base/gfx/base_surface.h7
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp314
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h60
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp193
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.h21
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.cpp136
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.h41
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp95
-rw-r--r--engines/wintermute/base/particles/part_emitter.h2
-rw-r--r--engines/wintermute/base/particles/part_force.cpp12
-rw-r--r--engines/wintermute/base/particles/part_force.h2
-rw-r--r--engines/wintermute/base/particles/part_particle.cpp48
-rw-r--r--engines/wintermute/base/particles/part_particle.h2
-rw-r--r--engines/wintermute/base/save_thumb_helper.cpp14
-rw-r--r--engines/wintermute/base/save_thumb_helper.h2
-rw-r--r--engines/wintermute/base/saveload.cpp2
-rw-r--r--engines/wintermute/base/saveload.h2
-rw-r--r--engines/wintermute/base/scriptables/dcscript.h2
-rw-r--r--engines/wintermute/base/scriptables/script.cpp37
-rw-r--r--engines/wintermute/base/scriptables/script.h2
-rw-r--r--engines/wintermute/base/scriptables/script_engine.cpp11
-rw-r--r--engines/wintermute/base/scriptables/script_engine.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.cpp4
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.cpp16
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.cpp12
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.cpp3
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp4
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_object.cpp2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_object.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.cpp22
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.h2
-rw-r--r--engines/wintermute/base/scriptables/script_stack.cpp4
-rw-r--r--engines/wintermute/base/scriptables/script_stack.h2
-rw-r--r--engines/wintermute/base/scriptables/script_value.cpp35
-rw-r--r--engines/wintermute/base/scriptables/script_value.h2
-rw-r--r--engines/wintermute/base/sound/base_sound.cpp22
-rw-r--r--engines/wintermute/base/sound/base_sound.h2
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp2
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.h2
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.cpp2
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.h2
-rw-r--r--engines/wintermute/base/timer.cpp10
-rw-r--r--engines/wintermute/base/timer.h6
-rw-r--r--engines/wintermute/coll_templ.h22
-rw-r--r--engines/wintermute/configure.engine3
-rw-r--r--engines/wintermute/dcgf.h2
-rw-r--r--engines/wintermute/dctypes.h5
-rw-r--r--engines/wintermute/debugger.cpp6
-rw-r--r--engines/wintermute/debugger.h6
-rw-r--r--engines/wintermute/detection.cpp3
-rw-r--r--engines/wintermute/detection_tables.h266
-rw-r--r--engines/wintermute/graphics/transform_struct.cpp119
-rw-r--r--engines/wintermute/graphics/transform_struct.h89
-rw-r--r--engines/wintermute/graphics/transform_tools.cpp87
-rw-r--r--engines/wintermute/graphics/transform_tools.h53
-rw-r--r--engines/wintermute/graphics/transparent_surface.cpp974
-rw-r--r--engines/wintermute/graphics/transparent_surface.h82
-rw-r--r--engines/wintermute/math/floatpoint.h52
-rw-r--r--engines/wintermute/math/math_util.cpp4
-rw-r--r--engines/wintermute/math/math_util.h2
-rw-r--r--engines/wintermute/math/matrix4.cpp4
-rw-r--r--engines/wintermute/math/matrix4.h2
-rw-r--r--engines/wintermute/math/rect32.h41
-rw-r--r--engines/wintermute/math/vector2.cpp4
-rw-r--r--engines/wintermute/math/vector2.h2
-rw-r--r--engines/wintermute/module.mk2
-rw-r--r--engines/wintermute/persistent.h4
-rw-r--r--engines/wintermute/platform_osystem.cpp59
-rw-r--r--engines/wintermute/platform_osystem.h8
-rw-r--r--engines/wintermute/system/sys_class.cpp2
-rw-r--r--engines/wintermute/system/sys_class.h2
-rw-r--r--engines/wintermute/system/sys_class_registry.cpp2
-rw-r--r--engines/wintermute/system/sys_class_registry.h2
-rw-r--r--engines/wintermute/system/sys_instance.cpp2
-rw-r--r--engines/wintermute/system/sys_instance.h2
-rw-r--r--engines/wintermute/ui/ui_button.cpp120
-rw-r--r--engines/wintermute/ui/ui_button.h60
-rw-r--r--engines/wintermute/ui/ui_edit.cpp70
-rw-r--r--engines/wintermute/ui/ui_edit.h29
-rw-r--r--engines/wintermute/ui/ui_entity.cpp28
-rw-r--r--engines/wintermute/ui/ui_entity.h8
-rw-r--r--engines/wintermute/ui/ui_object.cpp102
-rw-r--r--engines/wintermute/ui/ui_object.h58
-rw-r--r--engines/wintermute/ui/ui_text.cpp56
-rw-r--r--engines/wintermute/ui/ui_text.h8
-rw-r--r--engines/wintermute/ui/ui_tiled_image.cpp155
-rw-r--r--engines/wintermute/ui/ui_tiled_image.h6
-rw-r--r--engines/wintermute/ui/ui_window.cpp144
-rw-r--r--engines/wintermute/ui/ui_window.h51
-rw-r--r--engines/wintermute/utils/crc.cpp2
-rw-r--r--engines/wintermute/utils/path_util.cpp2
-rw-r--r--engines/wintermute/utils/path_util.h2
-rw-r--r--engines/wintermute/utils/string_util.cpp211
-rw-r--r--engines/wintermute/utils/string_util.h5
-rw-r--r--engines/wintermute/utils/utils.cpp2
-rw-r--r--engines/wintermute/utils/utils.h2
-rw-r--r--engines/wintermute/video/video_player.cpp2
-rw-r--r--engines/wintermute/video/video_player.h2
-rw-r--r--engines/wintermute/video/video_theora_player.cpp35
-rw-r--r--engines/wintermute/video/video_theora_player.h8
-rw-r--r--engines/wintermute/wintermute.cpp10
-rw-r--r--engines/wintermute/wintypes.h2
-rw-r--r--engines/zvision/animation/rlf_animation.cpp331
-rw-r--r--engines/zvision/animation/rlf_animation.h163
-rw-r--r--engines/zvision/archives/zfs_archive.cpp157
-rw-r--r--engines/zvision/archives/zfs_archive.h126
-rw-r--r--engines/zvision/configure.engine3
-rw-r--r--engines/zvision/core/console.cpp218
-rw-r--r--engines/zvision/core/console.h55
-rw-r--r--engines/zvision/core/events.cpp186
-rw-r--r--engines/zvision/core/menu.h (renamed from backends/graphics/opengl/glerrorcheck.h)15
-rw-r--r--engines/zvision/core/save_manager.cpp206
-rw-r--r--engines/zvision/core/save_manager.h91
-rw-r--r--engines/zvision/cursors/cursor.cpp94
-rw-r--r--engines/zvision/cursors/cursor.h66
-rw-r--r--engines/zvision/cursors/cursor_manager.cpp152
-rw-r--r--engines/zvision/cursors/cursor_manager.h114
-rw-r--r--engines/zvision/detection.cpp272
-rw-r--r--engines/zvision/detection.h44
-rw-r--r--engines/zvision/fonts/truetype_font.cpp116
-rw-r--r--engines/zvision/fonts/truetype_font.h81
-rw-r--r--engines/zvision/graphics/render_manager.cpp526
-rw-r--r--engines/zvision/graphics/render_manager.h328
-rw-r--r--engines/zvision/graphics/render_table.cpp240
-rw-r--r--engines/zvision/graphics/render_table.h85
-rw-r--r--engines/zvision/inventory/inventory_manager.h28
-rw-r--r--engines/zvision/module.mk43
-rw-r--r--engines/zvision/scripting/actions.cpp401
-rw-r--r--engines/zvision/scripting/actions.h346
-rw-r--r--engines/zvision/scripting/control.cpp124
-rw-r--r--engines/zvision/scripting/control.h146
-rw-r--r--engines/zvision/scripting/controls/animation_control.cpp263
-rw-r--r--engines/zvision/scripting/controls/animation_control.h87
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp142
-rw-r--r--engines/zvision/scripting/controls/input_control.h60
-rw-r--r--engines/zvision/scripting/controls/lever_control.cpp402
-rw-r--r--engines/zvision/scripting/controls/lever_control.h127
-rw-r--r--engines/zvision/scripting/controls/push_toggle_control.cpp98
-rw-r--r--engines/zvision/scripting/controls/push_toggle_control.h67
-rw-r--r--engines/zvision/scripting/controls/timer_node.cpp73
-rw-r--r--engines/zvision/scripting/controls/timer_node.h55
-rw-r--r--engines/zvision/scripting/puzzle.h74
-rw-r--r--engines/zvision/scripting/scr_file_handling.cpp302
-rw-r--r--engines/zvision/scripting/script_manager.cpp444
-rw-r--r--engines/zvision/scripting/script_manager.h225
-rw-r--r--engines/zvision/sound/zork_raw.cpp217
-rw-r--r--engines/zvision/sound/zork_raw.h120
-rw-r--r--engines/zvision/strings/string_manager.cpp255
-rw-r--r--engines/zvision/strings/string_manager.h85
-rw-r--r--engines/zvision/subtitles/subtitles.h29
-rw-r--r--engines/zvision/utility/clock.cpp70
-rw-r--r--engines/zvision/utility/clock.h78
-rw-r--r--engines/zvision/utility/lzss_read_stream.cpp103
-rw-r--r--engines/zvision/utility/lzss_read_stream.h72
-rw-r--r--engines/zvision/utility/single_value_container.cpp348
-rw-r--r--engines/zvision/utility/single_value_container.h183
-rw-r--r--engines/zvision/utility/utility.cpp237
-rw-r--r--engines/zvision/utility/utility.h115
-rw-r--r--engines/zvision/video/video.cpp171
-rw-r--r--engines/zvision/video/zork_avi_decoder.cpp53
-rw-r--r--engines/zvision/video/zork_avi_decoder.h60
-rw-r--r--engines/zvision/zvision.cpp184
-rw-r--r--engines/zvision/zvision.h151
-rw-r--r--graphics/VectorRenderer.h18
-rw-r--r--graphics/VectorRendererSpec.cpp874
-rw-r--r--graphics/VectorRendererSpec.h26
-rw-r--r--graphics/cursorman.cpp8
-rw-r--r--graphics/cursorman.h6
-rw-r--r--graphics/decoders/bmp.cpp6
-rw-r--r--graphics/decoders/iff.cpp10
-rw-r--r--graphics/decoders/iff.h4
-rw-r--r--graphics/decoders/image_decoder.h6
-rw-r--r--graphics/decoders/jpeg.cpp861
-rw-r--r--graphics/decoders/jpeg.h124
-rw-r--r--graphics/decoders/pcx.cpp6
-rw-r--r--graphics/decoders/pict.cpp2
-rw-r--r--graphics/decoders/png.cpp14
-rw-r--r--graphics/decoders/tga.cpp6
-rw-r--r--graphics/decoders/tga.h1
-rw-r--r--graphics/font.cpp219
-rw-r--r--graphics/font.h10
-rw-r--r--graphics/fonts/bdf.cpp12
-rw-r--r--graphics/fonts/bdf.h6
-rw-r--r--graphics/fonts/ttf.cpp85
-rw-r--r--graphics/fonts/winfont.cpp6
-rw-r--r--graphics/fonts/winfont.h6
-rw-r--r--graphics/scaler/thumbnail_intern.cpp217
-rw-r--r--graphics/surface.cpp72
-rw-r--r--graphics/surface.h105
-rw-r--r--graphics/thumbnail.cpp118
-rw-r--r--graphics/thumbnail.h18
-rw-r--r--graphics/yuv_to_rgb.cpp18
-rw-r--r--graphics/yuv_to_rgb.h15
-rw-r--r--gui/EventRecorder.cpp680
-rw-r--r--gui/EventRecorder.h238
-rw-r--r--gui/ThemeEngine.cpp116
-rw-r--r--gui/ThemeEngine.h26
-rw-r--r--gui/about.cpp11
-rw-r--r--gui/browser.h1
-rw-r--r--gui/browser_osx.mm73
-rw-r--r--gui/chooser.cpp1
-rw-r--r--gui/console.cpp23
-rw-r--r--gui/console.h6
-rw-r--r--gui/credits.h52
-rw-r--r--gui/dialog.h3
-rw-r--r--gui/editrecorddialog.cpp87
-rw-r--r--gui/editrecorddialog.h56
-rw-r--r--gui/gui-manager.cpp155
-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/object.cpp2
-rw-r--r--gui/object.h7
-rw-r--r--gui/onscreendialog.cpp233
-rw-r--r--gui/onscreendialog.h66
-rw-r--r--gui/options.cpp2
-rw-r--r--gui/predictivedialog.cpp18
-rw-r--r--gui/recorderdialog.cpp298
-rw-r--r--gui/recorderdialog.h83
-rw-r--r--gui/saveload-dialog.cpp2
-rw-r--r--gui/themes/default.inc3282
-rw-r--r--gui/themes/scummclassic.zipbin104059 -> 113348 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 -> 1489429 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.stx50
-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
-rwxr-xr-xgui/themes/scummtheme.py17
-rw-r--r--gui/themes/translations.datbin439725 -> 441486 bytes
-rw-r--r--gui/widget.cpp10
-rw-r--r--gui/widgets/editable.cpp36
-rw-r--r--gui/widgets/editable.h5
-rw-r--r--gui/widgets/edittext.cpp16
-rw-r--r--gui/widgets/list.cpp5
-rw-r--r--po/POTFILES41
-rw-r--r--po/module.mk4
-rw-r--r--po/pl_PL.po134
-rw-r--r--ports.mk18
-rw-r--r--test/audio/raw.h1
-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.cpp589
-rw-r--r--video/avi_decoder.h65
-rw-r--r--video/codecs/cdtoons.cpp2
-rw-r--r--video/codecs/cinepak.cpp6
-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/codecs/msrle.cpp2
-rw-r--r--video/codecs/msvideo1.cpp2
-rw-r--r--video/codecs/qtrle.cpp12
-rw-r--r--video/codecs/rpza.cpp2
-rw-r--r--video/codecs/smc.cpp2
-rw-r--r--video/codecs/truemotion1.cpp5
-rw-r--r--video/codecs/truemotion1.h4
-rw-r--r--video/coktel_decoder.cpp59
-rw-r--r--video/dxa_decoder.cpp6
-rw-r--r--video/flic_decoder.cpp14
-rw-r--r--video/module.mk5
-rw-r--r--video/smk_decoder.cpp11
-rw-r--r--video/theora_decoder.cpp11
-rw-r--r--video/video_decoder.cpp53
-rw-r--r--video/video_decoder.h41
1497 files changed, 116789 insertions, 45455 deletions
diff --git a/.gitignore b/.gitignore
index 80adcb7551..469f22d11c 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
@@ -104,6 +105,9 @@ project.xcworkspace
/plugins
+/engines/plugins_table.h
+/engines/engines.mk
+
/test/runner
/test/runner.cpp
/test/*.dSYM
@@ -116,10 +120,14 @@ project.xcworkspace
/devtools/create_kyradat/create_kyradat
/devtools/create_lure/create_lure
/devtools/create_mads/create_mads
+/devtools/create_mortdat/create_mortdat
+/devtools/create_neverhood/create_neverhood
/devtools/create_project/create_project
/devtools/create_teenagent/create_teenagent
+/devtools/create_tony/create_tony
/devtools/create_toon/create_toon
/devtools/create_translations/create_translations
+/devtools/extract_mort/extract_mort
/devtools/qtable/qtable
/devtools/skycpt/skycpt
@@ -159,6 +167,12 @@ ipch/
#Ignore default Visual Studio build folders
[Dd]ebug/
[Rr]elease/
+[Dd]ebug32/
+[Rr]elease32/
+[Dd]ebug64/
+[Rr]elease64/
+LLVM32/
+LLVM64/
#Ignore Qt Creator project files
ScummVM.config
@@ -168,3 +182,6 @@ ScummVM.includes
#Ignore Komodo IDE/Edit project files
*.komodoproject
+
+#Ignore Mac DS_Store files
+.DS_Store
diff --git a/AUTHORS b/AUTHORS
index e6a25b5b76..947ce5568a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,9 +6,9 @@ ScummVM Team
PR Office
---------
- Arnaud Boutonne - Public Relations Officer, Project
- Administrator
- Eugene Sandulenko - Project Leader
+ Arnaud Boutonne - Public Relations Officer, Project
+ Administrator
+ Eugene Sandulenko - Project Leader
Core Team
---------
@@ -19,30 +19,30 @@ ScummVM Team
Retired Project Leaders
-----------------------
James Brown
- Vincent Hamm - ScummVM co-founder, Original Cruise/CinE
- author
+ Vincent Hamm - ScummVM co-founder, Original Cruise/CinE
+ author
Max Horn
- Ludvig Strigeus - Original ScummVM and SimonVM author
+ Ludvig Strigeus - Original ScummVM and SimonVM author
Engine Teams
------------
SCUMM:
Torbjorn Andersson
- James Brown - (retired)
- Jonathan Gray - (retired)
- Vincent Hamm - (retired)
- Max Horn - (retired)
+ James Brown - (retired)
+ Jonathan Gray - (retired)
+ Vincent Hamm - (retired)
+ Max Horn - (retired)
Travis Howell
- Pawel Kolodziejski - Codecs, iMUSE, Smush, etc.
- Gregory Montoir - (retired)
- Eugene Sandulenko - FT INSANE, MM NES, MM C64, game detection,
- Herc/CGA
- Ludvig Strigeus - (retired)
+ Pawel Kolodziejski - Codecs, iMUSE, Smush, etc.
+ Gregory Montoir - (retired)
+ Eugene Sandulenko - FT INSANE, MM NES, MM C64, game
+ detection, Herc/CGA
+ Ludvig Strigeus - (retired)
HE:
- Jonathan Gray - (retired)
+ Jonathan Gray - (retired)
Travis Howell
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
Eugene Sandulenko
AGI:
@@ -50,26 +50,30 @@ ScummVM Team
Matthew Hoops
Filippos Karapetis
Pawel Kolodziejski
- Walter van Niftrik - (retired)
+ Walter van Niftrik - (retired)
Kari Salminen
Eugene Sandulenko
- David Symonds - (retired)
+ David Symonds - (retired)
AGOS:
Torbjorn Andersson
Paul Gilbert
Travis Howell
- Oliver Kiehl - (retired)
- Ludvig Strigeus - (retired)
+ Oliver Kiehl - (retired)
+ Ludvig Strigeus - (retired)
+
+ AVALANCHE:
+ Peter Bozso
+ Arnaud Boutonne
CGE:
Arnaud Boutonne
Paul Gilbert
Cine:
- Vincent Hamm - (retired)
+ Vincent Hamm - (retired)
Pawel Kolodziejski
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
Kari Salminen
Eugene Sandulenko
@@ -78,7 +82,7 @@ ScummVM Team
CruisE:
Paul Gilbert
- Vincent Hamm - (retired)
+ Vincent Hamm - (retired)
Draci:
Denis Kasak
@@ -92,7 +96,7 @@ ScummVM Team
Torbjorn Andersson
Bertrand Augereau
Filippos Karapetis
- Vladimir Menshakov - (retired)
+ Vladimir Menshakov - (retired)
Willem Jan Palenstijn
Gob:
@@ -116,10 +120,10 @@ ScummVM Team
Eugene Sandulenko
Kyra:
- Torbjorn Andersson - VQA Player
+ Torbjorn Andersson - VQA Player
Oystein Eftevaag
Florian Kagerer
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
Johannes Schickel
Lastexpress:
@@ -142,6 +146,14 @@ ScummVM Team
Eugene Sandulenko
David Turner
+ Mortevielle:
+ Arnaud Boutonne
+ Paul Gilbert
+
+ Neverhood:
+ Benjamin Haisch
+ Filippos Karapetis
+
Parallaction:
peres
@@ -149,14 +161,14 @@ ScummVM Team
Matthew Hoops
Queen:
- David Eriksson - (retired)
- Gregory Montoir - (retired)
+ David Eriksson - (retired)
+ Gregory Montoir - (retired)
Joost Peters
SAGA:
Torbjorn Andersson
- Daniel Balsom - Original engine reimplementation author
- (retired)
+ Daniel Balsom - Original engine reimplementation author
+ (retired)
Filippos Karapetis
Andrew Kurushin
Eugene Sandulenko
@@ -164,46 +176,46 @@ ScummVM Team
SCI:
Greg Frieger
Paul Gilbert
- Max Horn - (retired)
+ Max Horn - (retired)
Filippos Karapetis
Martin Kiewitz
- Walter van Niftrik - (retired)
+ Walter van Niftrik - (retired)
Willem Jan Palenstijn
Jordi Vilalta Prat
Lars Skovlund
Sky:
- Robert Goeffringmann - (retired)
- Oliver Kiehl - (retired)
+ Robert Goeffringmann - (retired)
+ Oliver Kiehl - (retired)
Joost Peters
Sword1:
- Fabio Battaglia - PSX version support
- Thierry Crozat - Mac version support
- Robert Goeffringmann - (retired)
+ Fabio Battaglia - PSX version support
+ Thierry Crozat - Mac version support
+ Robert Goeffringmann - (retired)
Sword2:
Torbjorn Andersson
- Fabio Battaglia - PSX version support
- Jonathan Gray - (retired)
+ Fabio Battaglia - PSX version support
+ Jonathan Gray - (retired)
Sword25:
Torbjorn Andersson
Paul Gilbert
- Max Horn - (retired)
+ Max Horn - (retired)
Filippos Karapetis
Eugene Sandulenko
TeenAgent:
- Robert Megone - Help with callback rewriting
- Vladimir Menshakov - (retired)
+ Robert Megone - Help with callback rewriting
+ Vladimir Menshakov - (retired)
Tinsel:
Torbjorn Andersson
- Fabio Battaglia - PSX version support
+ Fabio Battaglia - PSX version support
Paul Gilbert
Sven Hesse
- Max Horn - (retired)
+ Max Horn - (retired)
Filippos Karapetis
Joost Peters
@@ -220,27 +232,27 @@ ScummVM Team
Sylvain Dupont
Touche:
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
TsAGE:
Arnaud Boutonne
Paul Gilbert
Tucker:
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
Wintermute:
Einar Johan T. Somaaen
+ ZVision:
+ Adrian Astley
+
Backend Teams
-------------
Android:
Andre Heider
Angus Lees
- BADA:
- Chris Warren-Smith
-
Dreamcast:
Marcus Comstedt
@@ -254,26 +266,26 @@ ScummVM Team
Lubomyr Lisen
Maemo:
- Frantisek Dufka - (retired)
+ Frantisek Dufka - (retired)
Tarek Soliman
Nintendo 64:
Fabio Battaglia
Nintendo DS:
- Bertrand Augereau - HQ software scaler
+ Bertrand Augereau - HQ software scaler
Neil Millstone
OpenPandora:
John Willis
PocketPC / WinCE:
- Nicolas Bacca - (retired)
+ Nicolas Bacca - (retired)
Ismail Khatib
- Kostas Nakos - (retired)
+ Kostas Nakos - (retired)
PlayStation 2:
- Robert Goeffringmann - (retired)
+ Robert Goeffringmann - (retired)
Max Lingua
PSP (PlayStation Portable):
@@ -281,13 +293,16 @@ ScummVM Team
Joost Peters
SDL (Win/Linux/OS X/etc.):
- Max Horn - (retired)
- Eugene Sandulenko - Asm routines, GFX layers
+ Max Horn - (retired)
+ Eugene Sandulenko - Asm routines, GFX layers
SymbianOS:
Jurgen Braam
Lars Persson
+ Tizen / BADA:
+ Chris Warren-Smith
+
WebOS:
Klaus Reimer
@@ -297,9 +312,9 @@ ScummVM Team
Other subsystems
----------------
Infrastructure:
- Max Horn - Backend & Engine APIs, file API, sound
- mixer, audiostreams, data structures, etc.
- (retired)
+ Max Horn - Backend & Engine APIs, file API, sound
+ mixer, audiostreams, data structures,
+ etc. (retired)
Eugene Sandulenko
Johannes Schickel
@@ -309,33 +324,35 @@ ScummVM Team
Johannes Schickel
Miscellaneous:
- David Corrales-Lopez - Filesystem access improvements (GSoC 2007
- task) (retired)
- Jerome Fisher - MT-32 emulator
- Benjamin Haisch - Heavily improved de-/encoder for DXA videos
- Jochen Hoenicke - Speaker & PCjr sound support, AdLib work
- (retired)
- Daniel ter Laan - Restoring original Drascula tracks, and
- writing convert_dxa.bat
- Chris Page - Return to launcher, savestate improvements,
- leak fixes, ... (GSoC 2008 task) (retired)
- Robin Watts - ARM assembly routines for nice speedups on
- several ports; improvements to the sound
- mixer
+ David Corrales-Lopez - Filesystem access improvements (GSoC
+ 2007 task) (retired)
+ Jerome Fisher - MT-32 emulator
+ Benjamin Haisch - Heavily improved de-/encoder for DXA
+ videos
+ Jochen Hoenicke - Speaker & PCjr sound support, AdLib
+ work (retired)
+ Daniel ter Laan - Restoring original Drascula tracks, and
+ writing convert_dxa.bat
+ Chris Page - Return to launcher, savestate
+ improvements, leak fixes, ... (GSoC
+ 2008 task) (retired)
+ Robin Watts - ARM assembly routines for nice speedups
+ on several ports; improvements to the
+ sound mixer
Website (code)
--------------
- Fredrik Wendel - (retired)
+ Fredrik Wendel - (retired)
Website (maintenance)
---------------------
- James Brown - IRC Logs maintainer
- Thierry Crozat - Wiki maintainer
- Andre Heider - Buildbot maintainer
- Joost Peters - Doxygen Project Documentation maintainer
- Jordi Vilalta Prat - Wiki maintainer
- Eugene Sandulenko - Forum, IRC channel, Screen Shots and Mailing
- list maintainer
+ James Brown - IRC Logs maintainer
+ Thierry Crozat - Wiki maintainer
+ Andre Heider - Buildbot maintainer
+ Joost Peters - Doxygen Project Documentation maintainer
+ Jordi Vilalta Prat - Wiki maintainer
+ Eugene Sandulenko - Forum, IRC channel, Screen Shots and
+ Mailing list maintainer
John Willis
Website (content)
@@ -344,31 +361,31 @@ ScummVM Team
Documentation
-------------
- Thierry Crozat - Numerous contributions to documentation
- Joachim Eberhard - Numerous contributions to documentation
- (retired)
- Matthew Hoops - Wiki editor
+ Thierry Crozat - Numerous contributions to documentation
+ Joachim Eberhard - Numerous contributions to documentation
+ (retired)
+ Matthew Hoops - Wiki editor
Retired Team Members
--------------------
- Chris Apers - Former PalmOS porter
- Ralph Brorsen - Help with GUI implementation
- Jamieson Christian - iMUSE, MIDI, all things musical
- Felix Jakschitsch - Zak256 reverse engineering
- Mutwin Kraus - Original MacOS porter
- Peter Moraliyski - Port: GP32
- Jeremy Newman - Former webmaster
- Lionel Ulmer - Port: X11
- Won Star - Former GP32 porter
+ Chris Apers - Former PalmOS porter
+ Ralph Brorsen - Help with GUI implementation
+ Jamieson Christian - iMUSE, MIDI, all things musical
+ Felix Jakschitsch - Zak256 reverse engineering
+ Mutwin Kraus - Original MacOS porter
+ Peter Moraliyski - Port: GP32
+ Jeremy Newman - Former webmaster
+ Lionel Ulmer - Port: X11
+ Won Star - Former GP32 porter
Other contributions
*******************
Packages
--------
AmigaOS 4:
- Hans-Joerg Frieden - (retired)
+ Hans-Joerg Frieden - (retired)
Hubert Maier
- Juha Niemimaki - (retired)
+ Juha Niemimaki - (retired)
Atari/FreeMiNT:
Keith Scroggins
@@ -378,22 +395,22 @@ Other contributions
Luc Schrijvers
Debian GNU/Linux:
- Tore Anderson - (retired)
+ Tore Anderson - (retired)
David Weinehall
Fedora / RedHat:
Willem Jan Palenstijn
Mac OS X:
- Max Horn - (retired)
+ Max Horn - (retired)
Oystein Eftevaag
Mandriva:
- Dominik Scherer - (retired)
+ Dominik Scherer - (retired)
MorphOS:
Fabien Coeurjoly
- Ruediger Hanke - (retired)
+ Ruediger Hanke - (retired)
OS/2:
Paul Smedley
@@ -411,12 +428,12 @@ Other contributions
Travis Howell
Win64:
- Chris Gray - (retired)
+ Chris Gray - (retired)
Johannes Schickel
- Translations
- ------------
- Thierry Crozat - Translation Lead
+ GUI Translations
+ ----------------
+ Thierry Crozat - Translation Lead
Basque:
Mikel Iturbe Urretxa
@@ -444,7 +461,7 @@ Other contributions
German:
Simon Sawatzki
- Lothar Serra Mari - (retired)
+ Lothar Serra Mari - (retired)
Hungarian:
Alex Bevilacqua
@@ -478,97 +495,118 @@ Other contributions
Ukrainian:
Lubomyr Lisen
+ Game Translations
+ -----------------
+ CGE:
+ Dan Serban - Soltys English translation
+ Victor Gonzalez - Soltys Spanish translation
+ Alejandro Gomez de la Munoza - Soltys Spanish translation
+
+ Drascula:
+ Thierry Crozat - Improve French translation
+
+ Mortevielle:
+ Hugo Labrande - Improve English translation
+ Thierry Crozat - Improve English translation
+
Websites (design)
-----------------
- Dobo Balazs - Website design
- William Claydon - Skins for doxygen, buildbot and wiki
- Yaroslav Fedevych - HTML/CSS for the website
- Jean Marc Gimenez - ScummVM logo
- David Jensen - SVG logo conversion
- Raina - ScummVM forum buttons
+ Dobo Balazs - Website design
+ William Claydon - Skins for doxygen, buildbot and wiki
+ Yaroslav Fedevych - HTML/CSS for the website
+ Jean Marc Gimenez - ScummVM logo
+ David Jensen - SVG logo conversion
+ Raina - ScummVM forum buttons
Code contributions
------------------
- Ori Avtalion - Subtitle control options in the GUI; BASS GUI
- fixes
- Stuart Caie - Decoders for Amiga and AtariST data files
- (AGOS engine)
- Paolo Costabel - PSP port contributions
- Martin Doucha - CinE engine objectification
- Thomas Fach-Pedersen - ProTracker module player, Smacker video
- decoder
- Tobias Gunkel - Sound support for C64 version of MM/Zak, Loom
- PCE support
- Janne Huttunen - V3 actor mask support, Dig/FT SMUSH audio
- Kovacs Endre Janos - Several fixes for Simon1
- Jeroen Janssen - Numerous readability and bugfix patches
- Andreas Karlsson - Initial port for SymbianOS
- Claudio Matsuoka - Daily Linux builds
- Thomas Mayer - PSP port contributions
- Sean Murray - ScummVM tools GUI application (GSoC 2007 task)
- n0p - Windows CE port aspect ratio correction scaler
- and right click input method
- Mikesch Nepomuk - MI1 VGA floppy patches
- Nicolas Noble - Config file and ALSA support
- Tim Phillips - Initial MI1 CD music support
- Quietust - Sound support for Amiga SCUMM V2/V3 games, MM
- NES support
- Robert Crossfield - Improved support for Apple II/C64 versions of
- MM
- Andreas Roever - Broken Sword I & II MPEG2 cutscene support
- Edward Rudd - Fixes for playing MP3 versions of MI1/Loom
- audio
- Daniel Schepler - Final MI1 CD music support, initial Ogg Vorbis
- support
- Andre Souza - SDL-based OpenGL renderer
- Tom Frost - WebOS port contributions
+ Ori Avtalion - Subtitle control options in the GUI; BASS
+ GUI fixes
+ Stuart Caie - Decoders for Amiga and AtariST data files
+ (AGOS engine)
+ Paolo Costabel - PSP port contributions
+ Martin Doucha - CinE engine objectification
+ Thomas Fach-Pedersen - ProTracker module player, Smacker video
+ decoder
+ Tobias Gunkel - Sound support for C64 version of MM/Zak,
+ Loom PCE support
+ Janne Huttunen - V3 actor mask support, Dig/FT SMUSH audio
+ Kovacs Endre Janos - Several fixes for Simon1
+ Jeroen Janssen - Numerous readability and bugfix patches
+ Keith Kaisershot - Several Pegasus Prime patches
+ Andreas Karlsson - Initial port for SymbianOS
+ Claudio Matsuoka - Daily Linux builds
+ Thomas Mayer - PSP port contributions
+ Sean Murray - ScummVM tools GUI application (GSoC 2007
+ task)
+ n0p - Windows CE port aspect ratio correction
+ scaler and right click input method
+ Mikesch Nepomuk - MI1 VGA floppy patches
+ Nicolas Noble - Config file and ALSA support
+ Tim Phillips - Initial MI1 CD music support
+ Quietust - Sound support for Amiga SCUMM V2/V3
+ games, MM NES support
+ Robert Crossfield - Improved support for Apple II/C64
+ versions of MM
+ Andreas Roever - Broken Sword I & II MPEG2 cutscene
+ support
+ Edward Rudd - Fixes for playing MP3 versions of
+ MI1/Loom audio
+ Daniel Schepler - Final MI1 CD music support, initial Ogg
+ Vorbis support
+ Andre Souza - SDL-based OpenGL renderer
+ Tom Frost - WebOS port contributions
FreeSCI Contributors
--------------------
- Francois-R Boyer - MT-32 information and mapping code
- Rainer Canavan - IRIX MIDI driver and bug fixes
+ Francois-R Boyer - MT-32 information and mapping code
+ Rainer Canavan - IRIX MIDI driver and bug fixes
Xiaojun Chen
- Paul David Doherty - Game version information
- Vyacheslav Dikonov - Config script improvements
- Ruediger Hanke - Port to the MorphOS platform
- Matt Hargett - Clean-ups, bugfixes, Hardcore QA, Win32
- Max Horn - SetJump implementation
- Ravi I. - SCI0 sound resource specification
- Emmanuel Jeandel - Bugfixes and bug reports
- Dmitry Jemerov - Port to the Win32 platform, numerous bugfixes
- Chris Kehler - Makefile enhancements
- Christopher T. Lansdown - Original CVS maintainer, Alpha compatibility
- fixes
- Sergey Lapin - Port of Carl's type 2 decompression code
- Rickard Lind - MT-32->GM MIDI mapping magic, sound research
- Hubert Maier - AmigaOS 4 port
- Johannes Manhave - Document format translation
- Claudio Matsuoka - CVS snapshots, daily builds, BeOS and cygwin
- ports
- Dark Minister - SCI research (bytecode and parser)
- Carl Muckenhoupt - Sources to the SCI resource viewer tools that
- started it all
- Anders Baden Nielsen - PPC testing
- Walter van Niftrik - Ports to the Dreamcast and GP32 platforms
- Rune Orsval - Configuration file editor
- Solomon Peachy - SDL ports and much of the sound subsystem
- Robey Pointer - Bug tracking system hosting
- Magnus Reftel - Heap implementation, Python class viewer,
- bugfixes
- Christoph Reichenbach - UN*X code, VM/Graphics/Sound/other
- infrastructure
- George Reid - FreeBSD package management
- Lars Skovlund - Project maintenance, most documentation,
- bugfixes, SCI1 support
- Rink Springer - Port to the DOS platform, several bug fixes
- Rainer De Temple - SCI research
+ Paul David Doherty - Game version information
+ Vyacheslav Dikonov - Config script improvements
+ Ruediger Hanke - Port to the MorphOS platform
+ Matt Hargett - Clean-ups, bugfixes, Hardcore QA, Win32
+ Max Horn - SetJump implementation
+ Ravi I. - SCI0 sound resource specification
+ Emmanuel Jeandel - Bugfixes and bug reports
+ Dmitry Jemerov - Port to the Win32 platform, numerous
+ bugfixes
+ Chris Kehler - Makefile enhancements
+ Christopher T. Lansdown - Original CVS maintainer, Alpha
+ compatibility fixes
+ Sergey Lapin - Port of Carl's type 2 decompression code
+ Rickard Lind - MT-32->GM MIDI mapping magic, sound
+ research
+ Hubert Maier - AmigaOS 4 port
+ Johannes Manhave - Document format translation
+ Claudio Matsuoka - CVS snapshots, daily builds, BeOS and
+ cygwin ports
+ Dark Minister - SCI research (bytecode and parser)
+ Carl Muckenhoupt - Sources to the SCI resource viewer tools
+ that started it all
+ Anders Baden Nielsen - PPC testing
+ Walter van Niftrik - Ports to the Dreamcast and GP32 platforms
+ Rune Orsval - Configuration file editor
+ Solomon Peachy - SDL ports and much of the sound subsystem
+ Robey Pointer - Bug tracking system hosting
+ Magnus Reftel - Heap implementation, Python class viewer,
+ bugfixes
+ Christoph Reichenbach - UN*X code, VM/Graphics/Sound/other
+ infrastructure
+ George Reid - FreeBSD package management
+ Lars Skovlund - Project maintenance, most documentation,
+ bugfixes, SCI1 support
+ Rink Springer - Port to the DOS platform, several bug
+ fixes
+ Rainer De Temple - SCI research
Sean Terrell
- Hugues Valois - Game selection menu
- Jordi Vilalta - Numerous code and website clean-up patches
- Petr Vyhnak - The DCL-INFLATE algorithm, many Win32
- improvements
- Bas Zoetekouw - Man pages, debian package management, CVS
- maintenance
+ Hugues Valois - Game selection menu
+ Jordi Vilalta - Numerous code and website clean-up
+ patches
+ Petr Vyhnak - The DCL-INFLATE algorithm, many Win32
+ improvements
+ Bas Zoetekouw - Man pages, debian package management, CVS
+ maintenance
Special thanks to Prof. Dr. Gary Nutt for allowing the FreeSCI VM
extension as a course project in his Advanced OS course.
@@ -601,6 +639,8 @@ Special thanks to
Jimmi Thogersen - For ScummRev, and much obscure code/documentation
Tristan - For additional work on the original MT-32 emulator
James Woodcock - Soundtrack enhancements
+ Anton Yartsev - For the original re-implementation of the ZVision
+ engine
Tony Warriner and everyone at Revolution Software Ltd. for sharing with us
the source of some of their brilliant games, allowing us to release
diff --git a/Makefile b/Makefile
index 28eaead4b4..88b60ca73f 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"
@@ -75,7 +82,8 @@ EXECUTABLE := $(EXEPRE)scummvm$(EXEEXT)
include $(srcdir)/Makefile.common
# check if configure has been run or has been changed since last run
-config.h config.mk: $(srcdir)/configure $(srcdir)/engines/configure.engines
+ENGINE_SUBDIRS_CONFIGURE := $(wildcard $(srcdir)/engines/*/configure.engine)
+config.h: $(srcdir)/configure $(ENGINE_SUBDIRS_CONFIGURE)
ifeq "$(findstring config.mk,$(MAKEFILE_LIST))" "config.mk"
@echo "Running $(srcdir)/configure with the last specified parameters"
@sleep 2
@@ -87,6 +95,14 @@ else
$(error You need to run $(srcdir)/configure before you can run make. Check $(srcdir)/configure --help for a list of parameters)
endif
+config.mk engines/plugins_table.h engines/engines.mk: config.h
+ @if test -f $@; then \
+ touch $@; \
+ else \
+ rm -f config.h; \
+ $(MAKE) config.h; \
+ fi
+
ifneq ($(origin port_mk), undefined)
include $(srcdir)/$(port_mk)
endif
diff --git a/Makefile.common b/Makefile.common
index 4350e16adc..b56300a115 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -16,7 +16,7 @@ all: $(EXECUTABLE) plugins
PLUGINS :=
MODULES := test devtools base $(MODULES)
--include $(srcdir)/engines/engines.mk
+-include engines/engines.mk
# After the game specific modules follow the shared modules
MODULES += \
@@ -79,7 +79,7 @@ $(EXECUTABLE): $(OBJS)
$(QUIET_LINK)$(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) -o $@
distclean: clean clean-devtools
- $(RM) config.h config.mk config.log
+ $(RM) config.h config.mk config.log engines/engines.mk engines/plugins_table.h
clean:
$(RM_REC) $(DEPDIRS)
@@ -147,7 +147,7 @@ endif
# recreate them (which it can't), and in particular from looking for potential
# source files. This can save quite a bit of disk access time.
.PHONY: $(wildcard $(addsuffix /*.d,$(DEPDIRS))) $(addprefix $(srcdir)/, $(addsuffix /module.mk,$(MODULES))) \
- $(srcdir)/$(port_mk) $(srcdir)/rules.mk $(srcdir)/engines/engines.mk
+ $(srcdir)/$(port_mk) $(srcdir)/rules.mk
######################################################################
# Get the current version information
@@ -253,6 +253,12 @@ 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
ifdef ENABLE_QUEEN
DIST_FILES_ENGINEDATA+=queen.tbl
endif
@@ -262,6 +268,9 @@ endif
ifdef ENABLE_TEENAGENT
DIST_FILES_ENGINEDATA+=teenagent.dat
endif
+ifdef ENABLE_TONY
+DIST_FILES_ENGINEDATA+=tony.dat
+endif
ifdef ENABLE_TOON
DIST_FILES_ENGINEDATA+=toon.dat
endif
diff --git a/NEWS b/NEWS
index e52daeccd7..7a0487cdc9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,20 @@
For a more comprehensive changelog of the latest experimental code, see:
https://github.com/scummvm/scummvm/commits/
-1.6.0 (????-??-??)
+1.7.0 (????-??-??)
+ General:
+ - Updated MT-32 emulation code to version 1.3.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:
- Added support for 3 Skulls of the Toltecs.
- Added support for Eye of the Beholder.
diff --git a/audio/midiparser.cpp b/audio/midiparser.cpp
index 9c144c2479..2454575413 100644
--- a/audio/midiparser.cpp
+++ b/audio/midiparser.cpp
@@ -44,7 +44,8 @@ _centerPitchWheelOnUnload(false),
_sendSustainOffOnNotesOff(false),
_numTracks(0),
_activeTrack(255),
-_abortParse(0) {
+_abortParse(false),
+_jumpingToTick(false) {
memset(_activeNotes, 0, sizeof(_activeNotes));
memset(_tracks, 0, sizeof(_tracks));
_nextEvent.start = NULL;
@@ -204,49 +205,22 @@ void MidiParser::onTimer() {
return;
}
- if (info.event == 0xF0) {
- // SysEx event
- // Check for trailing 0xF7 -- if present, remove it.
- if (info.ext.data[info.length-1] == 0xF7)
- _driver->sysEx(info.ext.data, (uint16)info.length-1);
+ if (info.command() == 0x8) {
+ activeNote(info.channel(), info.basic.param1, false);
+ } else if (info.command() == 0x9) {
+ if (info.length > 0)
+ hangingNote(info.channel(), info.basic.param1, info.length * _psecPerTick - (endTime - eventTime));
else
- _driver->sysEx(info.ext.data, (uint16)info.length);
- } else if (info.event == 0xFF) {
- // META event
- if (info.ext.type == 0x2F) {
- // End of Track must be processed by us,
- // as well as sending it to the output device.
- if (_autoLoop) {
- jumpToTick(0);
- parseNextEvent(_nextEvent);
- } else {
- stopPlaying();
- _driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
- }
- return;
- } else if (info.ext.type == 0x51) {
- if (info.length >= 3) {
- setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
- }
- }
- _driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
- } else {
- if (info.command() == 0x8) {
- activeNote(info.channel(), info.basic.param1, false);
- } else if (info.command() == 0x9) {
- if (info.length > 0)
- hangingNote(info.channel(), info.basic.param1, info.length * _psecPerTick - (endTime - eventTime));
- else
- activeNote(info.channel(), info.basic.param1, true);
- }
- sendToDriver(info.event, info.basic.param1, info.basic.param2);
+ activeNote(info.channel(), info.basic.param1, true);
}
+ processEvent(info);
- if (!_abortParse) {
- _position._lastEventTime = eventTime;
- parseNextEvent(_nextEvent);
- }
+ if (_abortParse)
+ break;
+
+ _position._lastEventTime = eventTime;
+ parseNextEvent(_nextEvent);
}
if (!_abortParse) {
@@ -255,6 +229,45 @@ void MidiParser::onTimer() {
}
}
+void MidiParser::processEvent(const EventInfo &info, bool fireEvents) {
+ if (info.event == 0xF0) {
+ // SysEx event
+ // Check for trailing 0xF7 -- if present, remove it.
+ if (fireEvents) {
+ if (info.ext.data[info.length-1] == 0xF7)
+ _driver->sysEx(info.ext.data, (uint16)info.length-1);
+ else
+ _driver->sysEx(info.ext.data, (uint16)info.length);
+ }
+ } else if (info.event == 0xFF) {
+ // META event
+ if (info.ext.type == 0x2F) {
+ // End of Track must be processed by us,
+ // as well as sending it to the output device.
+ if (_autoLoop) {
+ jumpToTick(0);
+ parseNextEvent(_nextEvent);
+ } else {
+ stopPlaying();
+ if (fireEvents)
+ _driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
+ }
+ _abortParse = true;
+ return;
+ } else if (info.ext.type == 0x51) {
+ if (info.length >= 3) {
+ setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
+ }
+ }
+ if (fireEvents)
+ _driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
+ } else {
+ if (fireEvents)
+ sendToDriver(info.event, info.basic.param1, info.basic.param2);
+ }
+}
+
+
void MidiParser::allNotesOff() {
if (!_driver)
return;
@@ -370,6 +383,9 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
if (_activeTrack >= _numTracks)
return false;
+ assert(!_jumpingToTick); // This function is not re-entrant
+ _jumpingToTick = true;
+
Tracker currentPos(_position);
EventInfo currentEvent(_nextEvent);
@@ -390,34 +406,19 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
_position._playTick = _position._lastEventTick;
_position._playTime = _position._lastEventTime;
- if (info.event == 0xFF) {
- if (info.ext.type == 0x2F) { // End of track
- _position = currentPos;
- _nextEvent = currentEvent;
- return false;
- } else {
- if (info.ext.type == 0x51 && info.length >= 3) // Tempo
- setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
- if (fireEvents)
- _driver->metaEvent(info.ext.type, info.ext.data, (uint16) info.length);
- }
- } else if (fireEvents) {
- if (info.event == 0xF0) {
- if (info.ext.data[info.length-1] == 0xF7)
- _driver->sysEx(info.ext.data, (uint16)info.length-1);
- else
- _driver->sysEx(info.ext.data, (uint16)info.length);
- } else {
- // The note on sending code is used by the SCUMM engine. Other engine using this code
- // (such as SCI) have issues with this, as all the notes sent can be heard when a song
- // is fast-forwarded. Thus, if the engine requests it, don't send note on events.
- if (info.command() == 0x9 && dontSendNoteOn) {
- // Don't send note on; doing so creates a "warble" with some instruments on the MT-32.
- // Refer to patch #3117577
- } else {
- sendToDriver(info.event, info.basic.param1, info.basic.param2);
- }
- }
+ // Some special processing for the fast-forward case
+ if (info.command() == 0x9 && dontSendNoteOn) {
+ // Don't send note on; doing so creates a "warble" with
+ // some instruments on the MT-32. Refer to patch #3117577
+ } else if (info.event == 0xFF && info.ext.type == 0x2F) {
+ // End of track
+ // This means that we failed to find the right tick.
+ _position = currentPos;
+ _nextEvent = currentEvent;
+ _jumpingToTick = false;
+ return false;
+ } else {
+ processEvent(info, fireEvents);
}
parseNextEvent(_nextEvent);
@@ -441,6 +442,7 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
}
_abortParse = true;
+ _jumpingToTick = false;
return true;
}
diff --git a/audio/midiparser.h b/audio/midiparser.h
index bb9749b97f..05d0cbe1db 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -105,8 +105,8 @@ struct EventInfo {
///< will occur, and the MidiParser will have to generate one itself.
///< For all other events, this value should always be zero.
- byte channel() { return event & 0x0F; } ///< Separates the MIDI channel from the event.
- byte command() { return event >> 4; } ///< Separates the command code from the event.
+ byte channel() const { return event & 0x0F; } ///< Separates the MIDI channel from the event.
+ byte command() const { return event >> 4; } ///< Separates the command code from the event.
};
/**
@@ -287,12 +287,14 @@ protected:
///< so each event is parsed only once; this permits
///< simulated events in certain formats.
bool _abortParse; ///< If a jump or other operation interrupts parsing, flag to abort.
+ bool _jumpingToTick; ///< True if currently inside jumpToTick
protected:
static uint32 readVLQ(byte * &data);
virtual void resetTracking();
virtual void allNotesOff();
virtual void parseNextEvent(EventInfo &info) = 0;
+ virtual void processEvent(const EventInfo &info, bool fireEvents = true);
void activeNote(byte channel, byte note, bool active);
void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
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..2a90b583f3 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
@@ -459,9 +460,6 @@ bool MT32EmuMusicPlugin::checkDevice(MidiDriver::DeviceHandle) const {
}
Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- if (ConfMan.hasKey("extrapath"))
- SearchMan.addDirectory("extrapath", ConfMan.get("extrapath"));
-
*mididriver = new MidiDriver_MT32(g_system->getMixer());
return Common::kNoError;
diff --git a/audio/softsynth/mt32/AReverbModel.cpp b/audio/softsynth/mt32/AReverbModel.cpp
deleted file mode 100644
index 1d63832157..0000000000
--- a/audio/softsynth/mt32/AReverbModel.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "mt32emu.h"
-
-#if MT32EMU_USE_REVERBMODEL == 1
-
-#include "AReverbModel.h"
-
-// Analysing of state of reverb RAM address lines gives exact sizes of the buffers of filters used. This also indicates that
-// the reverb model implemented in the real devices consists of three series allpass filters preceded by a non-feedback comb (or a delay with a LPF)
-// and followed by three parallel comb filters
-
-namespace MT32Emu {
-
-// Because LA-32 chip makes it's output available to process by the Boss chip with a significant delay,
-// the Boss chip puts to the buffer the LA32 dry output when it is ready and performs processing of the _previously_ latched data.
-// Of course, the right way would be to use a dedicated variable for this, but our reverb model is way higher level,
-// so we can simply increase the input buffer size.
-static const Bit32u PROCESS_DELAY = 1;
-
-// Default reverb settings for modes 0-2. These correspond to CM-32L / LAPC-I "new" reverb settings. MT-32 reverb is a bit different.
-// Found by tracing reverb RAM data lines (thanks go to Lord_Nightmare & balrog).
-
-static const Bit32u NUM_ALLPASSES = 3;
-static const Bit32u NUM_COMBS = 4; // Well, actually there are 3 comb filters, but the entrance LPF + delay can be perfectly processed via a comb here.
-
-static const Bit32u MODE_0_ALLPASSES[] = {994, 729, 78};
-static const Bit32u MODE_0_COMBS[] = {705 + PROCESS_DELAY, 2349, 2839, 3632};
-static const Bit32u MODE_0_OUTL[] = {2349, 141, 1960};
-static const Bit32u MODE_0_OUTR[] = {1174, 1570, 145};
-static const Bit32u MODE_0_COMB_FACTOR[] = {0x3C, 0x60, 0x60, 0x60};
-static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
-static const Bit32u MODE_0_LEVELS[] = {10*1, 10*3, 10*5, 10*7, 11*9, 11*12, 11*15, 13*15};
-static const Bit32u MODE_0_LPF_AMP = 6;
-
-static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176};
-static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519};
-static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518};
-static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274};
-static const Bit32u MODE_1_COMB_FACTOR[] = {0x30, 0x60, 0x60, 0x60};
-static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
-static const Bit32u MODE_1_LEVELS[] = {10*1, 10*3, 11*5, 11*7, 11*9, 11*12, 11*15, 14*15};
-static const Bit32u MODE_1_LPF_AMP = 6;
-
-static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157};
-static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539};
-static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769};
-static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1};
-static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x20, 0x20, 0x20};
-static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
- 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
- 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0};
-static const Bit32u MODE_2_LEVELS[] = {10*1, 10*3, 11*5, 11*7, 11*9, 11*12, 12*15, 14*15};
-static const Bit32u MODE_2_LPF_AMP = 8;
-
-static const AReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_ALLPASSES, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_LEVELS, MODE_0_LPF_AMP};
-static const AReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_ALLPASSES, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_LEVELS, MODE_1_LPF_AMP};
-static const AReverbSettings REVERB_MODE_2_SETTINGS = {MODE_2_ALLPASSES, MODE_2_COMBS, MODE_2_OUTL, MODE_2_OUTR, MODE_2_COMB_FACTOR, MODE_2_COMB_FEEDBACK, MODE_2_LEVELS, MODE_2_LPF_AMP};
-
-static const AReverbSettings * const REVERB_SETTINGS[] = {&REVERB_MODE_0_SETTINGS, &REVERB_MODE_1_SETTINGS, &REVERB_MODE_2_SETTINGS, &REVERB_MODE_0_SETTINGS};
-
-RingBuffer::RingBuffer(const Bit32u newsize) : size(newsize), index(0) {
- buffer = new float[size];
-}
-
-RingBuffer::~RingBuffer() {
- delete[] buffer;
- buffer = NULL;
-}
-
-float RingBuffer::next() {
- if (++index >= size) {
- index = 0;
- }
- return buffer[index];
-}
-
-bool RingBuffer::isEmpty() const {
- if (buffer == NULL) return true;
-
- float *buf = buffer;
- float max = 0.001f;
- for (Bit32u i = 0; i < size; i++) {
- if ((*buf < -max) || (*buf > max)) return false;
- buf++;
- }
- return true;
-}
-
-void RingBuffer::mute() {
- float *buf = buffer;
- for (Bit32u i = 0; i < size; i++) {
- *buf++ = 0;
- }
-}
-
-AllpassFilter::AllpassFilter(const Bit32u useSize) : RingBuffer(useSize) {}
-
-float AllpassFilter::process(const float in) {
- // This model corresponds to the allpass filter implementation of the real CM-32L device
- // found from sample analysis
-
- const float bufferOut = next();
-
- // store input - feedback / 2
- buffer[index] = in - 0.5f * bufferOut;
-
- // return buffer output + feedforward / 2
- return bufferOut + 0.5f * buffer[index];
-}
-
-CombFilter::CombFilter(const Bit32u useSize) : RingBuffer(useSize) {}
-
-void CombFilter::process(const float in) {
- // This model corresponds to the comb filter implementation of the real CM-32L device
- // found from sample analysis
-
- // the previously stored value
- float last = buffer[index];
-
- // prepare input + feedback
- float filterIn = in + next() * feedbackFactor;
-
- // store input + feedback processed by a low-pass filter
- buffer[index] = filterFactor * last - filterIn;
-}
-
-float CombFilter::getOutputAt(const Bit32u outIndex) const {
- return buffer[(size + index - outIndex) % size];
-}
-
-void CombFilter::setFeedbackFactor(const float useFeedbackFactor) {
- feedbackFactor = useFeedbackFactor;
-}
-
-void CombFilter::setFilterFactor(const float useFilterFactor) {
- filterFactor = useFilterFactor;
-}
-
-AReverbModel::AReverbModel(const ReverbMode mode) : allpasses(NULL), combs(NULL), currentSettings(*REVERB_SETTINGS[mode]) {}
-
-AReverbModel::~AReverbModel() {
- close();
-}
-
-void AReverbModel::open() {
- allpasses = new AllpassFilter*[NUM_ALLPASSES];
- for (Bit32u i = 0; i < NUM_ALLPASSES; i++) {
- allpasses[i] = new AllpassFilter(currentSettings.allpassSizes[i]);
- }
- combs = new CombFilter*[NUM_COMBS];
- for (Bit32u i = 0; i < NUM_COMBS; i++) {
- combs[i] = new CombFilter(currentSettings.combSizes[i]);
- combs[i]->setFilterFactor(currentSettings.filterFactor[i] / 256.0f);
- }
- lpfAmp = currentSettings.lpfAmp / 16.0f;
- mute();
-}
-
-void AReverbModel::close() {
- if (allpasses != NULL) {
- for (Bit32u i = 0; i < NUM_ALLPASSES; i++) {
- if (allpasses[i] != NULL) {
- delete allpasses[i];
- allpasses[i] = NULL;
- }
- }
- delete[] allpasses;
- allpasses = NULL;
- }
- if (combs != NULL) {
- for (Bit32u i = 0; i < NUM_COMBS; i++) {
- if (combs[i] != NULL) {
- delete combs[i];
- combs[i] = NULL;
- }
- }
- delete[] combs;
- combs = NULL;
- }
-}
-
-void AReverbModel::mute() {
- if (allpasses == NULL || combs == NULL) return;
- for (Bit32u i = 0; i < NUM_ALLPASSES; i++) {
- allpasses[i]->mute();
- }
- for (Bit32u i = 0; i < NUM_COMBS; i++) {
- combs[i]->mute();
- }
-}
-
-void AReverbModel::setParameters(Bit8u time, Bit8u level) {
-// FIXME: wetLevel definitely needs ramping when changed
-// Although, most games don't set reverb level during MIDI playback
- if (combs == NULL) return;
- level &= 7;
- time &= 7;
- for (Bit32u i = 0; i < NUM_COMBS; i++) {
- combs[i]->setFeedbackFactor(currentSettings.decayTimes[(i << 3) + time] / 256.0f);
- }
- wetLevel = (level == 0 && time == 0) ? 0.0f : 0.5f * lpfAmp * currentSettings.wetLevels[level] / 256.0f;
-}
-
-bool AReverbModel::isActive() const {
- for (Bit32u i = 0; i < NUM_ALLPASSES; i++) {
- if (!allpasses[i]->isEmpty()) return true;
- }
- for (Bit32u i = 0; i < NUM_COMBS; i++) {
- if (!combs[i]->isEmpty()) return true;
- }
- return false;
-}
-
-void AReverbModel::process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) {
- float dry, link, outL1;
-
- for (unsigned long i = 0; i < numSamples; i++) {
- dry = wetLevel * (*inLeft + *inRight);
-
- // Get the last stored sample before processing in order not to loose it
- link = combs[0]->getOutputAt(currentSettings.combSizes[0] - 1);
-
- combs[0]->process(-dry);
-
- link = allpasses[0]->process(link);
- link = allpasses[1]->process(link);
- link = allpasses[2]->process(link);
-
- // If the output position is equal to the comb size, get it now in order not to loose it
- outL1 = 1.5f * combs[1]->getOutputAt(currentSettings.outLPositions[0] - 1);
-
- combs[1]->process(link);
- combs[2]->process(link);
- combs[3]->process(link);
-
- link = outL1 + 1.5f * combs[2]->getOutputAt(currentSettings.outLPositions[1]);
- link += combs[3]->getOutputAt(currentSettings.outLPositions[2]);
- *outLeft = link;
-
- link = 1.5f * combs[1]->getOutputAt(currentSettings.outRPositions[0]);
- link += 1.5f * combs[2]->getOutputAt(currentSettings.outRPositions[1]);
- link += combs[3]->getOutputAt(currentSettings.outRPositions[2]);
- *outRight = link;
-
- inLeft++;
- inRight++;
- outLeft++;
- outRight++;
- }
-}
-
-}
-
-#endif
diff --git a/audio/softsynth/mt32/AReverbModel.h b/audio/softsynth/mt32/AReverbModel.h
deleted file mode 100644
index c992478907..0000000000
--- a/audio/softsynth/mt32/AReverbModel.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MT32EMU_A_REVERB_MODEL_H
-#define MT32EMU_A_REVERB_MODEL_H
-
-namespace MT32Emu {
-
-struct AReverbSettings {
- const Bit32u * const allpassSizes;
- const Bit32u * const combSizes;
- const Bit32u * const outLPositions;
- const Bit32u * const outRPositions;
- const Bit32u * const filterFactor;
- const Bit32u * const decayTimes;
- const Bit32u * const wetLevels;
- const Bit32u lpfAmp;
-};
-
-class RingBuffer {
-protected:
- float *buffer;
- const Bit32u size;
- Bit32u index;
-
-public:
- RingBuffer(const Bit32u size);
- virtual ~RingBuffer();
- float next();
- bool isEmpty() const;
- void mute();
-};
-
-class AllpassFilter : public RingBuffer {
-public:
- AllpassFilter(const Bit32u size);
- float process(const float in);
-};
-
-class CombFilter : public RingBuffer {
- float feedbackFactor;
- float filterFactor;
-
-public:
- CombFilter(const Bit32u size);
- void process(const float in);
- float getOutputAt(const Bit32u outIndex) const;
- void setFeedbackFactor(const float useFeedbackFactor);
- void setFilterFactor(const float useFilterFactor);
-};
-
-class AReverbModel : public ReverbModel {
- AllpassFilter **allpasses;
- CombFilter **combs;
-
- const AReverbSettings &currentSettings;
- float lpfAmp;
- float wetLevel;
- void mute();
-
-public:
- AReverbModel(const ReverbMode mode);
- ~AReverbModel();
- void open();
- void close();
- void setParameters(Bit8u time, Bit8u level);
- void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
- bool isActive() const;
-};
-
-}
-
-#endif
diff --git a/audio/softsynth/mt32/BReverbModel.cpp b/audio/softsynth/mt32/BReverbModel.cpp
index cc0219b741..c16f7f17da 100644
--- a/audio/softsynth/mt32/BReverbModel.cpp
+++ b/audio/softsynth/mt32/BReverbModel.cpp
@@ -15,10 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+//#include <memory.h>
#include "mt32emu.h"
-
-#if MT32EMU_USE_REVERBMODEL == 2
-
#include "BReverbModel.h"
// Analysing of state of reverb RAM address lines gives exact sizes of the buffers of filters used. This also indicates that
@@ -62,9 +60,9 @@ static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518};
static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274};
static const Bit32u MODE_1_COMB_FACTOR[] = {0x80, 0x60, 0x60, 0x60};
static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
- 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
+ 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
+ 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
+ 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_1_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xE0};
static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0};
static const Bit32u MODE_1_LPF_AMP = 0x60;
@@ -103,7 +101,11 @@ static const BReverbSettings * const REVERB_SETTINGS[] = {&REVERB_MODE_0_SETTING
// This algorithm tries to emulate exactly Boss multiplication operation (at least this is what we see on reverb RAM data lines).
// Also LA32 is suspected to use the similar one to perform PCM interpolation and ring modulation.
-static Bit32s weirdMul(Bit32s a, Bit8u addMask, Bit8u carryMask) {
+static Sample weirdMul(Sample a, Bit8u addMask, Bit8u carryMask) {
+ (void)carryMask;
+#if MT32EMU_USE_FLOAT_SAMPLES
+ return a * addMask / 256.0f;
+#elif MT32EMU_BOSS_REVERB_PRECISE_MODE
Bit8u mask = 0x80;
Bit32s res = 0;
for (int i = 0; i < 8; i++) {
@@ -113,10 +115,13 @@ static Bit32s weirdMul(Bit32s a, Bit8u addMask, Bit8u carryMask) {
mask >>= 1;
}
return res;
+#else
+ return Sample(((Bit32s)a * addMask) >> 8);
+#endif
}
RingBuffer::RingBuffer(Bit32u newsize) : size(newsize), index(0) {
- buffer = new Bit16s[size];
+ buffer = new Sample[size];
}
RingBuffer::~RingBuffer() {
@@ -124,7 +129,7 @@ RingBuffer::~RingBuffer() {
buffer = NULL;
}
-Bit32s RingBuffer::next() {
+Sample RingBuffer::next() {
if (++index >= size) {
index = 0;
}
@@ -134,52 +139,69 @@ Bit32s RingBuffer::next() {
bool RingBuffer::isEmpty() const {
if (buffer == NULL) return true;
- Bit16s *buf = buffer;
+#if MT32EMU_USE_FLOAT_SAMPLES
+ Sample max = 0.001f;
+#else
+ Sample max = 8;
+#endif
+ Sample *buf = buffer;
for (Bit32u i = 0; i < size; i++) {
- if (*buf < -8 || *buf > 8) return false;
+ if (*buf < -max || *buf > max) return false;
buf++;
}
return true;
}
void RingBuffer::mute() {
- Bit16s *buf = buffer;
+#if MT32EMU_USE_FLOAT_SAMPLES
+ Sample *buf = buffer;
for (Bit32u i = 0; i < size; i++) {
*buf++ = 0;
}
+#else
+ memset(buffer, 0, size * sizeof(Sample));
+#endif
}
AllpassFilter::AllpassFilter(const Bit32u useSize) : RingBuffer(useSize) {}
-Bit32s AllpassFilter::process(const Bit32s in) {
+Sample AllpassFilter::process(const Sample in) {
// This model corresponds to the allpass filter implementation of the real CM-32L device
// found from sample analysis
- Bit16s bufferOut = next();
+ const Sample bufferOut = next();
+#if MT32EMU_USE_FLOAT_SAMPLES
+ // store input - feedback / 2
+ buffer[index] = in - 0.5f * bufferOut;
+
+ // return buffer output + feedforward / 2
+ return bufferOut + 0.5f * buffer[index];
+#else
// store input - feedback / 2
buffer[index] = in - (bufferOut >> 1);
// return buffer output + feedforward / 2
return bufferOut + (buffer[index] >> 1);
+#endif
}
CombFilter::CombFilter(const Bit32u useSize, const Bit32u useFilterFactor) : RingBuffer(useSize), filterFactor(useFilterFactor) {}
-void CombFilter::process(const Bit32s in) {
+void CombFilter::process(const Sample in) {
// This model corresponds to the comb filter implementation of the real CM-32L device
// the previously stored value
- Bit32s last = buffer[index];
+ const Sample last = buffer[index];
// prepare input + feedback
- Bit32s filterIn = in + weirdMul(next(), feedbackFactor, 0xF0 /* Maybe 0x80 ? */);
+ const Sample filterIn = in + weirdMul(next(), feedbackFactor, 0xF0 /* Maybe 0x80 ? */);
// store input + feedback processed by a low-pass filter
buffer[index] = weirdMul(last, filterFactor, 0x40) - filterIn;
}
-Bit32s CombFilter::getOutputAt(const Bit32u outIndex) const {
+Sample CombFilter::getOutputAt(const Bit32u outIndex) const {
return buffer[(size + index - outIndex) % size];
}
@@ -190,15 +212,15 @@ void CombFilter::setFeedbackFactor(const Bit32u useFeedbackFactor) {
DelayWithLowPassFilter::DelayWithLowPassFilter(const Bit32u useSize, const Bit32u useFilterFactor, const Bit32u useAmp)
: CombFilter(useSize, useFilterFactor), amp(useAmp) {}
-void DelayWithLowPassFilter::process(const Bit32s in) {
+void DelayWithLowPassFilter::process(const Sample in) {
// the previously stored value
- Bit32s last = buffer[index];
+ const Sample last = buffer[index];
// move to the next index
next();
// low-pass filter process
- Bit32s lpfOut = weirdMul(last, filterFactor, 0xFF) + in;
+ Sample lpfOut = weirdMul(last, filterFactor, 0xFF) + in;
// store lpfOut multiplied by LPF amp factor
buffer[index] = weirdMul(lpfOut, amp, 0xFF);
@@ -206,26 +228,26 @@ void DelayWithLowPassFilter::process(const Bit32s in) {
TapDelayCombFilter::TapDelayCombFilter(const Bit32u useSize, const Bit32u useFilterFactor) : CombFilter(useSize, useFilterFactor) {}
-void TapDelayCombFilter::process(const Bit32s in) {
+void TapDelayCombFilter::process(const Sample in) {
// the previously stored value
- Bit32s last = buffer[index];
+ const Sample last = buffer[index];
// move to the next index
next();
// prepare input + feedback
// Actually, the size of the filter varies with the TIME parameter, the feedback sample is taken from the position just below the right output
- Bit32s filterIn = in + weirdMul(getOutputAt(outR + MODE_3_FEEDBACK_DELAY), feedbackFactor, 0xF0);
+ const Sample filterIn = in + weirdMul(getOutputAt(outR + MODE_3_FEEDBACK_DELAY), feedbackFactor, 0xF0);
// store input + feedback processed by a low-pass filter
buffer[index] = weirdMul(last, filterFactor, 0xF0) - filterIn;
}
-Bit32s TapDelayCombFilter::getLeftOutput() const {
+Sample TapDelayCombFilter::getLeftOutput() const {
return getOutputAt(outL + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY);
}
-Bit32s TapDelayCombFilter::getRightOutput() const {
+Sample TapDelayCombFilter::getRightOutput() const {
return getOutputAt(outR + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY);
}
@@ -327,14 +349,14 @@ bool BReverbModel::isActive() const {
return false;
}
-void BReverbModel::process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) {
- Bit32s dry, link, outL1, outR1;
+void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples) {
+ Sample dry;
- for (unsigned long i = 0; i < numSamples; i++) {
+ while (numSamples > 0) {
if (tapDelayMode) {
- dry = Bit32s(*inLeft * 8192.0f) + Bit32s(*inRight * 8192.0f);
+ dry = *inLeft + *inRight;
} else {
- dry = Bit32s(*inLeft * 8192.0f) / 2 + Bit32s(*inRight * 8192.0f) / 2;
+ dry = *inLeft / 2 + *inRight / 2;
}
// Looks like dryAmp doesn't change in MT-32 but it does in CM-32L / LAPC-I
@@ -343,44 +365,53 @@ void BReverbModel::process(const float *inLeft, const float *inRight, float *out
if (tapDelayMode) {
TapDelayCombFilter *comb = static_cast<TapDelayCombFilter *> (*combs);
comb->process(dry);
- *outLeft = weirdMul(comb->getLeftOutput(), wetLevel, 0xFF) / 8192.0f;
- *outRight = weirdMul(comb->getRightOutput(), wetLevel, 0xFF) / 8192.0f;
+ *outLeft = weirdMul(comb->getLeftOutput(), wetLevel, 0xFF);
+ *outRight = weirdMul(comb->getRightOutput(), wetLevel, 0xFF);
} else {
- // Get the last stored sample before processing in order not to loose it
- link = combs[0]->getOutputAt(currentSettings.combSizes[0] - 1);
+ // If the output position is equal to the comb size, get it now in order not to loose it
+ Sample link = combs[0]->getOutputAt(currentSettings.combSizes[0] - 1);
// Entrance LPF. Note, comb.process() differs a bit here.
combs[0]->process(dry);
+#if !MT32EMU_USE_FLOAT_SAMPLES
// This introduces reverb noise which actually makes output from the real Boss chip nondeterministic
link = link - 1;
+#endif
link = allpasses[0]->process(link);
link = allpasses[1]->process(link);
link = allpasses[2]->process(link);
// If the output position is equal to the comb size, get it now in order not to loose it
- outL1 = combs[1]->getOutputAt(currentSettings.outLPositions[0] - 1);
- outL1 += outL1 >> 1;
+ Sample outL1 = combs[1]->getOutputAt(currentSettings.outLPositions[0] - 1);
combs[1]->process(link);
combs[2]->process(link);
combs[3]->process(link);
- link = combs[2]->getOutputAt(currentSettings.outLPositions[1]);
- link += link >> 1;
- link += outL1;
- link += combs[3]->getOutputAt(currentSettings.outLPositions[2]);
- *outLeft = weirdMul(link, wetLevel, 0xFF) / 8192.0f;
+ Sample outL2 = combs[2]->getOutputAt(currentSettings.outLPositions[1]);
+ Sample outL3 = combs[3]->getOutputAt(currentSettings.outLPositions[2]);
+ Sample outR1 = combs[1]->getOutputAt(currentSettings.outRPositions[0]);
+ Sample outR2 = combs[2]->getOutputAt(currentSettings.outRPositions[1]);
+ Sample outR3 = combs[3]->getOutputAt(currentSettings.outRPositions[2]);
+
+#if MT32EMU_USE_FLOAT_SAMPLES
+ *outLeft = 1.5f * (outL1 + outL2) + outL3;
+ *outRight = 1.5f * (outR1 + outR2) + outR3;
+#else
+ outL1 += outL1 >> 1;
+ outL2 += outL2 >> 1;
+ *outLeft = outL1 + outL2 + outL3;
- outR1 = combs[1]->getOutputAt(currentSettings.outRPositions[0]);
outR1 += outR1 >> 1;
- link = combs[2]->getOutputAt(currentSettings.outRPositions[1]);
- link += link >> 1;
- link += outR1;
- link += combs[3]->getOutputAt(currentSettings.outRPositions[2]);
- *outRight = weirdMul(link, wetLevel, 0xFF) / 8192.0f;
+ outR2 += outR2 >> 1;
+ *outRight = outR1 + outR2 + outR3;
+#endif
+ *outLeft = weirdMul(*outLeft, wetLevel, 0xFF);
+ *outRight = weirdMul(*outRight, wetLevel, 0xFF);
}
+ numSamples--;
inLeft++;
inRight++;
outLeft++;
@@ -389,5 +420,3 @@ void BReverbModel::process(const float *inLeft, const float *inRight, float *out
}
}
-
-#endif
diff --git a/audio/softsynth/mt32/BReverbModel.h b/audio/softsynth/mt32/BReverbModel.h
index d6fcb73c13..7cf431db0d 100644
--- a/audio/softsynth/mt32/BReverbModel.h
+++ b/audio/softsynth/mt32/BReverbModel.h
@@ -36,14 +36,14 @@ struct BReverbSettings {
class RingBuffer {
protected:
- Bit16s *buffer;
+ Sample *buffer;
const Bit32u size;
Bit32u index;
public:
RingBuffer(const Bit32u size);
virtual ~RingBuffer();
- Bit32s next();
+ Sample next();
bool isEmpty() const;
void mute();
};
@@ -51,7 +51,7 @@ public:
class AllpassFilter : public RingBuffer {
public:
AllpassFilter(const Bit32u size);
- Bit32s process(const Bit32s in);
+ Sample process(const Sample in);
};
class CombFilter : public RingBuffer {
@@ -61,8 +61,8 @@ protected:
public:
CombFilter(const Bit32u size, const Bit32u useFilterFactor);
- virtual void process(const Bit32s in); // Actually, no need to make it virtual, but for sure
- Bit32s getOutputAt(const Bit32u outIndex) const;
+ virtual void process(const Sample in);
+ Sample getOutputAt(const Bit32u outIndex) const;
void setFeedbackFactor(const Bit32u useFeedbackFactor);
};
@@ -71,7 +71,7 @@ class DelayWithLowPassFilter : public CombFilter {
public:
DelayWithLowPassFilter(const Bit32u useSize, const Bit32u useFilterFactor, const Bit32u useAmp);
- void process(const Bit32s in);
+ void process(const Sample in);
void setFeedbackFactor(const Bit32u) {}
};
@@ -81,13 +81,13 @@ class TapDelayCombFilter : public CombFilter {
public:
TapDelayCombFilter(const Bit32u useSize, const Bit32u useFilterFactor);
- void process(const Bit32s in);
- Bit32s getLeftOutput() const;
- Bit32s getRightOutput() const;
+ void process(const Sample in);
+ Sample getLeftOutput() const;
+ Sample getRightOutput() const;
void setOutputPositions(const Bit32u useOutL, const Bit32u useOutR);
};
-class BReverbModel : public ReverbModel {
+class BReverbModel {
AllpassFilter **allpasses;
CombFilter **combs;
@@ -100,10 +100,12 @@ class BReverbModel : public ReverbModel {
public:
BReverbModel(const ReverbMode mode);
~BReverbModel();
+ // After construction or a close(), open() must be called at least once before any other call (with the exception of close()).
void open();
+ // May be called multiple times without an open() in between.
void close();
void setParameters(Bit8u time, Bit8u level);
- void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
+ void process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples);
bool isActive() const;
};
diff --git a/audio/softsynth/mt32/DelayReverb.cpp b/audio/softsynth/mt32/DelayReverb.cpp
deleted file mode 100644
index d80c98acbc..0000000000
--- a/audio/softsynth/mt32/DelayReverb.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-//#include <cmath>
-//#include <cstring>
-#include "mt32emu.h"
-#include "DelayReverb.h"
-
-namespace MT32Emu {
-
-// CONFIRMED: The values below are found via analysis of digital samples and tracing reverb RAM address / data lines. Checked with all time and level combinations.
-// Obviously:
-// rightDelay = (leftDelay - 2) * 2 + 2
-// echoDelay = rightDelay - 1
-// Leaving these separate in case it's useful for work on other reverb modes...
-static const Bit32u REVERB_TIMINGS[8][3]= {
- // {leftDelay, rightDelay, feedbackDelay}
- {402, 802, 801},
- {626, 1250, 1249},
- {962, 1922, 1921},
- {1490, 2978, 2977},
- {2258, 4514, 4513},
- {3474, 6946, 6945},
- {5282, 10562, 10561},
- {8002, 16002, 16001}
-};
-
-// Reverb amp is found as dryAmp * wetAmp
-static const Bit32u REVERB_AMP[8] = {0x20*0x18, 0x50*0x18, 0x50*0x28, 0x50*0x40, 0x50*0x60, 0x50*0x80, 0x50*0xA8, 0x50*0xF8};
-static const Bit32u REVERB_FEEDBACK67 = 0x60;
-static const Bit32u REVERB_FEEDBACK = 0x68;
-static const float LPF_VALUE = 0x68 / 256.0f;
-
-static const Bit32u BUFFER_SIZE = 16384;
-
-DelayReverb::DelayReverb() {
- buf = NULL;
- setParameters(0, 0);
-}
-
-DelayReverb::~DelayReverb() {
- delete[] buf;
-}
-
-void DelayReverb::open() {
- if (buf == NULL) {
- delete[] buf;
-
- buf = new float[BUFFER_SIZE];
-
- recalcParameters();
-
- // mute buffer
- bufIx = 0;
- if (buf != NULL) {
- for (unsigned int i = 0; i < BUFFER_SIZE; i++) {
- buf[i] = 0.0f;
- }
- }
- }
-}
-
-void DelayReverb::close() {
- delete[] buf;
- buf = NULL;
-}
-
-// This method will always trigger a flush of the buffer
-void DelayReverb::setParameters(Bit8u newTime, Bit8u newLevel) {
- time = newTime;
- level = newLevel;
- recalcParameters();
-}
-
-void DelayReverb::recalcParameters() {
- // Number of samples between impulse and eventual appearance on the left channel
- delayLeft = REVERB_TIMINGS[time][0];
- // Number of samples between impulse and eventual appearance on the right channel
- delayRight = REVERB_TIMINGS[time][1];
- // Number of samples between a response and that response feeding back/echoing
- delayFeedback = REVERB_TIMINGS[time][2];
-
- if (level < 3 || time < 6) {
- feedback = REVERB_FEEDBACK / 256.0f;
- } else {
- feedback = REVERB_FEEDBACK67 / 256.0f;
- }
-
- // Overall output amp
- amp = (level == 0 && time == 0) ? 0.0f : REVERB_AMP[level] / 65536.0f;
-}
-
-void DelayReverb::process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) {
- if (buf == NULL) return;
-
- for (unsigned int sampleIx = 0; sampleIx < numSamples; sampleIx++) {
- // The ring buffer write index moves backwards; reads are all done with positive offsets.
- Bit32u bufIxPrev = (bufIx + 1) % BUFFER_SIZE;
- Bit32u bufIxLeft = (bufIx + delayLeft) % BUFFER_SIZE;
- Bit32u bufIxRight = (bufIx + delayRight) % BUFFER_SIZE;
- Bit32u bufIxFeedback = (bufIx + delayFeedback) % BUFFER_SIZE;
-
- // Attenuated input samples and feedback response are directly added to the current ring buffer location
- float lpfIn = amp * (inLeft[sampleIx] + inRight[sampleIx]) + feedback * buf[bufIxFeedback];
-
- // Single-pole IIR filter found on real devices
- buf[bufIx] = buf[bufIxPrev] * LPF_VALUE - lpfIn;
-
- outLeft[sampleIx] = buf[bufIxLeft];
- outRight[sampleIx] = buf[bufIxRight];
-
- bufIx = (BUFFER_SIZE + bufIx - 1) % BUFFER_SIZE;
- }
-}
-
-bool DelayReverb::isActive() const {
- if (buf == NULL) return false;
-
- float *b = buf;
- float max = 0.001f;
- for (Bit32u i = 0; i < BUFFER_SIZE; i++) {
- if ((*b < -max) || (*b > max)) return true;
- b++;
- }
- return false;
-}
-
-}
diff --git a/audio/softsynth/mt32/DelayReverb.h b/audio/softsynth/mt32/DelayReverb.h
deleted file mode 100644
index c8003832b5..0000000000
--- a/audio/softsynth/mt32/DelayReverb.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MT32EMU_DELAYREVERB_H
-#define MT32EMU_DELAYREVERB_H
-
-namespace MT32Emu {
-
-class DelayReverb : public ReverbModel {
-private:
- Bit8u time;
- Bit8u level;
-
- Bit32u bufIx;
- float *buf;
-
- Bit32u delayLeft;
- Bit32u delayRight;
- Bit32u delayFeedback;
-
- float amp;
- float feedback;
-
- void recalcParameters();
-
-public:
- DelayReverb();
- ~DelayReverb();
- void open();
- void close();
- void setParameters(Bit8u time, Bit8u level);
- void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
- bool isActive() const;
-};
-}
-#endif
diff --git a/audio/softsynth/mt32/FreeverbModel.cpp b/audio/softsynth/mt32/FreeverbModel.cpp
deleted file mode 100644
index bd9c70b6f4..0000000000
--- a/audio/softsynth/mt32/FreeverbModel.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "mt32emu.h"
-#include "FreeverbModel.h"
-
-#include "freeverb.h"
-
-namespace MT32Emu {
-
-FreeverbModel::FreeverbModel(float useScaleTuning, float useFiltVal, float useWet, Bit8u useRoom, float useDamp) {
- freeverb = NULL;
- scaleTuning = useScaleTuning;
- filtVal = useFiltVal;
- wet = useWet;
- room = useRoom;
- damp = useDamp;
-}
-
-FreeverbModel::~FreeverbModel() {
- delete freeverb;
-}
-
-void FreeverbModel::open() {
- if (freeverb == NULL) {
- freeverb = new revmodel(scaleTuning);
- }
- freeverb->mute();
-
- // entrance Lowpass filter factor
- freeverb->setfiltval(filtVal);
-
- // decay speed of high frequencies in the wet signal
- freeverb->setdamp(damp);
-}
-
-void FreeverbModel::close() {
- delete freeverb;
- freeverb = NULL;
-}
-
-void FreeverbModel::process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) {
- freeverb->process(inLeft, inRight, outLeft, outRight, numSamples);
-}
-
-void FreeverbModel::setParameters(Bit8u time, Bit8u level) {
- // wet signal level
- // FIXME: need to implement some sort of reverb level ramping
- freeverb->setwet((float)level / 7.0f * wet);
-
- // wet signal decay speed
- static float roomTable[] = {
- 0.25f, 0.37f, 0.54f, 0.71f, 0.78f, 0.86f, 0.93f, 1.00f,
- -1.00f, -0.50f, 0.00f, 0.30f, 0.51f, 0.64f, 0.77f, 0.90f,
- 0.50f, 0.57f, 0.70f, 0.77f, 0.85f, 0.93f, 0.96f, 1.01f};
- freeverb->setroomsize(roomTable[8 * room + time]);
-}
-
-bool FreeverbModel::isActive() const {
- // FIXME: Not bothering to do this properly since we'll be replacing Freeverb soon...
- return false;
-}
-
-}
diff --git a/audio/softsynth/mt32/FreeverbModel.h b/audio/softsynth/mt32/FreeverbModel.h
deleted file mode 100644
index 5ea11f1f40..0000000000
--- a/audio/softsynth/mt32/FreeverbModel.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MT32EMU_FREEVERB_MODEL_H
-#define MT32EMU_FREEVERB_MODEL_H
-
-class revmodel;
-
-namespace MT32Emu {
-
-class FreeverbModel : public ReverbModel {
- revmodel *freeverb;
- float scaleTuning;
- float filtVal;
- float wet;
- Bit8u room;
- float damp;
-public:
- FreeverbModel(float useScaleTuning, float useFiltVal, float useWet, Bit8u useRoom, float useDamp);
- ~FreeverbModel();
- void open();
- void close();
- void setParameters(Bit8u time, Bit8u level);
- void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
- bool isActive() const;
-};
-
-}
-
-#endif
diff --git a/audio/softsynth/mt32/LegacyWaveGenerator.cpp b/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp
index 35ca975018..0c9687b4d8 100644
--- a/audio/softsynth/mt32/LegacyWaveGenerator.cpp
+++ b/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp
@@ -18,9 +18,7 @@
//#include <cmath>
#include "mt32emu.h"
#include "mmath.h"
-#include "LegacyWaveGenerator.h"
-
-#if MT32EMU_ACCURATE_WG == 1
+#include "LA32FloatWaveGenerator.h"
namespace MT32Emu {
@@ -317,15 +315,29 @@ void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u
}
}
-Bit16s LA32PartialPair::nextOutSample() {
- float outputSample;
- if (ringModulated) {
- float ringModulatedSample = masterOutputSample * slaveOutputSample;
- outputSample = mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample;
- } else {
- outputSample = masterOutputSample + slaveOutputSample;
+static inline float produceDistortedSample(float sample) {
+ if (sample < -1.0f) {
+ return sample + 2.0f;
+ } else if (1.0f < sample) {
+ return sample - 2.0f;
}
- return Bit16s(outputSample * 8192.0f);
+ return sample;
+}
+
+float LA32PartialPair::nextOutSample() {
+ if (!ringModulated) {
+ return masterOutputSample + slaveOutputSample;
+ }
+ /*
+ * SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion.
+ * LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191.
+ * This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case.
+ * As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space,
+ * it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication.
+ * Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning.
+ */
+ float ringModulatedSample = produceDistortedSample(masterOutputSample) * produceDistortedSample(slaveOutputSample);
+ return mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample;
}
void LA32PartialPair::deactivate(const PairType useMaster) {
@@ -343,5 +355,3 @@ bool LA32PartialPair::isActive(const PairType useMaster) const {
}
}
-
-#endif // #if MT32EMU_ACCURATE_WG == 1
diff --git a/audio/softsynth/mt32/LegacyWaveGenerator.h b/audio/softsynth/mt32/LA32FloatWaveGenerator.h
index 81c1b9c713..9046160083 100644
--- a/audio/softsynth/mt32/LegacyWaveGenerator.h
+++ b/audio/softsynth/mt32/LA32FloatWaveGenerator.h
@@ -15,8 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#if MT32EMU_ACCURATE_WG == 1
-
#ifndef MT32EMU_LA32_WAVE_GENERATOR_H
#define MT32EMU_LA32_WAVE_GENERATOR_H
@@ -130,7 +128,7 @@ public:
void generateNextSample(const PairType master, const Bit32u amp, const Bit16u pitch, const Bit32u cutoff);
// Perform mixing / ring modulation and return the result
- Bit16s nextOutSample();
+ float nextOutSample();
// Deactivate the WG engine
void deactivate(const PairType master);
@@ -142,5 +140,3 @@ public:
} // namespace MT32Emu
#endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H
-
-#endif // #if MT32EMU_ACCURATE_WG == 1
diff --git a/audio/softsynth/mt32/LA32WaveGenerator.cpp b/audio/softsynth/mt32/LA32WaveGenerator.cpp
index 80650699fb..1d115c12ef 100644
--- a/audio/softsynth/mt32/LA32WaveGenerator.cpp
+++ b/audio/softsynth/mt32/LA32WaveGenerator.cpp
@@ -20,7 +20,9 @@
#include "mmath.h"
#include "LA32WaveGenerator.h"
-#if MT32EMU_ACCURATE_WG == 0
+#if MT32EMU_USE_FLOAT_SAMPLES
+#include "LA32FloatWaveGenerator.cpp"
+#else
namespace MT32Emu {
@@ -129,7 +131,8 @@ void LA32WaveGenerator::advancePosition() {
computePositions(highLinearLength, lowLinearLength, resonanceWaveLengthFactor);
// resonancePhase computation hack
- *(int*)&resonancePhase = ((resonanceSinePosition >> 18) + (phase > POSITIVE_FALLING_SINE_SEGMENT ? 2 : 0)) & 3;
+ int *resonancePhaseAlias = (int *)&resonancePhase;
+ *resonancePhaseAlias = ((resonanceSinePosition >> 18) + (phase > POSITIVE_FALLING_SINE_SEGMENT ? 2 : 0)) & 3;
}
void LA32WaveGenerator::generateNextSquareWaveLogSample() {
@@ -367,18 +370,12 @@ void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u
}
}
-Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample) {
- if (!wg.isActive() || ((ringModulatingLogSample != NULL) && (ringModulatingLogSample->logValue == SILENCE.logValue))) {
+Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg) {
+ if (!wg.isActive()) {
return 0;
}
- LogSample firstLogSample = wg.getOutputLogSample(true);
- LogSample secondLogSample = wg.getOutputLogSample(false);
- if (ringModulatingLogSample != NULL) {
- LA32Utilites::addLogSamples(firstLogSample, *ringModulatingLogSample);
- LA32Utilites::addLogSamples(secondLogSample, *ringModulatingLogSample);
- }
- Bit16s firstSample = LA32Utilites::unlog(firstLogSample);
- Bit16s secondSample = LA32Utilites::unlog(secondLogSample);
+ Bit16s firstSample = LA32Utilites::unlog(wg.getOutputLogSample(true));
+ Bit16s secondSample = LA32Utilites::unlog(wg.getOutputLogSample(false));
if (wg.isPCMWave()) {
return Bit16s(firstSample + ((Bit32s(secondSample - firstSample) * wg.getPCMInterpolationFactor()) >> 7));
}
@@ -386,19 +383,32 @@ Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg, const L
}
Bit16s LA32PartialPair::nextOutSample() {
- if (ringModulated) {
- LogSample slaveFirstLogSample = slave.getOutputLogSample(true);
- LogSample slaveSecondLogSample = slave.getOutputLogSample(false);
- Bit16s sample = unlogAndMixWGOutput(master, &slaveFirstLogSample);
- if (!slave.isPCMWave()) {
- sample += unlogAndMixWGOutput(master, &slaveSecondLogSample);
- }
- if (mixed) {
- sample += unlogAndMixWGOutput(master, NULL);
- }
- return sample;
+ if (!ringModulated) {
+ return unlogAndMixWGOutput(master) + unlogAndMixWGOutput(slave);
}
- return unlogAndMixWGOutput(master, NULL) + unlogAndMixWGOutput(slave, NULL);
+
+ /*
+ * SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion.
+ * LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191.
+ * This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case.
+ * As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space,
+ * it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication.
+ * Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning.
+ */
+ Bit16s nonOverdrivenMasterSample = unlogAndMixWGOutput(master); // Store master partial sample for further mixing
+ Bit16s masterSample = nonOverdrivenMasterSample << 2;
+ masterSample >>= 2;
+
+ /* SEMI-CONFIRMED from sample analysis:
+ * We observe that for partial structures with ring modulation the interpolation is not applied to the slave PCM partial.
+ * It's assumed that the multiplication circuitry intended to perform the interpolation on the slave PCM partial
+ * is borrowed by the ring modulation circuit (or the LA32 chip has a similar lack of resources assigned to each partial pair).
+ */
+ Bit16s slaveSample = slave.isPCMWave() ? LA32Utilites::unlog(slave.getOutputLogSample(true)) : unlogAndMixWGOutput(slave);
+ slaveSample <<= 2;
+ slaveSample >>= 2;
+ Bit16s ringModulatedSample = Bit16s(((Bit32s)masterSample * (Bit32s)slaveSample) >> 13);
+ return mixed ? nonOverdrivenMasterSample + ringModulatedSample : ringModulatedSample;
}
void LA32PartialPair::deactivate(const PairType useMaster) {
@@ -415,4 +425,4 @@ bool LA32PartialPair::isActive(const PairType useMaster) const {
}
-#endif // #if MT32EMU_ACCURATE_WG == 0
+#endif // #if MT32EMU_USE_FLOAT_SAMPLES
diff --git a/audio/softsynth/mt32/LA32WaveGenerator.h b/audio/softsynth/mt32/LA32WaveGenerator.h
index 37a4aead85..b5f4dedff4 100644
--- a/audio/softsynth/mt32/LA32WaveGenerator.h
+++ b/audio/softsynth/mt32/LA32WaveGenerator.h
@@ -15,7 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#if MT32EMU_ACCURATE_WG == 0
+#if MT32EMU_USE_FLOAT_SAMPLES
+#include "LA32FloatWaveGenerator.h"
+#else
#ifndef MT32EMU_LA32_WAVE_GENERATOR_H
#define MT32EMU_LA32_WAVE_GENERATOR_H
@@ -207,7 +209,7 @@ class LA32PartialPair {
bool ringModulated;
bool mixed;
- static Bit16s unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample);
+ static Bit16s unlogAndMixWGOutput(const LA32WaveGenerator &wg);
public:
enum PairType {
@@ -243,4 +245,4 @@ public:
#endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H
-#endif // #if MT32EMU_ACCURATE_WG == 0
+#endif // #if MT32EMU_USE_FLOAT_SAMPLES
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index 62ba346c35..8a0daf3b38 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -67,18 +67,12 @@ Part::Part(Synth *useSynth, unsigned int usePartNum) {
pitchBend = 0;
activePartialCount = 0;
memset(patchCache, 0, sizeof(patchCache));
- for (int i = 0; i < MT32EMU_MAX_POLY; i++) {
- freePolys.prepend(new Poly(this));
- }
}
Part::~Part() {
while (!activePolys.isEmpty()) {
delete activePolys.takeFirst();
}
- while (!freePolys.isEmpty()) {
- delete freePolys.takeFirst();
- }
}
void Part::setDataEntryMSB(unsigned char midiDataEntryMSB) {
@@ -175,6 +169,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 +202,6 @@ void RhythmPart::setTimbre(TimbreParam * /*timbre*/) {
void Part::setTimbre(TimbreParam *timbre) {
*timbreTemp = *timbre;
- synth->newTimbreSet(partNum, timbre->common.name);
}
unsigned int RhythmPart::getAbsTimbreNum() const {
@@ -431,23 +425,10 @@ void Part::noteOn(unsigned int midiKey, unsigned int velocity) {
playPoly(patchCache, NULL, midiKey, key, velocity);
}
-void Part::abortPoly(Poly *poly) {
- if (poly->startAbort()) {
- while (poly->isActive()) {
- if (!synth->prerender()) {
- synth->printDebug("%s (%s): Ran out of prerender space to abort poly gracefully", name, currentInstr);
- poly->terminate();
- break;
- }
- }
- }
-}
-
bool Part::abortFirstPoly(unsigned int key) {
for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) {
if (poly->getKey() == key) {
- abortPoly(poly);
- return true;
+ return poly->startAbort();
}
}
return false;
@@ -456,8 +437,7 @@ bool Part::abortFirstPoly(unsigned int key) {
bool Part::abortFirstPoly(PolyState polyState) {
for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) {
if (poly->getState() == polyState) {
- abortPoly(poly);
- return true;
+ return poly->startAbort();
}
}
return false;
@@ -474,8 +454,7 @@ bool Part::abortFirstPoly() {
if (activePolys.isEmpty()) {
return false;
}
- abortPoly(activePolys.getFirst());
- return true;
+ return activePolys.getFirst()->startAbort();
}
void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhythmTemp, unsigned int midiKey, unsigned int key, unsigned int velocity) {
@@ -489,6 +468,7 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt
if ((patchTemp->patch.assignMode & 2) == 0) {
// Single-assign mode
abortFirstPoly(key);
+ if (synth->isAbortingPoly()) return;
}
if (!synth->partialManager->freePartials(needPartials, partNum)) {
@@ -498,12 +478,13 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt
#endif
return;
}
+ if (synth->isAbortingPoly()) return;
- if (freePolys.isEmpty()) {
+ Poly *poly = synth->partialManager->assignPolyToPart(this);
+ if (poly == NULL) {
synth->printDebug("%s (%s): No free poly to play key %d (velocity %d)", name, currentInstr, midiKey, velocity);
return;
}
- Poly *poly = freePolys.takeFirst();
if (patchTemp->patch.assignMode & 1) {
// Priority to data first received
activePolys.prepend(poly);
@@ -533,7 +514,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);
}
@@ -597,6 +577,10 @@ unsigned int Part::getActivePartialCount() const {
return activePartialCount;
}
+const Poly *Part::getFirstActivePoly() const {
+ return activePolys.getFirst();
+}
+
unsigned int Part::getActiveNonReleasingPartialCount() const {
unsigned int activeNonReleasingPartialCount = 0;
for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) {
@@ -607,16 +591,17 @@ unsigned int Part::getActiveNonReleasingPartialCount() const {
return activeNonReleasingPartialCount;
}
+Synth *Part::getSynth() const {
+ return synth;
+}
+
void Part::partialDeactivated(Poly *poly) {
activePartialCount--;
if (!poly->isActive()) {
activePolys.remove(poly);
- freePolys.prepend(poly);
+ synth->partialManager->polyFreed(poly);
synth->polyStateChanged(partNum);
}
- if (activePartialCount == 0) {
- synth->partStateChanged(partNum, false);
- }
}
//#define POLY_LIST_DEBUG
diff --git a/audio/softsynth/mt32/Part.h b/audio/softsynth/mt32/Part.h
index b6585880fe..2aeeaf5bd7 100644
--- a/audio/softsynth/mt32/Part.h
+++ b/audio/softsynth/mt32/Part.h
@@ -51,13 +51,11 @@ private:
unsigned int activePartialCount;
PatchCache patchCache[4];
- PolyList freePolys;
PolyList activePolys;
void setPatch(const PatchParam *patch);
unsigned int midiKeyToKey(unsigned int midiKey);
- void abortPoly(Poly *poly);
bool abortFirstPoly(unsigned int key);
protected:
@@ -110,8 +108,10 @@ public:
virtual void setTimbre(TimbreParam *timbre);
virtual unsigned int getAbsTimbreNum() const;
const char *getCurrentInstr() const;
+ const Poly *getFirstActivePoly() const;
unsigned int getActivePartialCount() const;
unsigned int getActiveNonReleasingPartialCount() const;
+ Synth *getSynth() const;
const MemParams::PatchTemp *getPatchTemp() const;
diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp
index a0aec90ec4..75e674074f 100644
--- a/audio/softsynth/mt32/Partial.cpp
+++ b/audio/softsynth/mt32/Partial.cpp
@@ -24,15 +24,10 @@
namespace MT32Emu {
-#ifdef INACCURATE_SMOOTH_PAN
-// Mok wanted an option for smoother panning, and we love Mok.
-static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f};
-#else
-// CONFIRMED by Mok: These NUMERATOR values (as bytes, not floats, obviously) are sent exactly like this to the LA32.
-static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f, 7.0f};
-#endif
-static const float PAN_NUMERATOR_MASTER[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
-static const float PAN_NUMERATOR_SLAVE[] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f};
+static const Bit8u PAN_NUMERATOR_MASTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7};
+static const Bit8u PAN_NUMERATOR_SLAVE[] = {0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7};
+
+static const Bit32s PAN_FACTORS[] = {0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256};
Partial::Partial(Synth *useSynth, int useDebugPartialNum) :
synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0) {
@@ -87,7 +82,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);
@@ -117,23 +111,30 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
structurePosition = patchCache->structurePosition;
Bit8u panSetting = rhythmTemp != NULL ? rhythmTemp->panpot : part->getPatchTemp()->panpot;
- float panVal;
if (mixType == 3) {
if (structurePosition == 0) {
- panVal = PAN_NUMERATOR_MASTER[panSetting];
+ panSetting = PAN_NUMERATOR_MASTER[panSetting] << 1;
} else {
- panVal = PAN_NUMERATOR_SLAVE[panSetting];
+ panSetting = PAN_NUMERATOR_SLAVE[panSetting] << 1;
}
// Do a normal mix independent of any pair partial.
mixType = 0;
pairPartial = NULL;
} else {
- panVal = PAN_NUMERATOR_NORMAL[panSetting];
+ // Mok wanted an option for smoother panning, and we love Mok.
+#ifndef INACCURATE_SMOOTH_PAN
+ // CONFIRMED by Mok: exactly bytes like this (right shifted?) are sent to the LA32.
+ panSetting &= 0x0E;
+#endif
}
- // FIXME: Sample analysis suggests that the use of panVal is linear, but there are some some quirks that still need to be resolved.
- stereoVolume.leftVol = panVal / 7.0f;
- stereoVolume.rightVol = 1.0f - stereoVolume.leftVol;
+ leftPanValue = synth->reversedStereoEnabled ? 14 - panSetting : panSetting;
+ rightPanValue = 14 - leftPanValue;
+
+#if !MT32EMU_USE_FLOAT_SAMPLES
+ leftPanValue = PAN_FACTORS[leftPanValue];
+ rightPanValue = PAN_FACTORS[rightPanValue];
+#endif
// SEMI-CONFIRMED: From sample analysis:
// Found that timbres with 3 or 4 partials (i.e. one using two partial pairs) are mixed in two different ways.
@@ -150,8 +151,8 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
// For my personal taste, this behaviour rather enriches the sounding and should be emulated.
// Also, the current partial allocator model probably needs to be refined.
if (debugPartialNum & 8) {
- stereoVolume.leftVol = -stereoVolume.leftVol;
- stereoVolume.rightVol = -stereoVolume.rightVol;
+ leftPanValue = -leftPanValue;
+ rightPanValue = -rightPanValue;
}
if (patchCache->PCMPartial) {
@@ -199,9 +200,6 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
if (!hasRingModulatingSlave()) {
la32Pair.deactivate(LA32PartialPair::SLAVE);
}
- // Temporary integration hack
- stereoVolume.leftVol /= 8192.0f;
- stereoVolume.rightVol /= 8192.0f;
}
Bit32u Partial::getAmpValue() {
@@ -233,39 +231,6 @@ Bit32u Partial::getCutoffValue() {
return (tvf->getBaseCutoff() << 18) + cutoffModifierRampVal;
}
-unsigned long Partial::generateSamples(Bit16s *partialBuf, unsigned long length) {
- if (!isActive() || alreadyOutputed) {
- return 0;
- }
- if (poly == NULL) {
- synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::generateSamples()!", debugPartialNum);
- return 0;
- }
- alreadyOutputed = true;
-
- for (sampleNum = 0; sampleNum < length; sampleNum++) {
- if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) {
- deactivate();
- break;
- }
- la32Pair.generateNextSample(LA32PartialPair::MASTER, getAmpValue(), tvp->nextPitch(), getCutoffValue());
- if (hasRingModulatingSlave()) {
- la32Pair.generateNextSample(LA32PartialPair::SLAVE, pair->getAmpValue(), pair->tvp->nextPitch(), pair->getCutoffValue());
- if (!pair->tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::SLAVE)) {
- pair->deactivate();
- if (mixType == 2) {
- deactivate();
- break;
- }
- }
- }
- *partialBuf++ = la32Pair.nextOutSample();
- }
- unsigned long renderedSamples = sampleNum;
- sampleNum = 0;
- return renderedSamples;
-}
-
bool Partial::hasRingModulatingSlave() const {
return pair != NULL && structurePosition == 0 && (mixType == 1 || mixType == 2);
}
@@ -289,7 +254,18 @@ Synth *Partial::getSynth() const {
return synth;
}
-bool Partial::produceOutput(float *leftBuf, float *rightBuf, unsigned long length) {
+TVA *Partial::getTVA() const {
+ return tva;
+}
+
+void Partial::backupCache(const PatchCache &cache) {
+ if (patchCache == &cache) {
+ cachebackup = cache;
+ patchCache = &cachebackup;
+ }
+}
+
+bool Partial::produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length) {
if (!isActive() || alreadyOutputed || isRingModulatingSlave()) {
return false;
}
@@ -297,15 +273,52 @@ bool Partial::produceOutput(float *leftBuf, float *rightBuf, unsigned long lengt
synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum);
return false;
}
- unsigned long numGenerated = generateSamples(myBuffer, length);
- for (unsigned int i = 0; i < numGenerated; i++) {
- *leftBuf++ = myBuffer[i] * stereoVolume.leftVol;
- *rightBuf++ = myBuffer[i] * stereoVolume.rightVol;
- }
- for (; numGenerated < length; numGenerated++) {
- *leftBuf++ = 0.0f;
- *rightBuf++ = 0.0f;
+ alreadyOutputed = true;
+
+ for (sampleNum = 0; sampleNum < length; sampleNum++) {
+ if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) {
+ deactivate();
+ break;
+ }
+ la32Pair.generateNextSample(LA32PartialPair::MASTER, getAmpValue(), tvp->nextPitch(), getCutoffValue());
+ if (hasRingModulatingSlave()) {
+ la32Pair.generateNextSample(LA32PartialPair::SLAVE, pair->getAmpValue(), pair->tvp->nextPitch(), pair->getCutoffValue());
+ if (!pair->tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::SLAVE)) {
+ pair->deactivate();
+ if (mixType == 2) {
+ deactivate();
+ break;
+ }
+ }
+ }
+
+ // Although, LA32 applies panning itself, we assume here it is applied in the mixer, not within a pair.
+ // Applying the pan value in the log-space looks like a waste of unlog resources. Though, it needs clarification.
+ Sample sample = la32Pair.nextOutSample();
+
+ // FIXME: Sample analysis suggests that the use of panVal is linear, but there are some quirks that still need to be resolved.
+#if MT32EMU_USE_FLOAT_SAMPLES
+ Sample leftOut = (sample * (float)leftPanValue) / 14.0f;
+ Sample rightOut = (sample * (float)rightPanValue) / 14.0f;
+ *(leftBuf++) += leftOut;
+ *(rightBuf++) += rightOut;
+#else
+ // FIXME: Dividing by 7 (or by 14 in a Mok-friendly way) looks of course pointless. Need clarification.
+ // FIXME2: LA32 may produce distorted sound in case if the absolute value of maximal amplitude of the input exceeds 8191
+ // when the panning value is non-zero. Most probably the distortion occurs in the same way it does with ring modulation,
+ // and it seems to be caused by limited precision of the common multiplication circuit.
+ // From analysis of this overflow, it is obvious that the right channel output is actually found
+ // by subtraction of the left channel output from the input.
+ // Though, it is unknown whether this overflow is exploited somewhere.
+ Sample leftOut = Sample((sample * leftPanValue) >> 8);
+ Sample rightOut = Sample((sample * rightPanValue) >> 8);
+ *leftBuf = Synth::clipBit16s((Bit32s)*leftBuf + (Bit32s)leftOut);
+ *rightBuf = Synth::clipBit16s((Bit32s)*rightBuf + (Bit32s)rightOut);
+ leftBuf++;
+ rightBuf++;
+#endif
}
+ sampleNum = 0;
return true;
}
diff --git a/audio/softsynth/mt32/Partial.h b/audio/softsynth/mt32/Partial.h
index 21b1bfe376..05c1c740c4 100644
--- a/audio/softsynth/mt32/Partial.h
+++ b/audio/softsynth/mt32/Partial.h
@@ -25,26 +25,22 @@ class Part;
class TVA;
struct ControlROMPCMStruct;
-struct StereoVolume {
- float leftVol;
- float rightVol;
-};
-
// A partial represents one of up to four waveform generators currently playing within a poly.
class Partial {
private:
Synth *synth;
const int debugPartialNum; // Only used for debugging
- // Number of the sample currently being rendered by generateSamples(), or 0 if no run is in progress
+ // Number of the sample currently being rendered by produceOutput(), or 0 if no run is in progress
// This is only kept available for debugging purposes.
unsigned long sampleNum;
+ // Actually, this is a 4-bit register but we abuse this to emulate inverted mixing.
+ // Also we double the value to enable INACCURATE_SMOOTH_PAN, with respect to MoK.
+ Bit32s leftPanValue, rightPanValue;
+
int ownerPart; // -1 if unassigned
int mixType;
int structurePosition; // 0 or 1 of a structure pair
- StereoVolume stereoVolume;
-
- Bit16s myBuffer[MAX_SAMPLES_PER_RUN];
// Only used for PCM partials
int pcmNum;
@@ -56,6 +52,11 @@ private:
int pulseWidthVal;
Poly *poly;
+ Partial *pair;
+
+ TVA *tva;
+ TVP *tvp;
+ TVF *tvf;
LA32Ramp ampRamp;
LA32Ramp cutoffModifierRamp;
@@ -63,18 +64,13 @@ private:
// TODO: This should be owned by PartialPair
LA32PartialPair la32Pair;
+ const PatchCache *patchCache;
+ PatchCache cachebackup;
+
Bit32u getAmpValue();
Bit32u getCutoffValue();
public:
- const PatchCache *patchCache;
- TVA *tva;
- TVP *tvp;
- TVF *tvf;
-
- PatchCache cachebackup;
-
- Partial *pair;
bool alreadyOutputed;
Partial(Synth *synth, int debugPartialNum);
@@ -97,14 +93,14 @@ public:
bool isPCM() const;
const ControlROMPCMStruct *getControlROMPCMStruct() const;
Synth *getSynth() const;
+ TVA *getTVA() const;
+
+ void backupCache(const PatchCache &cache);
// Returns true only if data written to buffer
// This function (unlike the one below it) returns processed stereo samples
// made from combining this single partial with its pair, if it has one.
- bool produceOutput(float *leftBuf, float *rightBuf, unsigned long length);
-
- // This function writes mono sample output to the provided buffer, and returns the number of samples written
- unsigned long generateSamples(Bit16s *partialBuf, unsigned long length);
+ bool produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length);
};
}
diff --git a/audio/softsynth/mt32/PartialManager.cpp b/audio/softsynth/mt32/PartialManager.cpp
index 436e7a353e..905b5b8cf3 100644
--- a/audio/softsynth/mt32/PartialManager.cpp
+++ b/audio/softsynth/mt32/PartialManager.cpp
@@ -25,19 +25,26 @@ namespace MT32Emu {
PartialManager::PartialManager(Synth *useSynth, Part **useParts) {
synth = useSynth;
parts = useParts;
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ partialTable = new Partial *[synth->getPartialCount()];
+ freePolys = new Poly *[synth->getPartialCount()];
+ firstFreePolyIndex = 0;
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
partialTable[i] = new Partial(synth, i);
+ freePolys[i] = new Poly();
}
}
PartialManager::~PartialManager(void) {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
delete partialTable[i];
+ if (freePolys[i] != NULL) delete freePolys[i];
}
+ delete[] partialTable;
+ delete[] freePolys;
}
void PartialManager::clearAlreadyOutputed() {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
partialTable[i]->alreadyOutputed = false;
}
}
@@ -46,12 +53,12 @@ bool PartialManager::shouldReverb(int i) {
return partialTable[i]->shouldReverb();
}
-bool PartialManager::produceOutput(int i, float *leftBuf, float *rightBuf, Bit32u bufferLength) {
+bool PartialManager::produceOutput(int i, Sample *leftBuf, Sample *rightBuf, Bit32u bufferLength) {
return partialTable[i]->produceOutput(leftBuf, rightBuf, bufferLength);
}
void PartialManager::deactivateAll() {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
partialTable[i]->deactivate();
}
}
@@ -69,7 +76,7 @@ Partial *PartialManager::allocPartial(int partNum) {
Partial *outPartial = NULL;
// Get the first inactive partial
- for (int partialNum = 0; partialNum < MT32EMU_MAX_PARTIALS; partialNum++) {
+ for (unsigned int partialNum = 0; partialNum < synth->getPartialCount(); partialNum++) {
if (!partialTable[partialNum]->isActive()) {
outPartial = partialTable[partialNum];
break;
@@ -83,7 +90,7 @@ Partial *PartialManager::allocPartial(int partNum) {
unsigned int PartialManager::getFreePartialCount(void) {
int count = 0;
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
if (!partialTable[i]->isActive()) {
count++;
}
@@ -94,7 +101,7 @@ unsigned int PartialManager::getFreePartialCount(void) {
// This function is solely used to gather data for debug output at the moment.
void PartialManager::getPerPartPartialUsage(unsigned int perPartPartialUsage[9]) {
memset(perPartPartialUsage, 0, 9 * sizeof(unsigned int));
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
if (partialTable[i]->isActive()) {
perPartPartialUsage[partialTable[i]->getOwnerPart()]++;
}
@@ -189,7 +196,7 @@ bool PartialManager::freePartials(unsigned int needed, int partNum) {
break;
}
#endif
- if (getFreePartialCount() >= needed) {
+ if (synth->isAbortingPoly() || getFreePartialCount() >= needed) {
return true;
}
}
@@ -206,7 +213,7 @@ bool PartialManager::freePartials(unsigned int needed, int partNum) {
if (!abortFirstPolyPreferHeldWhereReserveExceeded(partNum)) {
break;
}
- if (getFreePartialCount() >= needed) {
+ if (synth->isAbortingPoly() || getFreePartialCount() >= needed) {
return true;
}
}
@@ -222,7 +229,7 @@ bool PartialManager::freePartials(unsigned int needed, int partNum) {
if (!abortFirstPolyPreferHeldWhereReserveExceeded(-1)) {
break;
}
- if (getFreePartialCount() >= needed) {
+ if (synth->isAbortingPoly() || getFreePartialCount() >= needed) {
return true;
}
}
@@ -233,7 +240,7 @@ bool PartialManager::freePartials(unsigned int needed, int partNum) {
if (!parts[partNum]->abortFirstPolyPreferHeld()) {
break;
}
- if (getFreePartialCount() >= needed) {
+ if (synth->isAbortingPoly() || getFreePartialCount() >= needed) {
return true;
}
}
@@ -243,10 +250,39 @@ bool PartialManager::freePartials(unsigned int needed, int partNum) {
}
const Partial *PartialManager::getPartial(unsigned int partialNum) const {
- if (partialNum > MT32EMU_MAX_PARTIALS - 1) {
+ if (partialNum > synth->getPartialCount() - 1) {
return NULL;
}
return partialTable[partialNum];
}
+Poly *PartialManager::assignPolyToPart(Part *part) {
+ if (firstFreePolyIndex < synth->getPartialCount()) {
+ Poly *poly = freePolys[firstFreePolyIndex];
+ freePolys[firstFreePolyIndex] = NULL;
+ firstFreePolyIndex++;
+ poly->setPart(part);
+ return poly;
+ }
+ return NULL;
+}
+
+void PartialManager::polyFreed(Poly *poly) {
+ if (0 == firstFreePolyIndex) {
+ synth->printDebug("Cannot return freed poly, currently active polys:\n");
+ for (Bit32u partNum = 0; partNum < 9; partNum++) {
+ const Poly *activePoly = synth->getPart(partNum)->getFirstActivePoly();
+ Bit32u polyCount = 0;
+ while (activePoly != NULL) {
+ activePoly->getNext();
+ polyCount++;
+ }
+ synth->printDebug("Part: %i, active poly count: %i\n", partNum, polyCount);
+ }
+ }
+ poly->setPart(NULL);
+ firstFreePolyIndex--;
+ freePolys[firstFreePolyIndex] = poly;
+}
+
}
diff --git a/audio/softsynth/mt32/PartialManager.h b/audio/softsynth/mt32/PartialManager.h
index a1c9266ea1..229b6e8121 100644
--- a/audio/softsynth/mt32/PartialManager.h
+++ b/audio/softsynth/mt32/PartialManager.h
@@ -24,17 +24,17 @@ class Synth;
class PartialManager {
private:
- Synth *synth; // Only used for sending debug output
+ Synth *synth;
Part **parts;
-
- Partial *partialTable[MT32EMU_MAX_PARTIALS];
+ Poly **freePolys;
+ Partial **partialTable;
Bit8u numReservedPartialsForPart[9];
+ Bit32u firstFreePolyIndex;
bool abortFirstReleasingPolyWhereReserveExceeded(int minPart);
bool abortFirstPolyPreferHeldWhereReserveExceeded(int minPart);
public:
-
PartialManager(Synth *synth, Part **parts);
~PartialManager();
Partial *allocPartial(int partNum);
@@ -43,10 +43,12 @@ public:
bool freePartials(unsigned int needed, int partNum);
unsigned int setReserve(Bit8u *rset);
void deactivateAll();
- bool produceOutput(int i, float *leftBuf, float *rightBuf, Bit32u bufferLength);
+ bool produceOutput(int i, Sample *leftBuf, Sample *rightBuf, Bit32u bufferLength);
bool shouldReverb(int i);
void clearAlreadyOutputed();
const Partial *getPartial(unsigned int partialNum) const;
+ Poly *assignPolyToPart(Part *part);
+ void polyFreed(Poly *poly);
};
}
diff --git a/audio/softsynth/mt32/Poly.cpp b/audio/softsynth/mt32/Poly.cpp
index 46574f8967..1554881270 100644
--- a/audio/softsynth/mt32/Poly.cpp
+++ b/audio/softsynth/mt32/Poly.cpp
@@ -19,8 +19,8 @@
namespace MT32Emu {
-Poly::Poly(Part *usePart) {
- part = usePart;
+Poly::Poly() {
+ part = NULL;
key = 255;
velocity = 255;
sustain = false;
@@ -32,10 +32,21 @@ Poly::Poly(Part *usePart) {
next = NULL;
}
+void Poly::setPart(Part *usePart) {
+ part = usePart;
+}
+
void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain, Partial **newPartials) {
if (isActive()) {
- // FIXME: Throw out some big ugly debug output with a lot of exclamation marks - we should never get here
- terminate();
+ // This should never happen
+ part->getSynth()->printDebug("Resetting active poly. Active partial count: %i\n", activePartialCount);
+ for (int i = 0; i < 4; i++) {
+ if (partials[i] != NULL && partials[i]->isActive()) {
+ partials[i]->deactivate();
+ activePartialCount--;
+ }
+ }
+ state = POLY_Inactive;
}
key = newKey;
@@ -92,41 +103,24 @@ bool Poly::startDecay() {
}
bool Poly::startAbort() {
- if (state == POLY_Inactive) {
+ if (state == POLY_Inactive || part->getSynth()->isAbortingPoly()) {
return false;
}
for (int t = 0; t < 4; t++) {
Partial *partial = partials[t];
if (partial != NULL) {
partial->startAbort();
+ part->getSynth()->abortingPoly = this;
}
}
return true;
}
-void Poly::terminate() {
- if (state == POLY_Inactive) {
- return;
- }
- for (int t = 0; t < 4; t++) {
- Partial *partial = partials[t];
- if (partial != NULL) {
- partial->deactivate();
- }
- }
- if (state != POLY_Inactive) {
- // FIXME: Throw out lots of debug output - this should never happen
- // (Deactivating the partials above should've made them each call partialDeactivated(), ultimately changing the state to POLY_Inactive)
- state = POLY_Inactive;
- }
-}
-
void Poly::backupCacheToPartials(PatchCache cache[4]) {
for (int partialNum = 0; partialNum < 4; partialNum++) {
Partial *partial = partials[partialNum];
- if (partial != NULL && partial->patchCache == &cache[partialNum]) {
- partial->cachebackup = cache[partialNum];
- partial->patchCache = &partial->cachebackup;
+ if (partial != NULL) {
+ partial->backupCache(cache[partialNum]);
}
}
}
@@ -171,11 +165,14 @@ void Poly::partialDeactivated(Partial *partial) {
}
if (activePartialCount == 0) {
state = POLY_Inactive;
+ if (part->getSynth()->abortingPoly == this) {
+ part->getSynth()->abortingPoly = NULL;
+ }
}
part->partialDeactivated(this);
}
-Poly *Poly::getNext() {
+Poly *Poly::getNext() const {
return next;
}
diff --git a/audio/softsynth/mt32/Poly.h b/audio/softsynth/mt32/Poly.h
index 068cf73d35..33abc35fdf 100644
--- a/audio/softsynth/mt32/Poly.h
+++ b/audio/softsynth/mt32/Poly.h
@@ -44,13 +44,13 @@ private:
Poly *next;
public:
- Poly(Part *part);
+ Poly();
+ void setPart(Part *usePart);
void reset(unsigned int key, unsigned int velocity, bool sustain, Partial **partials);
bool noteOff(bool pedalHeld);
bool stopPedalHold();
bool startDecay();
bool startAbort();
- void terminate();
void backupCacheToPartials(PatchCache cache[4]);
@@ -63,7 +63,7 @@ public:
void partialDeactivated(Partial *partial);
- Poly *getNext();
+ Poly *getNext() const;
void setNext(Poly *poly);
};
diff --git a/audio/softsynth/mt32/Structures.h b/audio/softsynth/mt32/Structures.h
index 43d2d1f226..421e427fc0 100644
--- a/audio/softsynth/mt32/Structures.h
+++ b/audio/softsynth/mt32/Structures.h
@@ -38,6 +38,12 @@ typedef signed short int Bit16s;
typedef unsigned char Bit8u;
typedef signed char Bit8s;
+#if MT32EMU_USE_FLOAT_SAMPLES
+typedef float Sample;
+#else
+typedef Bit16s Sample;
+#endif
+
// The following structures represent the MT-32's memory
// Since sysex allows this memory to be written to in blocks of bytes,
// we keep this packed so that we can copy data into the various
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index b7af992b99..efba9b7514 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -26,15 +26,7 @@
#include "mt32emu.h"
#include "mmath.h"
#include "PartialManager.h"
-
-#if MT32EMU_USE_REVERBMODEL == 1
-#include "AReverbModel.h"
-#elif MT32EMU_USE_REVERBMODEL == 2
#include "BReverbModel.h"
-#else
-#include "FreeverbModel.h"
-#endif
-#include "DelayReverb.h"
namespace MT32Emu {
@@ -50,84 +42,22 @@ static const ControlROMMap ControlROMMaps[7] = {
// (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp)
};
-static inline Bit16s *streamOffset(Bit16s *stream, Bit32u pos) {
- return stream == NULL ? NULL : stream + pos;
-}
-
-static inline void clearIfNonNull(Bit16s *stream, Bit32u len) {
- if (stream != NULL) {
- memset(stream, 0, len * sizeof(Bit16s));
- }
-}
-
-static inline void mix(float *target, const float *stream, Bit32u len) {
- while (len--) {
- *target += *stream;
- stream++;
- target++;
- }
-}
+static inline void muteStream(Sample *stream, Bit32u len) {
+ if (stream == NULL) return;
-static inline void clearFloats(float *leftBuf, float *rightBuf, Bit32u len) {
+#if MT32EMU_USE_FLOAT_SAMPLES
// FIXME: Use memset() where compatibility is guaranteed (if this turns out to be a win)
while (len--) {
- *leftBuf++ = 0.0f;
- *rightBuf++ = 0.0f;
- }
-}
-
-static inline Bit16s clipBit16s(Bit32s a) {
- // Clamp values above 32767 to 32767, and values below -32768 to -32768
- if ((a + 32768) & ~65535) {
- return (a >> 31) ^ 32767;
- }
- return a;
-}
-
-static void floatToBit16s_nice(Bit16s *target, const float *source, Bit32u len, float outputGain) {
- float gain = outputGain * 16384.0f;
- while (len--) {
- // Since we're not shooting for accuracy here, don't worry about the rounding mode.
- *target = clipBit16s((Bit32s)(*source * gain));
- source++;
- target++;
- }
-}
-
-static void floatToBit16s_pure(Bit16s *target, const float *source, Bit32u len, float /*outputGain*/) {
- while (len--) {
- *target = clipBit16s((Bit32s)floor(*source * 8192.0f));
- source++;
- target++;
- }
-}
-
-static void floatToBit16s_reverb(Bit16s *target, const float *source, Bit32u len, float outputGain) {
- float gain = outputGain * 8192.0f;
- while (len--) {
- *target = clipBit16s((Bit32s)floor(*source * gain));
- source++;
- target++;
- }
-}
-
-static void floatToBit16s_generation1(Bit16s *target, const float *source, Bit32u len, float outputGain) {
- float gain = outputGain * 8192.0f;
- while (len--) {
- *target = clipBit16s((Bit32s)floor(*source * gain));
- *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE);
- source++;
- target++;
+ *stream++ = 0.0f;
}
+#else
+ memset(stream, 0, len * sizeof(Sample));
+#endif
}
-static void floatToBit16s_generation2(Bit16s *target, const float *source, Bit32u len, float outputGain) {
- float gain = outputGain * 8192.0f;
- while (len--) {
- *target = clipBit16s((Bit32s)floor(*source * gain));
- *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE) | ((*target >> 14) & 0x0001);
- source++;
- target++;
+static inline void advanceStreamPosition(Sample *&stream, Bit32u posDelta) {
+ if (stream != NULL) {
+ stream += posDelta;
}
}
@@ -146,6 +76,7 @@ Synth::Synth(ReportHandler *useReportHandler) {
isOpen = false;
reverbEnabled = true;
reverbOverridden = false;
+ partialCount = DEFAULT_MAX_PARTIALS;
if (useReportHandler == NULL) {
reportHandler = new ReportHandler;
@@ -155,28 +86,20 @@ Synth::Synth(ReportHandler *useReportHandler) {
isDefaultReportHandler = false;
}
-#if MT32EMU_USE_REVERBMODEL == 1
- reverbModels[REVERB_MODE_ROOM] = new AReverbModel(REVERB_MODE_ROOM);
- reverbModels[REVERB_MODE_HALL] = new AReverbModel(REVERB_MODE_HALL);
- reverbModels[REVERB_MODE_PLATE] = new AReverbModel(REVERB_MODE_PLATE);
- reverbModels[REVERB_MODE_TAP_DELAY] = new DelayReverb();
-#elif MT32EMU_USE_REVERBMODEL == 2
reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM);
reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL);
reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE);
reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY);
-#else
- reverbModels[REVERB_MODE_ROOM] = new FreeverbModel(0.76f, 0.687770909f, 0.63f, 0, 0.5f);
- reverbModels[REVERB_MODE_HALL] = new FreeverbModel(2.0f, 0.712025098f, 0.86f, 1, 0.5f);
- reverbModels[REVERB_MODE_PLATE] = new FreeverbModel(0.4f, 0.939522749f, 0.38f, 2, 0.05f);
- reverbModels[REVERB_MODE_TAP_DELAY] = new DelayReverb();
-#endif
reverbModel = NULL;
setDACInputMode(DACInputMode_NICE);
+ setMIDIDelayMode(MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY);
setOutputGain(1.0f);
- setReverbOutputGain(0.68f);
+ setReverbOutputGain(1.0f);
+ setReversedStereoEnabled(false);
partialManager = NULL;
+ midiQueue = NULL;
+ lastReceivedMIDIEventTimestamp = 0;
memset(parts, 0, sizeof(parts));
renderedSampleCount = 0;
}
@@ -197,29 +120,16 @@ void ReportHandler::showLCDMessage(const char *data) {
}
void ReportHandler::printDebug(const char *fmt, va_list list) {
- vprintf(fmt, list);
- printf("\n");
-}
-
-void Synth::partStateChanged(int partNum, bool isPartActive) {
- reportHandler->onPartStateChanged(partNum, isPartActive);
+ vprintf(fmt, list);
+ printf("\n");
}
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, ...) {
@@ -249,35 +159,72 @@ bool Synth::isReverbOverridden() const {
}
void Synth::setDACInputMode(DACInputMode mode) {
- switch(mode) {
- case DACInputMode_GENERATION1:
- la32FloatToBit16sFunc = floatToBit16s_generation1;
- reverbFloatToBit16sFunc = floatToBit16s_reverb;
- break;
- case DACInputMode_GENERATION2:
- la32FloatToBit16sFunc = floatToBit16s_generation2;
- reverbFloatToBit16sFunc = floatToBit16s_reverb;
- break;
- case DACInputMode_PURE:
- la32FloatToBit16sFunc = floatToBit16s_pure;
- reverbFloatToBit16sFunc = floatToBit16s_pure;
- break;
- case DACInputMode_NICE:
- default:
- la32FloatToBit16sFunc = floatToBit16s_nice;
- reverbFloatToBit16sFunc = floatToBit16s_reverb;
- break;
- }
+ dacInputMode = mode;
+}
+
+DACInputMode Synth::getDACInputMode() const {
+ return dacInputMode;
+}
+
+void Synth::setMIDIDelayMode(MIDIDelayMode mode) {
+ midiDelayMode = mode;
+}
+
+MIDIDelayMode Synth::getMIDIDelayMode() const {
+ return midiDelayMode;
}
+#if MT32EMU_USE_FLOAT_SAMPLES
+
void Synth::setOutputGain(float newOutputGain) {
outputGain = newOutputGain;
}
+float Synth::getOutputGain() const {
+ return outputGain;
+}
+
void Synth::setReverbOutputGain(float newReverbOutputGain) {
reverbOutputGain = newReverbOutputGain;
}
+float Synth::getReverbOutputGain() const {
+ return reverbOutputGain;
+}
+
+#else // #if MT32EMU_USE_FLOAT_SAMPLES
+
+void Synth::setOutputGain(float newOutputGain) {
+ if (newOutputGain < 0.0f) newOutputGain = -newOutputGain;
+ if (256.0f < newOutputGain) newOutputGain = 256.0f;
+ outputGain = int(newOutputGain * 256.0f);
+}
+
+float Synth::getOutputGain() const {
+ return outputGain / 256.0f;
+}
+
+void Synth::setReverbOutputGain(float newReverbOutputGain) {
+ if (newReverbOutputGain < 0.0f) newReverbOutputGain = -newReverbOutputGain;
+ float maxValue = 256.0f / CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR;
+ if (maxValue < newReverbOutputGain) newReverbOutputGain = maxValue;
+ reverbOutputGain = int(newReverbOutputGain * 256.0f);
+}
+
+float Synth::getReverbOutputGain() const {
+ return reverbOutputGain / 256.0f;
+}
+
+#endif // #if MT32EMU_USE_FLOAT_SAMPLES
+
+void Synth::setReversedStereoEnabled(bool enabled) {
+ reversedStereoEnabled = enabled;
+}
+
+bool Synth::isReversedStereoEnabled() {
+ return reversedStereoEnabled;
+}
+
bool Synth::loadControlROM(const ROMImage &controlROMImage) {
if (&controlROMImage == NULL) return false;
Common::File *file = controlROMImage.getFile();
@@ -356,9 +303,9 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) {
bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) {
ControlROMPCMStruct *tps = (ControlROMPCMStruct *)&controlROMData[mapAddress];
for (int i = 0; i < count; i++) {
- size_t rAddr = tps[i].pos * 0x800;
- size_t rLenExp = (tps[i].len & 0x70) >> 4;
- size_t rLen = 0x800 << rLenExp;
+ Bit32u rAddr = tps[i].pos * 0x800;
+ Bit32u rLenExp = (tps[i].len & 0x70) >> 4;
+ Bit32u rLen = 0x800 << rLenExp;
if (rAddr + rLen > pcmROMSize) {
printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen);
return false;
@@ -420,17 +367,18 @@ bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int count, int startTi
return true;
}
-bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage) {
+bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount) {
if (isOpen) {
return false;
}
- prerenderReadIx = prerenderWriteIx = 0;
+ partialCount = usePartialCount;
+ abortingPoly = NULL;
#if MT32EMU_MONITOR_INIT
printDebug("Initialising Constant Tables");
#endif
#if !MT32EMU_REDUCE_REVERB_MEMORY
- for (int i = 0; i < 4; i++) {
- reverbModels[i]->open(useProp.sampleRate);
+ for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
+ reverbModels[i]->open();
}
#endif
@@ -567,6 +515,8 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage) {
// For resetting mt32 mid-execution
mt32default = mt32ram;
+ midiQueue = new MidiEventQueue();
+
isOpen = true;
isEnabled = false;
@@ -581,6 +531,9 @@ void Synth::close() {
return;
}
+ delete midiQueue;
+ midiQueue = NULL;
+
delete partialManager;
partialManager = NULL;
@@ -601,12 +554,78 @@ void Synth::close() {
isOpen = false;
}
-void Synth::playMsg(Bit32u msg) {
+void Synth::flushMIDIQueue() {
+ if (midiQueue != NULL) {
+ for (;;) {
+ const MidiEvent *midiEvent = midiQueue->peekMidiEvent();
+ if (midiEvent == NULL) break;
+ if (midiEvent->sysexData == NULL) {
+ playMsgNow(midiEvent->shortMessageData);
+ } else {
+ playSysexNow(midiEvent->sysexData, midiEvent->sysexLength);
+ }
+ midiQueue->dropMidiEvent();
+ }
+ lastReceivedMIDIEventTimestamp = renderedSampleCount;
+ }
+}
+
+void Synth::setMIDIEventQueueSize(Bit32u useSize) {
+ if (midiQueue != NULL) {
+ flushMIDIQueue();
+ delete midiQueue;
+ midiQueue = new MidiEventQueue(useSize);
+ }
+}
+
+Bit32u Synth::getShortMessageLength(Bit32u msg) {
+ if ((msg & 0xF0) == 0xF0) return 1;
+ // NOTE: This calculation isn't quite correct
+ // as it doesn't consider the running status byte
+ return ((msg & 0xE0) == 0xC0) ? 2 : 3;
+}
+
+Bit32u Synth::addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp) {
+ Bit32u transferTime = Bit32u((double)len * MIDI_DATA_TRANSFER_RATE);
+ // Dealing with wrapping
+ if (Bit32s(timestamp - lastReceivedMIDIEventTimestamp) < 0) {
+ timestamp = lastReceivedMIDIEventTimestamp;
+ }
+ timestamp += transferTime;
+ lastReceivedMIDIEventTimestamp = timestamp;
+ return timestamp;
+}
+
+bool Synth::playMsg(Bit32u msg) {
+ return playMsg(msg, renderedSampleCount);
+}
+
+bool Synth::playMsg(Bit32u msg, Bit32u timestamp) {
+ if (midiQueue == NULL) return false;
+ if (midiDelayMode != MIDIDelayMode_IMMEDIATE) {
+ timestamp = addMIDIInterfaceDelay(getShortMessageLength(msg), timestamp);
+ }
+ return midiQueue->pushShortMessage(msg, timestamp);
+}
+
+bool Synth::playSysex(const Bit8u *sysex, Bit32u len) {
+ return playSysex(sysex, len, renderedSampleCount);
+}
+
+bool Synth::playSysex(const Bit8u *sysex, Bit32u len, Bit32u timestamp) {
+ if (midiQueue == NULL) return false;
+ if (midiDelayMode == MIDIDelayMode_DELAY_ALL) {
+ timestamp = addMIDIInterfaceDelay(len, timestamp);
+ }
+ return midiQueue->pushSysex(sysex, len, timestamp);
+}
+
+void Synth::playMsgNow(Bit32u msg) {
// FIXME: Implement active sensing
unsigned char code = (unsigned char)((msg & 0x0000F0) >> 4);
unsigned char chan = (unsigned char)(msg & 0x00000F);
- unsigned char note = (unsigned char)((msg & 0x00FF00) >> 8);
- unsigned char velocity = (unsigned char)((msg & 0xFF0000) >> 16);
+ unsigned char note = (unsigned char)((msg & 0x007F00) >> 8);
+ unsigned char velocity = (unsigned char)((msg & 0x7F0000) >> 16);
isEnabled = true;
//printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
@@ -619,11 +638,6 @@ void Synth::playMsg(Bit32u msg) {
return;
}
playMsgOnPart(part, code, note, velocity);
-
- // This ensures minimum 1-sample delay between sequential MIDI events
- // Without this, a sequence of NoteOn and immediately succeeding NoteOff messages is always silent
- // Technically, it's also impossible to send events through the MIDI interface faster than about each millisecond
- prerender();
}
void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) {
@@ -705,7 +719,7 @@ void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char
#if MT32EMU_MONITOR_MIDI > 0
printDebug("Unknown MIDI Control code: 0x%02x - vel 0x%02x", note, velocity);
#endif
- break;
+ return;
}
break;
@@ -722,13 +736,12 @@ void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char
#if MT32EMU_MONITOR_MIDI > 0
printDebug("Unknown Midi code: 0x%01x - %02x - %02x", code, note, velocity);
#endif
- break;
+ return;
}
-
- //midiOutShortMsg(m_out, msg);
+ reportHandler->onMIDIMessagePlayed();
}
-void Synth::playSysex(const Bit8u *sysex, Bit32u len) {
+void Synth::playSysexNow(const Bit8u *sysex, Bit32u len) {
if (len < 2) {
printDebug("playSysex: Message is too short for sysex (%d bytes)", len);
}
@@ -823,6 +836,7 @@ void Synth::readSysex(unsigned char /*device*/, const Bit8u * /*sysex*/, Bit32u
}
void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) {
+ reportHandler->onMIDIMessagePlayed();
Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]);
addr = MT32EMU_MEMADDR(addr);
sysex += 3;
@@ -1245,7 +1259,7 @@ void Synth::refreshSystemReverbParameters() {
reportHandler->onNewReverbTime(mt32ram.system.reverbTime);
reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel);
- ReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode];
+ BReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode];
#if MT32EMU_REDUCE_REVERB_MEMORY
if (reverbModel != newReverbModel) {
if (reverbModel != NULL) {
@@ -1321,179 +1335,229 @@ void Synth::reset() {
isEnabled = false;
}
-void Synth::render(Bit16s *stream, Bit32u len) {
- if (!isEnabled) {
- memset(stream, 0, len * sizeof(Bit16s) * 2);
- return;
+MidiEvent::~MidiEvent() {
+ if (sysexData != NULL) {
+ delete[] sysexData;
}
- while (len > 0) {
- Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;
- renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisLen);
- for (Bit32u i = 0; i < thisLen; i++) {
- stream[0] = clipBit16s((Bit32s)tmpNonReverbLeft[i] + (Bit32s)tmpReverbDryLeft[i] + (Bit32s)tmpReverbWetLeft[i]);
- stream[1] = clipBit16s((Bit32s)tmpNonReverbRight[i] + (Bit32s)tmpReverbDryRight[i] + (Bit32s)tmpReverbWetRight[i]);
- stream += 2;
- }
- len -= thisLen;
+}
+
+void MidiEvent::setShortMessage(Bit32u useShortMessageData, Bit32u useTimestamp) {
+ if (sysexData != NULL) {
+ delete[] sysexData;
}
+ shortMessageData = useShortMessageData;
+ timestamp = useTimestamp;
+ sysexData = NULL;
+ sysexLength = 0;
}
-bool Synth::prerender() {
- int newPrerenderWriteIx = (prerenderWriteIx + 1) % MAX_PRERENDER_SAMPLES;
- if (newPrerenderWriteIx == prerenderReadIx) {
- // The prerender buffer is full
- return false;
+void MidiEvent::setSysex(const Bit8u *useSysexData, Bit32u useSysexLength, Bit32u useTimestamp) {
+ if (sysexData != NULL) {
+ delete[] sysexData;
}
- doRenderStreams(
- prerenderNonReverbLeft + prerenderWriteIx,
- prerenderNonReverbRight + prerenderWriteIx,
- prerenderReverbDryLeft + prerenderWriteIx,
- prerenderReverbDryRight + prerenderWriteIx,
- prerenderReverbWetLeft + prerenderWriteIx,
- prerenderReverbWetRight + prerenderWriteIx,
- 1);
- prerenderWriteIx = newPrerenderWriteIx;
+ shortMessageData = 0;
+ timestamp = useTimestamp;
+ sysexLength = useSysexLength;
+ Bit8u *dstSysexData = new Bit8u[sysexLength];
+ sysexData = dstSysexData;
+ memcpy(dstSysexData, useSysexData, sysexLength);
+}
+
+MidiEventQueue::MidiEventQueue(Bit32u useRingBufferSize) : ringBufferSize(useRingBufferSize) {
+ ringBuffer = new MidiEvent[ringBufferSize];
+ memset(ringBuffer, 0, ringBufferSize * sizeof(MidiEvent));
+ reset();
+}
+
+MidiEventQueue::~MidiEventQueue() {
+ delete[] ringBuffer;
+}
+
+void MidiEventQueue::reset() {
+ startPosition = 0;
+ endPosition = 0;
+}
+
+bool MidiEventQueue::pushShortMessage(Bit32u shortMessageData, Bit32u timestamp) {
+ unsigned int newEndPosition = (endPosition + 1) % ringBufferSize;
+ // Is ring buffer full?
+ if (startPosition == newEndPosition) return false;
+ ringBuffer[endPosition].setShortMessage(shortMessageData, timestamp);
+ endPosition = newEndPosition;
return true;
}
-static inline void maybeCopy(Bit16s *out, Bit32u outPos, Bit16s *in, Bit32u inPos, Bit32u len) {
- if (out == NULL) {
- return;
- }
- memcpy(out + outPos, in + inPos, len * sizeof(Bit16s));
+bool MidiEventQueue::pushSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp) {
+ unsigned int newEndPosition = (endPosition + 1) % ringBufferSize;
+ // Is ring buffer full?
+ if (startPosition == newEndPosition) return false;
+ ringBuffer[endPosition].setSysex(sysexData, sysexLength, timestamp);
+ endPosition = newEndPosition;
+ return true;
}
-void Synth::copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len) {
- maybeCopy(nonReverbLeft, pos, prerenderNonReverbLeft, prerenderReadIx, len);
- maybeCopy(nonReverbRight, pos, prerenderNonReverbRight, prerenderReadIx, len);
- maybeCopy(reverbDryLeft, pos, prerenderReverbDryLeft, prerenderReadIx, len);
- maybeCopy(reverbDryRight, pos, prerenderReverbDryRight, prerenderReadIx, len);
- maybeCopy(reverbWetLeft, pos, prerenderReverbWetLeft, prerenderReadIx, len);
- maybeCopy(reverbWetRight, pos, prerenderReverbWetRight, prerenderReadIx, len);
+const MidiEvent *MidiEventQueue::peekMidiEvent() {
+ return (startPosition == endPosition) ? NULL : &ringBuffer[startPosition];
}
-void Synth::checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len) {
- if (prerenderReadIx > prerenderWriteIx) {
- // There's data in the prerender buffer, and the write index has wrapped.
- Bit32u prerenderCopyLen = MAX_PRERENDER_SAMPLES - prerenderReadIx;
- if (prerenderCopyLen > len) {
- prerenderCopyLen = len;
- }
- copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen);
- len -= prerenderCopyLen;
- pos += prerenderCopyLen;
- prerenderReadIx = (prerenderReadIx + prerenderCopyLen) % MAX_PRERENDER_SAMPLES;
- }
- if (prerenderReadIx < prerenderWriteIx) {
- // There's data in the prerender buffer, and the write index is ahead of the read index.
- Bit32u prerenderCopyLen = prerenderWriteIx - prerenderReadIx;
- if (prerenderCopyLen > len) {
- prerenderCopyLen = len;
- }
- copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen);
- len -= prerenderCopyLen;
- pos += prerenderCopyLen;
- prerenderReadIx += prerenderCopyLen;
- }
- if (prerenderReadIx == prerenderWriteIx) {
- // If the ring buffer's empty, reset it to start at 0 to minimise wrapping,
- // which requires two writes instead of one.
- prerenderReadIx = prerenderWriteIx = 0;
- }
-}
-
-void Synth::renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) {
- if (!isEnabled) {
- clearIfNonNull(nonReverbLeft, len);
- clearIfNonNull(nonReverbRight, len);
- clearIfNonNull(reverbDryLeft, len);
- clearIfNonNull(reverbDryRight, len);
- clearIfNonNull(reverbWetLeft, len);
- clearIfNonNull(reverbWetRight, len);
- return;
+void MidiEventQueue::dropMidiEvent() {
+ // Is ring buffer empty?
+ if (startPosition != endPosition) {
+ startPosition = (startPosition + 1) % ringBufferSize;
}
- Bit32u pos = 0;
+}
- // First, check for data in the prerender buffer and spit that out before generating anything new.
- // Note that the prerender buffer is rarely used - see comments elsewhere for details.
- checkPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, len);
+void Synth::render(Sample *stream, Bit32u len) {
+ Sample tmpNonReverbLeft[MAX_SAMPLES_PER_RUN];
+ Sample tmpNonReverbRight[MAX_SAMPLES_PER_RUN];
+ Sample tmpReverbDryLeft[MAX_SAMPLES_PER_RUN];
+ Sample tmpReverbDryRight[MAX_SAMPLES_PER_RUN];
+ Sample tmpReverbWetLeft[MAX_SAMPLES_PER_RUN];
+ Sample tmpReverbWetRight[MAX_SAMPLES_PER_RUN];
while (len > 0) {
Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;
- doRenderStreams(
- streamOffset(nonReverbLeft, pos),
- streamOffset(nonReverbRight, pos),
- streamOffset(reverbDryLeft, pos),
- streamOffset(reverbDryRight, pos),
- streamOffset(reverbWetLeft, pos),
- streamOffset(reverbWetRight, pos),
- thisLen);
+ renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisLen);
+ for (Bit32u i = 0; i < thisLen; i++) {
+#if MT32EMU_USE_FLOAT_SAMPLES
+ *(stream++) = tmpNonReverbLeft[i] + tmpReverbDryLeft[i] + tmpReverbWetLeft[i];
+ *(stream++) = tmpNonReverbRight[i] + tmpReverbDryRight[i] + tmpReverbWetRight[i];
+#else
+ *(stream++) = clipBit16s((Bit32s)tmpNonReverbLeft[i] + (Bit32s)tmpReverbDryLeft[i] + (Bit32s)tmpReverbWetLeft[i]);
+ *(stream++) = clipBit16s((Bit32s)tmpNonReverbRight[i] + (Bit32s)tmpReverbDryRight[i] + (Bit32s)tmpReverbWetRight[i]);
+#endif
+ }
len -= thisLen;
- pos += thisLen;
}
}
-// FIXME: Using more temporary buffers than we need to
-void Synth::doRenderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) {
- clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len);
- if (!reverbEnabled) {
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
- mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
- mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
+void Synth::renderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) {
+ while (len > 0) {
+ // We need to ensure zero-duration notes will play so add minimum 1-sample delay.
+ Bit32u thisLen = 1;
+ if (!isAbortingPoly()) {
+ const MidiEvent *nextEvent = midiQueue->peekMidiEvent();
+ Bit32s samplesToNextEvent = (nextEvent != NULL) ? Bit32s(nextEvent->timestamp - renderedSampleCount) : MAX_SAMPLES_PER_RUN;
+ if (samplesToNextEvent > 0) {
+ thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;
+ if (thisLen > (Bit32u)samplesToNextEvent) {
+ thisLen = samplesToNextEvent;
+ }
+ } else {
+ if (nextEvent->sysexData == NULL) {
+ playMsgNow(nextEvent->shortMessageData);
+ // If a poly is aborting we don't drop the event from the queue.
+ // Instead, we'll return to it again when the abortion is done.
+ if (!isAbortingPoly()) {
+ midiQueue->dropMidiEvent();
+ }
+ } else {
+ playSysexNow(nextEvent->sysexData, nextEvent->sysexLength);
+ midiQueue->dropMidiEvent();
+ }
}
}
- if (nonReverbLeft != NULL) {
- la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain);
- }
- if (nonReverbRight != NULL) {
- la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain);
- }
- clearIfNonNull(reverbDryLeft, len);
- clearIfNonNull(reverbDryRight, len);
- clearIfNonNull(reverbWetLeft, len);
- clearIfNonNull(reverbWetRight, len);
+ doRenderStreams(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, thisLen);
+ advanceStreamPosition(nonReverbLeft, thisLen);
+ advanceStreamPosition(nonReverbRight, thisLen);
+ advanceStreamPosition(reverbDryLeft, thisLen);
+ advanceStreamPosition(reverbDryRight, thisLen);
+ advanceStreamPosition(reverbWetLeft, thisLen);
+ advanceStreamPosition(reverbWetRight, thisLen);
+ len -= thisLen;
+ }
+}
+
+void Synth::convertSamplesToOutput(Sample *target, const Sample *source, Bit32u len, bool reverb) {
+ if (target == NULL) return;
+
+ if (dacInputMode == DACInputMode_PURE) {
+ memcpy(target, source, len * sizeof(Sample));
+ return;
+ }
+
+#if MT32EMU_USE_FLOAT_SAMPLES
+ float gain = reverb ? reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR : 2.0f * outputGain;
+ while (len--) {
+ *(target++) = *(source++) * gain;
+ }
+#else
+ int gain;
+ if (reverb) {
+ gain = int(reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR);
} else {
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (!partialManager->shouldReverb(i)) {
- if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
- mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
- mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
- }
+ gain = outputGain;
+ switch (dacInputMode) {
+ case DACInputMode_NICE:
+ // Since we're not shooting for accuracy here, don't worry about the rounding mode.
+ gain <<= 1;
+ break;
+ case DACInputMode_GENERATION1:
+ while (len--) {
+ *target = clipBit16s(Bit32s((*source * gain) >> 8));
+ *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE);
+ source++;
+ target++;
}
+ return;
+ case DACInputMode_GENERATION2:
+ while (len--) {
+ *target = clipBit16s(Bit32s((*source * gain) >> 8));
+ *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE) | ((*target >> 14) & 0x0001);
+ source++;
+ target++;
+ }
+ return;
+ default:
+ break;
}
- if (nonReverbLeft != NULL) {
- la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain);
- }
- if (nonReverbRight != NULL) {
- la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain);
+ }
+ while (len--) {
+ *(target++) = clipBit16s(Bit32s((*(source++) * gain) >> 8));
+ }
+#endif
+}
+
+void Synth::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) {
+ if (isEnabled) {
+ Sample tmpBufMixLeft[MAX_SAMPLES_PER_RUN], tmpBufMixRight[MAX_SAMPLES_PER_RUN];
+ muteStream(tmpBufMixLeft, len);
+ muteStream(tmpBufMixRight, len);
+ for (unsigned int i = 0; i < getPartialCount(); i++) {
+ if (!reverbEnabled || !partialManager->shouldReverb(i)) {
+ partialManager->produceOutput(i, tmpBufMixLeft, tmpBufMixRight, len);
+ }
}
+ convertSamplesToOutput(nonReverbLeft, tmpBufMixLeft, len, false);
+ convertSamplesToOutput(nonReverbRight, tmpBufMixRight, len, false);
+ } else {
+ muteStream(nonReverbLeft, len);
+ muteStream(nonReverbRight, len);
+ }
- clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len);
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ if (isEnabled && reverbEnabled) {
+ Sample tmpBufMixLeft[MAX_SAMPLES_PER_RUN], tmpBufMixRight[MAX_SAMPLES_PER_RUN];
+ muteStream(tmpBufMixLeft, len);
+ muteStream(tmpBufMixRight, len);
+ for (unsigned int i = 0; i < getPartialCount(); i++) {
if (partialManager->shouldReverb(i)) {
- if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
- mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
- mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
- }
+ partialManager->produceOutput(i, tmpBufMixLeft, tmpBufMixRight, len);
}
}
- if (reverbDryLeft != NULL) {
- la32FloatToBit16sFunc(reverbDryLeft, &tmpBufMixLeft[0], len, outputGain);
- }
- if (reverbDryRight != NULL) {
- la32FloatToBit16sFunc(reverbDryRight, &tmpBufMixRight[0], len, outputGain);
- }
+ convertSamplesToOutput(reverbDryLeft, tmpBufMixLeft, len, false);
+ convertSamplesToOutput(reverbDryRight, tmpBufMixRight, len, false);
- // FIXME: Note that on the real devices, reverb input and output are signed linear 16-bit (well, kinda, there's some fudging) PCM, not float.
- reverbModel->process(&tmpBufMixLeft[0], &tmpBufMixRight[0], &tmpBufReverbOutLeft[0], &tmpBufReverbOutRight[0], len);
- if (reverbWetLeft != NULL) {
- reverbFloatToBit16sFunc(reverbWetLeft, &tmpBufReverbOutLeft[0], len, reverbOutputGain);
- }
- if (reverbWetRight != NULL) {
- reverbFloatToBit16sFunc(reverbWetRight, &tmpBufReverbOutRight[0], len, reverbOutputGain);
- }
+ Sample tmpBufReverbOutLeft[MAX_SAMPLES_PER_RUN], tmpBufReverbOutRight[MAX_SAMPLES_PER_RUN];
+ reverbModel->process(tmpBufMixLeft, tmpBufMixRight, tmpBufReverbOutLeft, tmpBufReverbOutRight, len);
+ convertSamplesToOutput(reverbWetLeft, tmpBufReverbOutLeft, len, true);
+ convertSamplesToOutput(reverbWetRight, tmpBufReverbOutRight, len, true);
+ } else {
+ muteStream(reverbDryLeft, len);
+ muteStream(reverbDryRight, len);
+ muteStream(reverbWetLeft, len);
+ muteStream(reverbWetRight, len);
}
+
partialManager->clearAlreadyOutputed();
renderedSampleCount += len;
}
@@ -1502,19 +1566,14 @@ void Synth::printPartialUsage(unsigned long sampleOffset) {
unsigned int partialUsage[9];
partialManager->getPerPartPartialUsage(partialUsage);
if (sampleOffset > 0) {
- printDebug("[+%lu] Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", sampleOffset, partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], MT32EMU_MAX_PARTIALS - partialManager->getFreePartialCount());
+ printDebug("[+%lu] Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", sampleOffset, partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialCount() - partialManager->getFreePartialCount());
} else {
- printDebug("Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], MT32EMU_MAX_PARTIALS - partialManager->getFreePartialCount());
+ printDebug("Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialCount() - partialManager->getFreePartialCount());
}
}
bool Synth::hasActivePartials() const {
- if (prerenderReadIx != prerenderWriteIx) {
- // Data in the prerender buffer means that the current isActive() states are "in the future".
- // It also means that partials are definitely active at this render point.
- return true;
- }
- for (int partialNum = 0; partialNum < MT32EMU_MAX_PARTIALS; partialNum++) {
+ for (unsigned int partialNum = 0; partialNum < getPartialCount(); partialNum++) {
if (partialManager->getPartial(partialNum)->isActive()) {
return true;
}
@@ -1522,6 +1581,10 @@ bool Synth::hasActivePartials() const {
return false;
}
+bool Synth::isAbortingPoly() const {
+ return abortingPoly != NULL;
+}
+
bool Synth::isActive() const {
if (hasActivePartials()) {
return true;
@@ -1536,6 +1599,10 @@ const Partial *Synth::getPartial(unsigned int partialNum) const {
return partialManager->getPartial(partialNum);
}
+unsigned int Synth::getPartialCount() const {
+ return partialCount;
+}
+
const Part *Synth::getPart(unsigned int partNum) const {
if (partNum > 8) {
return NULL;
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index 56e88e6156..8816711bf3 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -27,6 +27,7 @@ class Partial;
class PartialManager;
class Part;
class ROMImage;
+class BReverbModel;
/**
* Methods for emulating the connection between the LA32 and the DAC, which involves
@@ -44,6 +45,7 @@ enum DACInputMode {
// * Much less likely to overdrive than any other mode.
// * Half the volume of any of the other modes, meaning its volume relative to the reverb
// output when mixed together directly will sound wrong.
+ // * Output gain is ignored for both LA32 and reverb output.
// * Perfect for developers while debugging :)
DACInputMode_PURE,
@@ -58,7 +60,17 @@ enum DACInputMode {
DACInputMode_GENERATION2
};
-typedef void (*FloatToBit16sFunc)(Bit16s *target, const float *source, Bit32u len, float outputGain);
+enum MIDIDelayMode {
+ // Process incoming MIDI events immediately.
+ MIDIDelayMode_IMMEDIATE,
+
+ // Delay incoming short MIDI messages as if they where transferred via a MIDI cable to a real hardware unit and immediate sysex processing.
+ // This ensures more accurate timing of simultaneous NoteOn messages.
+ MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY,
+
+ // Delay all incoming MIDI events as if they where transferred via a MIDI cable to a real hardware unit.
+ MIDIDelayMode_DELAY_ALL
+};
const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41;
@@ -217,18 +229,6 @@ public:
ResetMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Reset, MT32EMU_MEMADDR(0x7F0000), 0x3FFF, 1) {}
};
-class ReverbModel {
-public:
- virtual ~ReverbModel() {}
- // After construction or a close(), open() will be called at least once before any other call (with the exception of close()).
- virtual void open() = 0;
- // May be called multiple times without an open() in between.
- virtual void close() = 0;
- virtual void setParameters(Bit8u time, Bit8u level) = 0;
- virtual void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) = 0;
- virtual bool isActive() const = 0;
-};
-
class ReportHandler {
friend class Synth;
@@ -244,15 +244,55 @@ protected:
virtual void onErrorControlROM() {}
virtual void onErrorPCMROM() {}
virtual void showLCDMessage(const char *message);
+ virtual void onMIDIMessagePlayed() {}
virtual void onDeviceReset() {}
virtual void onDeviceReconfig() {}
virtual void onNewReverbMode(Bit8u /* mode */) {}
virtual void onNewReverbTime(Bit8u /* time */) {}
virtual void onNewReverbLevel(Bit8u /* level */) {}
- virtual void onPartStateChanged(int /* partNum */, bool /* isActive */) {}
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 */) {}
+};
+
+/**
+ * Used to safely store timestamped MIDI events in a local queue.
+ */
+struct MidiEvent {
+ Bit32u shortMessageData;
+ const Bit8u *sysexData;
+ Bit32u sysexLength;
+ Bit32u timestamp;
+
+ ~MidiEvent();
+ void setShortMessage(Bit32u shortMessageData, Bit32u timestamp);
+ void setSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp);
+};
+
+/**
+ * Simple queue implementation using a ring buffer to store incoming MIDI event before the synth actually processes it.
+ * It is intended to:
+ * - get rid of prerenderer while retaining graceful partial abortion
+ * - add fair emulation of the MIDI interface delays
+ * - extend the synth interface with the default implementation of a typical rendering loop.
+ * THREAD SAFETY:
+ * It is safe to use either in a single thread environment or when there are only two threads - one performs only reading
+ * and one performs only writing. More complicated usage requires external synchronisation.
+ */
+class MidiEventQueue {
+private:
+ MidiEvent *ringBuffer;
+ Bit32u ringBufferSize;
+ volatile Bit32u startPosition;
+ volatile Bit32u endPosition;
+
+public:
+ MidiEventQueue(Bit32u ringBufferSize = DEFAULT_MIDI_EVENT_QUEUE_SIZE);
+ ~MidiEventQueue();
+ void reset();
+ bool pushShortMessage(Bit32u shortMessageData, Bit32u timestamp);
+ bool pushSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp);
+ const MidiEvent *peekMidiEvent();
+ void dropMidiEvent();
};
class Synth {
@@ -260,6 +300,7 @@ friend class Part;
friend class RhythmPart;
friend class Poly;
friend class Partial;
+friend class PartialManager;
friend class Tables;
friend class MemoryRegion;
friend class TVA;
@@ -286,22 +327,32 @@ private:
Bit16s *pcmROMData;
size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
- Bit8s chantable[32];
-
- Bit32u renderedSampleCount;
+ unsigned int partialCount;
+ Bit8s chantable[32]; // FIXME: Need explanation why 32 is set, obviously it should be 16
+ MidiEventQueue *midiQueue;
+ volatile Bit32u lastReceivedMIDIEventTimestamp;
+ volatile Bit32u renderedSampleCount;
MemParams mt32ram, mt32default;
- ReverbModel *reverbModels[4];
- ReverbModel *reverbModel;
+ BReverbModel *reverbModels[4];
+ BReverbModel *reverbModel;
bool reverbEnabled;
bool reverbOverridden;
- FloatToBit16sFunc la32FloatToBit16sFunc;
- FloatToBit16sFunc reverbFloatToBit16sFunc;
+ MIDIDelayMode midiDelayMode;
+ DACInputMode dacInputMode;
+
+#if MT32EMU_USE_FLOAT_SAMPLES
float outputGain;
float reverbOutputGain;
+#else
+ int outputGain;
+ int reverbOutputGain;
+#endif
+
+ bool reversedStereoEnabled;
bool isOpen;
@@ -311,41 +362,18 @@ private:
PartialManager *partialManager;
Part *parts[9];
- // FIXME: We can reorganise things so that we don't need all these separate tmpBuf, tmp and prerender buffers.
- // This should be rationalised when things have stabilised a bit (if prerender buffers don't die in the mean time).
-
- float tmpBufPartialLeft[MAX_SAMPLES_PER_RUN];
- float tmpBufPartialRight[MAX_SAMPLES_PER_RUN];
- float tmpBufMixLeft[MAX_SAMPLES_PER_RUN];
- float tmpBufMixRight[MAX_SAMPLES_PER_RUN];
- float tmpBufReverbOutLeft[MAX_SAMPLES_PER_RUN];
- float tmpBufReverbOutRight[MAX_SAMPLES_PER_RUN];
-
- Bit16s tmpNonReverbLeft[MAX_SAMPLES_PER_RUN];
- Bit16s tmpNonReverbRight[MAX_SAMPLES_PER_RUN];
- Bit16s tmpReverbDryLeft[MAX_SAMPLES_PER_RUN];
- Bit16s tmpReverbDryRight[MAX_SAMPLES_PER_RUN];
- Bit16s tmpReverbWetLeft[MAX_SAMPLES_PER_RUN];
- Bit16s tmpReverbWetRight[MAX_SAMPLES_PER_RUN];
-
- // These ring buffers are only used to simulate delays present on the real device.
- // In particular, when a partial needs to be aborted to free it up for use by a new Poly,
+ // When a partial needs to be aborted to free it up for use by a new Poly,
// the controller will busy-loop waiting for the sound to finish.
- Bit16s prerenderNonReverbLeft[MAX_PRERENDER_SAMPLES];
- Bit16s prerenderNonReverbRight[MAX_PRERENDER_SAMPLES];
- Bit16s prerenderReverbDryLeft[MAX_PRERENDER_SAMPLES];
- Bit16s prerenderReverbDryRight[MAX_PRERENDER_SAMPLES];
- Bit16s prerenderReverbWetLeft[MAX_PRERENDER_SAMPLES];
- Bit16s prerenderReverbWetRight[MAX_PRERENDER_SAMPLES];
- int prerenderReadIx;
- int prerenderWriteIx;
-
- bool prerender();
- void copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len);
- void checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len);
- void doRenderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len);
-
- void playAddressedSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
+ // We emulate this by delaying new MIDI events processing until abortion finishes.
+ Poly *abortingPoly;
+
+ Bit32u getShortMessageLength(Bit32u msg);
+ Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp);
+
+ void convertSamplesToOutput(Sample *target, const Sample *source, Bit32u len, bool reverb);
+ bool isAbortingPoly() const;
+ void doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len);
+
void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len) const;
void initMemoryRegions();
void deleteMemoryRegions();
@@ -370,13 +398,19 @@ 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:
+ static inline Bit16s clipBit16s(Bit32s sample) {
+ // Clamp values above 32767 to 32767, and values below -32768 to -32768
+ if ((sample + 32768) & ~65535) {
+ return (sample >> 31) ^ 32767;
+ }
+ return (Bit16s)sample;
+ }
+
static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum);
// Optionally sets callbacks for reporting various errors, information and debug messages
@@ -386,18 +420,44 @@ public:
// Used to initialise the MT-32. Must be called before any other function.
// Returns true if initialization was sucessful, otherwise returns false.
// controlROMImage and pcmROMImage represent Control and PCM ROM images for use by synth.
- bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage);
+ // usePartialCount sets the maximum number of partials playing simultaneously for this session.
+ bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount = DEFAULT_MAX_PARTIALS);
// Closes the MT-32 and deallocates any memory used by the synthesizer
void close(void);
- // Sends a 4-byte MIDI message to the MT-32 for immediate playback
- void playMsg(Bit32u msg);
+ // All the enqueued events are processed by the synth immediately.
+ void flushMIDIQueue();
+
+ // Sets size of the internal MIDI event queue.
+ // The queue is flushed before reallocation.
+ void setMIDIEventQueueSize(Bit32u);
+
+ // Enqueues a MIDI event for subsequent playback.
+ // The minimum delay involves the delay introduced while the event is transferred via MIDI interface
+ // and emulation of the MCU busy-loop while it frees partials for use by a new Poly.
+ // Calls from multiple threads must be synchronised, although,
+ // no synchronisation is required with the rendering thread.
+
+ // The MIDI event will be processed not before the specified timestamp.
+ // The timestamp is measured as the global rendered sample count since the synth was created.
+ bool playMsg(Bit32u msg, Bit32u timestamp);
+ bool playSysex(const Bit8u *sysex, Bit32u len, Bit32u timestamp);
+ // The MIDI event will be processed ASAP.
+ bool playMsg(Bit32u msg);
+ bool playSysex(const Bit8u *sysex, Bit32u len);
+
+ // WARNING:
+ // The methods below don't ensure minimum 1-sample delay between sequential MIDI events,
+ // and a sequence of NoteOn and immediately succeeding NoteOff messages is always silent.
+
+ // Sends a 4-byte MIDI message to the MT-32 for immediate playback.
+ void playMsgNow(Bit32u msg);
void playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity);
// Sends a string of Sysex commands to the MT-32 for immediate interpretation
// The length is in bytes
- void playSysex(const Bit8u *sysex, Bit32u len);
+ void playSysexNow(const Bit8u *sysex, Bit32u len);
void playSysexWithoutFraming(const Bit8u *sysex, Bit32u len);
void playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len);
void writeSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
@@ -407,20 +467,34 @@ public:
void setReverbOverridden(bool reverbOverridden);
bool isReverbOverridden() const;
void setDACInputMode(DACInputMode mode);
+ DACInputMode getDACInputMode() const;
+ void setMIDIDelayMode(MIDIDelayMode mode);
+ MIDIDelayMode getMIDIDelayMode() const;
// Sets output gain factor. Applied to all output samples and unrelated with the synth's Master volume.
+ // Ignored in DACInputMode_PURE
void setOutputGain(float);
+ float getOutputGain() const;
// Sets output gain factor for the reverb wet output. setOutputGain() doesn't change reverb output gain.
+ // Note: We're currently emulate CM-32L/CM-64 reverb quite accurately and the reverb output level closely
+ // corresponds to the level of digital capture. Although, according to the CM-64 PCB schematic,
+ // there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68
+ // of that for LA32 analogue output. This factor is applied to the reverb output gain.
+ // Ignored in DACInputMode_PURE
void setReverbOutputGain(float);
+ float getReverbOutputGain() const;
+
+ void setReversedStereoEnabled(bool enabled);
+ bool isReversedStereoEnabled();
// Renders samples to the specified output stream.
// The length is in frames, not bytes (in 16-bit stereo,
// one frame is 4 bytes).
- void render(Bit16s *stream, Bit32u len);
+ void render(Sample *stream, Bit32u len);
// Renders samples to the specified output streams (any or all of which may be NULL).
- void renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len);
+ void renderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len);
// Returns true when there is at least one active partial, otherwise false.
bool hasActivePartials() const;
@@ -430,6 +504,9 @@ public:
const Partial *getPartial(unsigned int partialNum) const;
+ // Returns the maximum number of partials playing simultaneously.
+ unsigned int getPartialCount() const;
+
void readMemory(Bit32u addr, Bit32u len, Bit8u *data);
// partNum should be 0..7 for Part 1..8, or 8 for Rhythm
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/audio/softsynth/mt32/TVP.cpp b/audio/softsynth/mt32/TVP.cpp
index c3e64c18d0..8f68245753 100644
--- a/audio/softsynth/mt32/TVP.cpp
+++ b/audio/softsynth/mt32/TVP.cpp
@@ -181,7 +181,7 @@ void TVP::updatePitch() {
pitch = (Bit16u)newPitch;
// FIXME: We're doing this here because that's what the CM-32L does - we should probably move this somewhere more appropriate in future.
- partial->tva->recalcSustain();
+ partial->getTVA()->recalcSustain();
}
void TVP::targetPitchOffsetReached() {
diff --git a/audio/softsynth/mt32/Tables.h b/audio/softsynth/mt32/Tables.h
index 8b4580df0e..bfb80e121e 100644
--- a/audio/softsynth/mt32/Tables.h
+++ b/audio/softsynth/mt32/Tables.h
@@ -25,6 +25,11 @@ namespace MT32Emu {
// The output from the synth is supposed to be resampled to convert the sample rate.
const unsigned int SAMPLE_RATE = 32000;
+// MIDI interface data transfer rate in samples. Used to simulate the transfer delay.
+const double MIDI_DATA_TRANSFER_RATE = (double)SAMPLE_RATE / 31250.0 * 8.0;
+
+const float CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR = 0.68f;
+
const int MIDDLEC = 60;
class Synth;
diff --git a/audio/softsynth/mt32/freeverb.cpp b/audio/softsynth/mt32/freeverb.cpp
deleted file mode 100644
index 181b878596..0000000000
--- a/audio/softsynth/mt32/freeverb.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-// Allpass filter implementation
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-#include "freeverb.h"
-
-allpass::allpass()
-{
- bufidx = 0;
-}
-
-void allpass::setbuffer(float *buf, int size)
-{
- buffer = buf;
- bufsize = size;
-}
-
-void allpass::mute()
-{
- for (int i=0; i<bufsize; i++)
- buffer[i]=0;
-}
-
-void allpass::setfeedback(float val)
-{
- feedback = val;
-}
-
-float allpass::getfeedback()
-{
- return feedback;
-}
-
-void allpass::deletebuffer()
-{
- delete[] buffer;
- buffer = 0;
-}
-// Comb filter implementation
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-comb::comb()
-{
- filterstore = 0;
- bufidx = 0;
-}
-
-void comb::setbuffer(float *buf, int size)
-{
- buffer = buf;
- bufsize = size;
-}
-
-void comb::mute()
-{
- for (int i=0; i<bufsize; i++)
- buffer[i]=0;
-}
-
-void comb::setdamp(float val)
-{
- damp1 = val;
- damp2 = 1-val;
-}
-
-float comb::getdamp()
-{
- return damp1;
-}
-
-void comb::setfeedback(float val)
-{
- feedback = val;
-}
-
-float comb::getfeedback()
-{
- return feedback;
-}
-
-void comb::deletebuffer()
-{
- delete[] buffer;
- buffer = 0;
-}
-// Reverb model implementation
-//
-// Written by Jezar at Dreampoint, June 2000
-// Modifications by Jerome Fisher, 2009, 2011
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-revmodel::revmodel(float scaletuning)
-{
- int i;
- int bufsize;
-
- // Allocate buffers for the components
- for (i = 0; i < numcombs; i++) {
- bufsize = int(scaletuning * combtuning[i]);
- combL[i].setbuffer(new float[bufsize], bufsize);
- bufsize += int(scaletuning * stereospread);
- combR[i].setbuffer(new float[bufsize], bufsize);
- }
- for (i = 0; i < numallpasses; i++) {
- bufsize = int(scaletuning * allpasstuning[i]);
- allpassL[i].setbuffer(new float[bufsize], bufsize);
- allpassL[i].setfeedback(0.5f);
- bufsize += int(scaletuning * stereospread);
- allpassR[i].setbuffer(new float[bufsize], bufsize);
- allpassR[i].setfeedback(0.5f);
- }
-
- // Set default values
- dry = initialdry;
- wet = initialwet*scalewet;
- damp = initialdamp*scaledamp;
- roomsize = (initialroom*scaleroom) + offsetroom;
- width = initialwidth;
- mode = initialmode;
- update();
-
- // Buffer will be full of rubbish - so we MUST mute them
- mute();
-}
-
-revmodel::~revmodel()
-{
- int i;
-
- for (i = 0; i < numcombs; i++) {
- combL[i].deletebuffer();
- combR[i].deletebuffer();
- }
- for (i = 0; i < numallpasses; i++) {
- allpassL[i].deletebuffer();
- allpassR[i].deletebuffer();
- }
-}
-
-void revmodel::mute()
-{
- int i;
-
- if (getmode() >= freezemode)
- return;
-
- for (i=0;i<numcombs;i++)
- {
- combL[i].mute();
- combR[i].mute();
- }
- for (i=0;i<numallpasses;i++)
- {
- allpassL[i].mute();
- allpassR[i].mute();
- }
-
- // Init LPF history
- filtprev1 = 0;
- filtprev2 = 0;
-}
-
-void revmodel::process(const float *inputL, const float *inputR, float *outputL, float *outputR, long numsamples)
-{
- float outL,outR,input;
-
- while (numsamples-- > 0)
- {
- int i;
-
- outL = outR = 0;
- input = (*inputL + *inputR) * gain;
-
- // Implementation of 2-stage IIR single-pole low-pass filter
- // found at the entrance of reverb processing on real devices
- filtprev1 += (input - filtprev1) * filtval;
- filtprev2 += (filtprev1 - filtprev2) * filtval;
- input = filtprev2;
-
- int s = -1;
- // Accumulate comb filters in parallel
- for (i=0; i<numcombs; i++)
- {
- outL += s * combL[i].process(input);
- outR += s * combR[i].process(input);
- s = -s;
- }
-
- // Feed through allpasses in series
- for (i=0; i<numallpasses; i++)
- {
- outL = allpassL[i].process(outL);
- outR = allpassR[i].process(outR);
- }
-
- // Calculate output REPLACING anything already there
- *outputL = outL*wet1 + outR*wet2;
- *outputR = outR*wet1 + outL*wet2;
-
- inputL++;
- inputR++;
- outputL++;
- outputR++;
- }
-}
-
-void revmodel::update()
-{
-// Recalculate internal values after parameter change
-
- int i;
-
- wet1 = wet*(width/2 + 0.5f);
- wet2 = wet*((1-width)/2);
-
- if (mode >= freezemode)
- {
- roomsize1 = 1;
- damp1 = 0;
- gain = muted;
- }
- else
- {
- roomsize1 = roomsize;
- damp1 = damp;
- gain = fixedgain;
- }
-
- for (i=0; i<numcombs; i++)
- {
- combL[i].setfeedback(roomsize1);
- combR[i].setfeedback(roomsize1);
- }
-
- for (i=0; i<numcombs; i++)
- {
- combL[i].setdamp(damp1);
- combR[i].setdamp(damp1);
- }
-}
-
-// The following get/set functions are not inlined, because
-// speed is never an issue when calling them, and also
-// because as you develop the reverb model, you may
-// wish to take dynamic action when they are called.
-
-void revmodel::setroomsize(float value)
-{
- roomsize = (value*scaleroom) + offsetroom;
- update();
-}
-
-float revmodel::getroomsize()
-{
- return (roomsize-offsetroom)/scaleroom;
-}
-
-void revmodel::setdamp(float value)
-{
- damp = value*scaledamp;
- update();
-}
-
-float revmodel::getdamp()
-{
- return damp/scaledamp;
-}
-
-void revmodel::setwet(float value)
-{
- wet = value*scalewet;
- update();
-}
-
-float revmodel::getwet()
-{
- return wet/scalewet;
-}
-
-void revmodel::setdry(float value)
-{
- dry = value*scaledry;
-}
-
-float revmodel::getdry()
-{
- return dry/scaledry;
-}
-
-void revmodel::setwidth(float value)
-{
- width = value;
- update();
-}
-
-float revmodel::getwidth()
-{
- return width;
-}
-
-void revmodel::setmode(float value)
-{
- mode = value;
- update();
-}
-
-float revmodel::getmode()
-{
- if (mode >= freezemode)
- return 1;
- else
- return 0;
-}
-
-void revmodel::setfiltval(float value)
-{
- filtval = value;
-}
diff --git a/audio/softsynth/mt32/freeverb.h b/audio/softsynth/mt32/freeverb.h
deleted file mode 100644
index ae4d48169e..0000000000
--- a/audio/softsynth/mt32/freeverb.h
+++ /dev/null
@@ -1,189 +0,0 @@
-#ifndef _freeverb_
-#define _freeverb_
-
-// Reverb model tuning values
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-const int numcombs = 8;
-const int numallpasses = 4;
-const float muted = 0;
-const float fixedgain = 0.015f;
-const float scalewet = 3;
-const float scaledry = 2;
-const float scaledamp = 0.4f;
-const float scaleroom = 0.28f;
-const float offsetroom = 0.7f;
-const float initialroom = 0.5f;
-const float initialdamp = 0.5f;
-const float initialwet = 1/scalewet;
-const float initialdry = 0;
-const float initialwidth = 1;
-const float initialmode = 0;
-const float freezemode = 0.5f;
-const int stereospread = 23;
-
-const int combtuning[] = {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617};
-const int allpasstuning[] = {556, 441, 341, 225};
-
-// Macro for killing denormalled numbers
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// Based on IS_DENORMAL macro by Jon Watte
-// This code is public domain
-
-static inline float undenormalise(float x) {
- union {
- float f;
- unsigned int i;
- } u;
- u.f = x;
- if ((u.i & 0x7f800000) == 0) {
- return 0.0f;
- }
- return x;
-}
-
-// Allpass filter declaration
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-class allpass
-{
-public:
- allpass();
- void setbuffer(float *buf, int size);
- void deletebuffer();
- inline float process(float inp);
- void mute();
- void setfeedback(float val);
- float getfeedback();
-// private:
- float feedback;
- float *buffer;
- int bufsize;
- int bufidx;
-};
-
-
-// Big to inline - but crucial for speed
-
-inline float allpass::process(float input)
-{
- float output;
- float bufout;
-
- bufout = undenormalise(buffer[bufidx]);
-
- output = -input + bufout;
- buffer[bufidx] = input + (bufout*feedback);
-
- if (++bufidx>=bufsize) bufidx = 0;
-
- return output;
-}
-
-// Comb filter class declaration
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-class comb
-{
-public:
- comb();
- void setbuffer(float *buf, int size);
- void deletebuffer();
- inline float process(float inp);
- void mute();
- void setdamp(float val);
- float getdamp();
- void setfeedback(float val);
- float getfeedback();
-private:
- float feedback;
- float filterstore;
- float damp1;
- float damp2;
- float *buffer;
- int bufsize;
- int bufidx;
-};
-
-
-// Big to inline - but crucial for speed
-
-inline float comb::process(float input)
-{
- float output;
-
- output = undenormalise(buffer[bufidx]);
-
- filterstore = undenormalise((output*damp2) + (filterstore*damp1));
-
- buffer[bufidx] = input + (filterstore*feedback);
-
- if (++bufidx>=bufsize) bufidx = 0;
-
- return output;
-}
-
-// Reverb model declaration
-//
-// Written by Jezar at Dreampoint, June 2000
-// Modifications by Jerome Fisher, 2009
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-class revmodel
-{
-public:
- revmodel(float scaletuning);
- ~revmodel();
- void mute();
- void process(const float *inputL, const float *inputR, float *outputL, float *outputR, long numsamples);
- void setroomsize(float value);
- float getroomsize();
- void setdamp(float value);
- float getdamp();
- void setwet(float value);
- float getwet();
- void setdry(float value);
- float getdry();
- void setwidth(float value);
- float getwidth();
- void setmode(float value);
- float getmode();
- void setfiltval(float value);
-private:
- void update();
-private:
- float gain;
- float roomsize,roomsize1;
- float damp,damp1;
- float wet,wet1,wet2;
- float dry;
- float width;
- float mode;
-
- // LPF stuff
- float filtval;
- float filtprev1;
- float filtprev2;
-
- // Comb filters
- comb combL[numcombs];
- comb combR[numcombs];
-
- // Allpass filters
- allpass allpassL[numallpasses];
- allpass allpassR[numallpasses];
-};
-
-#endif//_freeverb_
diff --git a/audio/softsynth/mt32/module.mk b/audio/softsynth/mt32/module.mk
index e7afdfd2b4..1c8aa125ab 100644
--- a/audio/softsynth/mt32/module.mk
+++ b/audio/softsynth/mt32/module.mk
@@ -1,24 +1,19 @@
MODULE := audio/softsynth/mt32
MODULE_OBJS := \
- AReverbModel.o \
BReverbModel.o \
- DelayReverb.o \
- FreeverbModel.o \
LA32Ramp.o \
LA32WaveGenerator.o \
- LegacyWaveGenerator.o \
Part.o \
Partial.o \
PartialManager.o \
Poly.o \
ROMInfo.o \
Synth.o \
+ Tables.o \
TVA.o \
TVF.o \
- TVP.o \
- Tables.o \
- freeverb.o
+ TVP.o
# Include common rules
include $(srcdir)/rules.mk
diff --git a/audio/softsynth/mt32/mt32emu.h b/audio/softsynth/mt32/mt32emu.h
index 971a0886d5..ab963886ac 100644
--- a/audio/softsynth/mt32/mt32emu.h
+++ b/audio/softsynth/mt32/mt32emu.h
@@ -60,27 +60,24 @@
#define MT32EMU_MONITOR_TVF 0
// Configuration
-// The maximum number of partials playing simultaneously
-#define MT32EMU_MAX_PARTIALS 32
-// The maximum number of notes playing simultaneously per part.
-// No point making it more than MT32EMU_MAX_PARTIALS, since each note needs at least one partial.
-#define MT32EMU_MAX_POLY 32
// If non-zero, deletes reverb buffers that are not in use to save memory.
// If zero, keeps reverb buffers for all modes around all the time to avoid allocating/freeing in the critical path.
#define MT32EMU_REDUCE_REVERB_MEMORY 1
-// 0: Use legacy Freeverb
-// 1: Use Accurate Reverb model aka AReverb
-// 2: Use Bit-perfect Boss Reverb model aka BReverb (for developers, not much practical use)
-#define MT32EMU_USE_REVERBMODEL 1
+// 0: Maximum speed at the cost of a bit lower emulation accuracy.
+// 1: Maximum achievable emulation accuracy.
+#define MT32EMU_BOSS_REVERB_PRECISE_MODE 0
-// 0: Use refined wave generator based on logarithmic fixed-point computations and LUTs
-// 1: Use legacy accurate wave generator based on float computations
-#define MT32EMU_ACCURATE_WG 0
+// 0: Use 16-bit signed samples and refined wave generator based on logarithmic fixed-point computations and LUTs. Maximum emulation accuracy and speed.
+// 1: Use float samples in the wave generator and renderer. Maximum output quality and minimum noise.
+#define MT32EMU_USE_FLOAT_SAMPLES 0
namespace MT32Emu
{
+// The default value for the maximum number of partials playing simultaneously.
+const unsigned int DEFAULT_MAX_PARTIALS = 32;
+
// The higher this number, the more memory will be used, but the more samples can be processed in one run -
// various parts of sample generation can be processed more efficiently in a single run.
// A run's maximum length is that given to Synth::render(), so giving a value here higher than render() is ever
@@ -90,11 +87,14 @@ namespace MT32Emu
// This value must be >= 1.
const unsigned int MAX_SAMPLES_PER_RUN = 4096;
-// This determines the amount of memory available for simulating delays.
-// If set too low, partials aborted to allow other partials to play will not end gracefully, but will terminate
-// abruptly and potentially cause a pop/crackle in the audio output.
-// This value must be >= 1.
-const unsigned int MAX_PRERENDER_SAMPLES = 1024;
+// The default size of the internal MIDI event queue.
+// It holds the incoming MIDI events before the rendering engine actually processes them.
+// The main goal is to fairly emulate the real hardware behaviour which obviously
+// uses an internal MIDI event queue to gather incoming data as well as the delays
+// introduced by transferring data via the MIDI interface.
+// This also facilitates building of an external rendering loop
+// as the queue stores timestamped MIDI events.
+const unsigned int DEFAULT_MIDI_EVENT_QUEUE_SIZE = 1024;
}
#include "Structures.h"
@@ -103,7 +103,6 @@ const unsigned int MAX_PRERENDER_SAMPLES = 1024;
#include "Poly.h"
#include "LA32Ramp.h"
#include "LA32WaveGenerator.h"
-#include "LegacyWaveGenerator.h"
#include "TVA.h"
#include "TVP.h"
#include "TVF.h"
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h
index 0afc6af991..76c3998862 100644
--- a/backends/audiocd/audiocd.h
+++ b/backends/audiocd/audiocd.h
@@ -110,7 +110,7 @@ public:
/**
* Initialize the specified CD drive for audio playback.
* @param drive the drive id
- * @return true if the CD drive was inited succesfully
+ * @return true if the CD drive was inited successfully
*/
virtual bool openCD(int drive) = 0;
diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp
index 3e0005dedd..3e95c3e26a 100644
--- a/backends/base-backend.cpp
+++ b/backends/base-backend.cpp
@@ -57,7 +57,7 @@ void BaseBackend::initBackend() {
void BaseBackend::fillScreen(uint32 col) {
Graphics::Surface *screen = lockScreen();
- if (screen && screen->pixels)
- memset(screen->pixels, col, screen->h * screen->pitch);
+ if (screen && screen->getPixels())
+ memset(screen->getPixels(), col, screen->h * screen->pitch);
unlockScreen();
}
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 38a0c8d46f..30f3b3790c 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -54,6 +54,8 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
_currentKeyDown.ascii = 0;
_currentKeyDown.flags = 0;
+ _keyRepeatTime = 0;
+
#ifdef ENABLE_VKEYBD
_vk = new Common::VirtualKeyboard();
#endif
@@ -84,7 +86,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..e84a8f8c01 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) {
@@ -389,8 +391,17 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
return false;
case SDL_VIDEORESIZE:
- if (_graphicsManager)
+ if (_graphicsManager) {
_graphicsManager->notifyResize(ev.resize.w, ev.resize.h);
+
+ // If the screen changed, send an Common::EVENT_SCREEN_CHANGED
+ int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
+ if (screenID != _lastScreenID) {
+ _lastScreenID = screenID;
+ event.type = Common::EVENT_SCREEN_CHANGED;
+ return true;
+ }
+ }
return false;
case SDL_QUIT:
diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h
index 54e3958972..2b66a6e6e1 100644
--- a/backends/fs/abstract-fs.h
+++ b/backends/fs/abstract-fs.h
@@ -100,7 +100,7 @@ public:
* @param mode Mode to use while listing the directory.
* @param hidden Whether to include hidden files or not in the results.
*
- * @return true if succesful, false otherwise (e.g. when the directory does not exist).
+ * @return true if successful, false otherwise (e.g. when the directory does not exist).
*/
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const = 0;
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index fe388c2a6e..6d713f10be 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -335,7 +335,7 @@ bool AmigaOSFilesystemNode::isReadable() const {
// Regular RWED protection flags are low-active or inverted, thus the negation.
// moreover pseudo root filesystem (null _pFileLock) is readable whatever the
// protection says
- bool readable = !(_nProt & EXDF_READ) || _pFileLock == 0;
+ bool readable = !(_nProt & EXDF_OTR_READ) || _pFileLock == 0;
return readable;
}
@@ -344,7 +344,7 @@ bool AmigaOSFilesystemNode::isWritable() const {
// Regular RWED protection flags are low-active or inverted, thus the negation.
// moreover pseudo root filesystem (null _pFileLock) is never writable whatever
// the protection says (because of the pseudo nature)
- bool writable = !(_nProt & EXDF_WRITE) && _pFileLock !=0;
+ bool writable = !(_nProt & EXDF_OTR_WRITE) && _pFileLock !=0;
return writable;
}
@@ -367,8 +367,14 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES);
while (dosList) {
if (dosList->dol_Type == DLT_VOLUME &&
- dosList->dol_Name &&
- dosList->dol_Task) {
+ dosList->dol_Name) {
+
+ // Original was
+ // dosList->dol_Name &&
+ // dosList->dol_Task) {
+ // which errored using SDK 53.24 with a 'struct dosList' has no member called 'dol_Task'
+ // I removed dol_Task because it's not used anywhere else
+ // and it neither brought up further errors nor crashes or regressions.
// Copy name to buffer
IDOS->CopyStringBSTRToC(dosList->dol_Name, buffer, MAXPATHLEN);
diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h
index 24397228e6..74258b8910 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -37,6 +37,27 @@ class GraphicsManager : public PaletteManager {
public:
virtual ~GraphicsManager() {}
+ /**
+ * Makes this graphics manager active. That means it should be ready to
+ * process inputs now. However, even without being active it should be
+ * able to query the supported modes and other bits.
+ *
+ * HACK: Actually this is specific to SdlGraphicsManager subclasses.
+ * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager
+ * because there is no relation between these two.
+ */
+ virtual void activateManager() {}
+
+ /**
+ * Makes this graphics manager inactive. This should allow another
+ * graphics manager to become active again.
+ *
+ * HACK: Actually this is specific to SdlGraphicsManager subclasses.
+ * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager
+ * because there is no relation between these two.
+ */
+ virtual void deactivateManager() {}
+
virtual bool hasFeature(OSystem::Feature f) = 0;
virtual void setFeatureState(OSystem::Feature f, bool enable) = 0;
virtual bool getFeatureState(OSystem::Feature f) = 0;
diff --git a/backends/graphics/opengl/debug.cpp b/backends/graphics/opengl/debug.cpp
new file mode 100644
index 0000000000..69006bb975
--- /dev/null
+++ b/backends/graphics/opengl/debug.cpp
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/graphics/opengl/debug.h"
+#include "backends/graphics/opengl/opengl-sys.h"
+
+#include "common/str.h"
+#include "common/textconsole.h"
+
+#ifdef OPENGL_DEBUG
+
+namespace OpenGL {
+
+namespace {
+Common::String getGLErrStr(GLenum error) {
+ switch (error) {
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
+ }
+
+ return Common::String::format("(Unknown GL error code 0x%X)", error);
+}
+} // End of anonymous namespace
+
+void checkGLError(const char *expr, const char *file, int line) {
+ GLenum error = glGetError();
+
+ if (error != GL_NO_ERROR) {
+ // We cannot use error here because we do not know whether we have a
+ // working screen or not.
+ warning("GL ERROR: %s on %s (%s:%d)", getGLErrStr(error).c_str(), expr, file, line);
+ }
+}
+} // End of namespace OpenGL
+
+#endif
diff --git a/backends/graphics/opengl/debug.h b/backends/graphics/opengl/debug.h
new file mode 100644
index 0000000000..ff6b678870
--- /dev/null
+++ b/backends/graphics/opengl/debug.h
@@ -0,0 +1,39 @@
+/* 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_GRAPHICS_OPENGL_DEBUG_H
+#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H
+
+#define OPENGL_DEBUG
+
+#ifdef OPENGL_DEBUG
+
+namespace OpenGL {
+void checkGLError(const char *expr, const char *file, int line);
+} // End of namespace OpenGL
+
+#define GLCALL(x) do { (x); OpenGL::checkGLError(#x, __FILE__, __LINE__); } while (false)
+#else
+#define GLCALL(x) do { (x); } while (false)
+#endif
+
+#endif
diff --git a/backends/graphics/opengl/extensions.cpp b/backends/graphics/opengl/extensions.cpp
new file mode 100644
index 0000000000..4482ef82b5
--- /dev/null
+++ b/backends/graphics/opengl/extensions.cpp
@@ -0,0 +1,48 @@
+/* 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/graphics/opengl/extensions.h"
+#include "backends/graphics/opengl/opengl-sys.h"
+
+#include "common/tokenizer.h"
+
+namespace OpenGL {
+
+bool g_extNPOTSupported = false;
+
+void initializeGLExtensions() {
+ const char *extString = (const char *)glGetString(GL_EXTENSIONS);
+
+ // Initialize default state.
+ g_extNPOTSupported = false;
+
+ Common::StringTokenizer tokenizer(extString, " ");
+ while (!tokenizer.empty()) {
+ Common::String token = tokenizer.nextToken();
+
+ if (token == "GL_ARB_texture_non_power_of_two") {
+ g_extNPOTSupported = true;
+ }
+ }
+}
+
+} // End of namespace OpenGL
diff --git a/backends/graphics/opengl/extensions.h b/backends/graphics/opengl/extensions.h
new file mode 100644
index 0000000000..87452429e2
--- /dev/null
+++ b/backends/graphics/opengl/extensions.h
@@ -0,0 +1,41 @@
+/* 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_GRAPHICS_OPENGL_EXTENSIONS_H
+#define BACKENDS_GRAPHICS_OPENGL_EXTENSIONS_H
+
+namespace OpenGL {
+
+/**
+ * Checks for availability of extensions we want to use and initializes them
+ * when available.
+ */
+void initializeGLExtensions();
+
+/**
+ * Whether non power of two textures are supported
+ */
+extern bool g_extNPOTSupported;
+
+} // End of namespace OpenGL
+
+#endif
diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp
deleted file mode 100644
index ca674563df..0000000000
--- a/backends/graphics/opengl/gltexture.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/scummsys.h"
-
-#if defined(USE_OPENGL)
-
-#include "backends/graphics/opengl/gltexture.h"
-#include "backends/graphics/opengl/glerrorcheck.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-#include "common/tokenizer.h"
-
-// Supported GL extensions
-static bool npot_supported = false;
-static bool glext_inited = false;
-
-/*static inline GLint xdiv(int numerator, int denominator) {
- assert(numerator < (1 << 16));
- return (numerator << 16) / denominator;
-}*/
-
-static GLuint nextHigher2(GLuint v) {
- if (v == 0)
- return 1;
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- return ++v;
-}
-
-void GLTexture::initGLExtensions() {
-
- // Return if extensions were already checked
- if (glext_inited)
- return;
-
- // Get a string with all extensions
- const char *ext_string = (const char *)glGetString(GL_EXTENSIONS);
- CHECK_GL_ERROR();
- Common::StringTokenizer tokenizer(ext_string, " ");
- // Iterate all string tokens
- while (!tokenizer.empty()) {
- Common::String token = tokenizer.nextToken();
- if (token == "GL_ARB_texture_non_power_of_two")
- npot_supported = true;
- }
-
- glext_inited = true;
-}
-
-GLTexture::GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type)
- :
- _bytesPerPixel(bpp),
- _internalFormat(internalFormat),
- _glFormat(format),
- _glType(type),
- _textureWidth(0),
- _textureHeight(0),
- _realWidth(0),
- _realHeight(0),
- _refresh(false),
- _filter(GL_NEAREST) {
-
- // Generate the texture ID
- glGenTextures(1, &_textureName); CHECK_GL_ERROR();
-}
-
-GLTexture::~GLTexture() {
- // Delete the texture
- glDeleteTextures(1, &_textureName); CHECK_GL_ERROR();
-}
-
-void GLTexture::refresh() {
- // Delete previous texture
- glDeleteTextures(1, &_textureName); CHECK_GL_ERROR();
-
- // Generate the texture ID
- glGenTextures(1, &_textureName); CHECK_GL_ERROR();
- _refresh = true;
-}
-
-void GLTexture::allocBuffer(GLuint w, GLuint h) {
- _realWidth = w;
- _realHeight = h;
-
- if (!_refresh) {
- if (npot_supported && _filter == GL_LINEAR) {
- // Check if we already allocated a correctly-sized buffer
- // This is so we don't need to duplicate the last row/column
- if (w == _textureWidth && h == _textureHeight)
- return;
- } else {
- // Check if we already have a large enough buffer
- if (w <= _textureWidth && h <= _textureHeight)
- return;
- }
- }
-
- if (npot_supported) {
- _textureWidth = w;
- _textureHeight = h;
- } else {
- _textureWidth = nextHigher2(w);
- _textureHeight = nextHigher2(h);
- }
-
- // Select this OpenGL texture
- glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
-
- // Set the texture parameters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _filter); CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _filter); CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
-
- // Allocate room for the texture
- glTexImage2D(GL_TEXTURE_2D, 0, _internalFormat,
- _textureWidth, _textureHeight, 0, _glFormat, _glType, NULL); CHECK_GL_ERROR();
-
- _refresh = false;
-}
-
-void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) {
- // Skip empty updates.
- if (w * h == 0)
- return;
-
- // Select this OpenGL texture
- glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
-
- // Check if the buffer has its data contiguously
- if ((int)w * _bytesPerPixel == pitch) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
- _glFormat, _glType, buf); CHECK_GL_ERROR();
- } else {
- // Update the texture row by row
- const byte *src = (const byte *)buf;
- GLuint curY = y;
- GLuint height = h;
- do {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, curY,
- w, 1, _glFormat, _glType, src); CHECK_GL_ERROR();
- curY++;
- src += pitch;
- } while (--height);
- }
-
- // If we're in linear filter mode, repeat the last row/column if the real dimensions
- // doesn't match the texture dimensions.
- if (_filter == GL_LINEAR) {
- if (_realWidth != _textureWidth && x + w == _realWidth) {
- const byte *src = (const byte *)buf + (w - 1) * _bytesPerPixel;
- GLuint curY = y;
- GLuint height = h;
-
- do {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x + w,
- curY, 1, 1, _glFormat, _glType, src); CHECK_GL_ERROR();
-
- curY++;
- src += pitch;
- } while (--height);
- }
-
- if (_realHeight != _textureHeight && y + h == _realHeight) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y + h,
- w, 1, _glFormat, _glType, (const byte *)buf + pitch * (h - 1)); CHECK_GL_ERROR();
- }
- }
-}
-
-void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- // Select this OpenGL texture
- glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
-
- // Calculate the texture rect that will be drawn
- const GLfloat texWidth = (GLfloat)_realWidth / _textureWidth;//xdiv(_surface.w, _textureWidth);
- const GLfloat texHeight = (GLfloat)_realHeight / _textureHeight;//xdiv(_surface.h, _textureHeight);
- const GLfloat texcoords[] = {
- 0, 0,
- texWidth, 0,
- 0, texHeight,
- texWidth, texHeight,
- };
- glTexCoordPointer(2, GL_FLOAT, 0, texcoords); CHECK_GL_ERROR();
-
- // Calculate the screen rect where the texture will be drawn
- const GLshort vertices[] = {
- x, y,
- (GLshort)(x + w), y,
- x, (GLshort)(y + h),
- (GLshort)(x + w), (GLshort)(y + h),
- };
- glVertexPointer(2, GL_SHORT, 0, vertices); CHECK_GL_ERROR();
-
- // Draw the texture to the screen buffer
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); CHECK_GL_ERROR();
-}
-
-#endif
diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h
deleted file mode 100644
index 8ff9838ff7..0000000000
--- a/backends/graphics/opengl/gltexture.h
+++ /dev/null
@@ -1,131 +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 BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H
-#define BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H
-
-#include "common/scummsys.h"
-
-#ifdef WIN32
-#if defined(ARRAYSIZE) && !defined(_WINDOWS_)
-#undef ARRAYSIZE
-#endif
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef ARRAYSIZE
-#endif
-
-// HACK: At this point in Windows platforms, common/util.h has been included
-// via common/rect.h (from backends/graphics/sdl/sdl-graphics.h), via
-// backends/graphics/openglsdl/openglsdl-graphics.h. Thus, we end up with
-// COMMON_UTIL_H defined, and ARRAYSIZE undefined (bad!). Therefore,
-// ARRAYSIZE is undefined in openglsdl-graphics.cpp. This is a temporary
-// hackish solution fo fix compilation under Windows.
-#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H)
-#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
-#endif
-
-#if defined(BADA)
-#include <FGraphicsOpengl.h>
-using namespace Osp::Graphics::Opengl;
-#elif defined(USE_GLES)
-#include <GLES/gl.h>
-#elif defined(SDL_BACKEND)
-#include <SDL_opengl.h>
-#else
-#include <GL/gl.h>
-#endif
-
-#include "graphics/surface.h"
-
-/**
- * OpenGL texture manager class
- */
-class GLTexture {
-public:
- /**
- * Initialize OpenGL Extensions
- */
- static void initGLExtensions();
-
- GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type);
- ~GLTexture();
-
- /**
- * Refresh the texture after a context change. The
- * process will be completed on next allocBuffer call.
- */
- void refresh();
-
- /**
- * Allocates memory needed for the given size.
- */
- void allocBuffer(GLuint width, GLuint height);
-
- /**
- * Updates the texture pixels.
- */
- void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y,
- GLuint w, GLuint h);
-
- /**
- * Draws the texture to the screen buffer.
- */
- void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
- /**
- * Get the texture width.
- */
- GLuint getWidth() const { return _realWidth; }
-
- /**
- * Get the texture height.
- */
- GLuint getHeight() const { return _realHeight; }
-
- /**
- * Get the bytes per pixel.
- */
- uint getBytesPerPixel() const { return _bytesPerPixel; }
-
- /**
- * Set the texture filter.
- * @filter the filter type, GL_NEAREST or GL_LINEAR
- */
- void setFilter(GLint filter) { _filter = filter; }
-
-private:
- const byte _bytesPerPixel;
- const GLenum _internalFormat;
- const GLenum _glFormat;
- const GLenum _glType;
-
- GLuint _realWidth;
- GLuint _realHeight;
- GLuint _textureName;
- GLuint _textureWidth;
- GLuint _textureHeight;
- GLint _filter;
- bool _refresh;
-};
-
-#endif
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 48e2663d44..a97f680f15 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -8,102 +8,90 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#include "common/scummsys.h"
-
-#if defined(USE_OPENGL)
#include "backends/graphics/opengl/opengl-graphics.h"
-#include "backends/graphics/opengl/glerrorcheck.h"
-#include "common/config-manager.h"
-#include "common/file.h"
-#include "common/mutex.h"
+#include "backends/graphics/opengl/texture.h"
+#include "backends/graphics/opengl/debug.h"
+#include "backends/graphics/opengl/extensions.h"
+
#include "common/textconsole.h"
#include "common/translation.h"
+#include "common/algorithm.h"
+#include "common/file.h"
#ifdef USE_OSD
#include "common/tokenizer.h"
+#include "common/rect.h"
#endif
-#include "graphics/font.h"
+
+#include "graphics/conversion.h"
+#ifdef USE_OSD
#include "graphics/fontman.h"
+#include "graphics/font.h"
+#endif
+
+namespace OpenGL {
OpenGLGraphicsManager::OpenGLGraphicsManager()
- :
+ : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)),
+ _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0),
+ _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(),
+ _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr),
+ _overlayVisible(false), _cursor(nullptr),
+ _cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0),
+ _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0),
+ _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false)
#ifdef USE_OSD
- _osdTexture(0), _osdAlpha(0), _osdFadeStartTime(0), _requireOSDUpdate(false),
+ , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
- _gameTexture(0), _overlayTexture(0), _cursorTexture(0),
- _screenChangeCount(1 << (sizeof(int) * 8 - 2)), _screenNeedsRedraw(false),
- _shakePos(0),
- _overlayVisible(false), _overlayNeedsRedraw(false),
- _transactionMode(kTransactionNone),
- _cursorNeedsRedraw(false), _cursorPaletteDisabled(true),
- _cursorVisible(false), _cursorKeyColor(0),
- _cursorDontScale(false),
- _formatBGR(false),
- _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) {
-
- memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
- memset(&_videoMode, 0, sizeof(_videoMode));
- memset(&_transactionDetails, 0, sizeof(_transactionDetails));
-
- _videoMode.mode = OpenGL::GFX_NORMAL;
- _videoMode.scaleFactor = 2;
- _videoMode.fullscreen = ConfMan.getBool("fullscreen");
- _videoMode.antialiasing = false;
-
- _gamePalette = (byte *)calloc(sizeof(byte) * 3, 256);
- _cursorPalette = (byte *)calloc(sizeof(byte) * 3, 256);
+ {
+ memset(_gamePalette, 0, sizeof(_gamePalette));
}
OpenGLGraphicsManager::~OpenGLGraphicsManager() {
- free(_gamePalette);
- free(_cursorPalette);
-
- _screenData.free();
- _overlayData.free();
- _cursorData.free();
- _osdSurface.free();
-
- delete _gameTexture;
- delete _overlayTexture;
- delete _cursorTexture;
+ delete _gameScreen;
+ delete _overlay;
+ delete _cursor;
+#ifdef USE_OSD
+ delete _osd;
+#endif
}
-//
-// Feature
-//
-
bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
- return
- (f == OSystem::kFeatureAspectRatioCorrection) ||
- (f == OSystem::kFeatureCursorPalette);
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ case OSystem::kFeatureCursorPalette:
+ return true;
+
+ case OSystem::kFeatureOverlaySupportsAlpha:
+ return _defaultFormatAlpha.aBits() > 3;
+
+ default:
+ return false;
+ }
}
void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- setFullscreenMode(enable);
- break;
-
case OSystem::kFeatureAspectRatioCorrection:
- _videoMode.aspectRatioCorrection = enable;
- _transactionDetails.needRefresh = true;
+ assert(_transactionMode != kTransactionNone);
+ _currentState.aspectRatioCorrection = enable;
break;
case OSystem::kFeatureCursorPalette:
- _cursorPaletteDisabled = !enable;
- _cursorNeedsRedraw = true;
+ _cursorPaletteEnabled = enable;
+ updateCursorPalette();
break;
default:
@@ -113,1191 +101,1013 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- return _videoMode.fullscreen;
-
case OSystem::kFeatureAspectRatioCorrection:
- return _videoMode.aspectRatioCorrection;
+ return _currentState.aspectRatioCorrection;
case OSystem::kFeatureCursorPalette:
- return !_cursorPaletteDisabled;
+ return _cursorPaletteEnabled;
default:
return false;
}
}
-//
-// Screen format and modes
-//
+namespace {
-static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL},
- {"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE},
- {"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL},
- {0, 0, 0}
+const OSystem::GraphicsMode glGraphicsModes[] = {
+ { "opengl_linear", _s("OpenGL"), GFX_LINEAR },
+ { "opengl_nearest", _s("OpenGL (No filtering)"), GFX_NEAREST },
+ { nullptr, nullptr, 0 }
};
-const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() {
- return s_supportedGraphicsModes;
-}
+} // End of anonymous namespace
const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const {
- return s_supportedGraphicsModes;
+ return glGraphicsModes;
}
int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
- return OpenGL::GFX_NORMAL;
+ return GFX_LINEAR;
}
bool OpenGLGraphicsManager::setGraphicsMode(int mode) {
- assert(_transactionMode == kTransactionActive);
+ assert(_transactionMode != kTransactionNone);
+
+ switch (mode) {
+ case GFX_LINEAR:
+ case GFX_NEAREST:
+ _currentState.graphicsMode = mode;
+
+ if (_gameScreen) {
+ _gameScreen->enableLinearFiltering(mode == GFX_LINEAR);
+ }
- setScale(2);
+ if (_cursor) {
+ _cursor->enableLinearFiltering(mode == GFX_LINEAR);
+ }
- if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
return true;
- switch (mode) {
- case OpenGL::GFX_NORMAL:
- case OpenGL::GFX_CONSERVE:
- case OpenGL::GFX_ORIGINAL:
- break;
default:
- warning("Unknown gfx mode %d", mode);
+ warning("OpenGLGraphicsManager::setGraphicsMode(%d): Unknown graphics mode", mode);
return false;
}
-
- _videoMode.mode = mode;
- _transactionDetails.needRefresh = true;
-
- return true;
}
int OpenGLGraphicsManager::getGraphicsMode() const {
- assert(_transactionMode == kTransactionNone);
- return _videoMode.mode;
-}
-
-void OpenGLGraphicsManager::resetGraphicsScale() {
- setScale(1);
+ return _currentState.graphicsMode;
}
#ifdef USE_RGB_COLOR
Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const {
- return _screenFormat;
+ return _currentState.gameFormat;
}
#endif
-void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
- assert(_transactionMode == kTransactionActive);
-
-#ifdef USE_RGB_COLOR
- Graphics::PixelFormat newFormat;
- if (!format)
- newFormat = Graphics::PixelFormat::createFormatCLUT8();
- else
- newFormat = *format;
-
- assert(newFormat.bytesPerPixel > 0);
-
- // Avoid redundant format changes
- if (newFormat != _videoMode.format) {
- _videoMode.format = newFormat;
- _transactionDetails.formatChanged = true;
- _screenFormat = newFormat;
- }
-#endif
-
- // Avoid redundant res changes
- if ((int)width == _videoMode.screenWidth && (int)height == _videoMode.screenHeight)
- return;
-
- _videoMode.screenWidth = width;
- _videoMode.screenHeight = height;
-
- _transactionDetails.sizeChanged = true;
-}
-
-int OpenGLGraphicsManager::getScreenChangeID() const {
- return _screenChangeCount;
-}
-
-//
-// GFX
-//
-
void OpenGLGraphicsManager::beginGFXTransaction() {
assert(_transactionMode == kTransactionNone);
+ // Start a transaction.
+ _oldState = _currentState;
_transactionMode = kTransactionActive;
- _transactionDetails.sizeChanged = false;
- _transactionDetails.needRefresh = false;
- _transactionDetails.needUpdatescreen = false;
- _transactionDetails.filterChanged = false;
-#ifdef USE_RGB_COLOR
- _transactionDetails.formatChanged = false;
-#endif
-
- _oldVideoMode = _videoMode;
}
OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
- int errors = OSystem::kTransactionSuccess;
+ assert(_transactionMode == kTransactionActive);
- assert(_transactionMode != kTransactionNone);
+ uint transactionError = OSystem::kTransactionSuccess;
+
+ bool setupNewGameScreen = false;
+ if ( _oldState.gameWidth != _currentState.gameWidth
+ || _oldState.gameHeight != _currentState.gameHeight) {
+ setupNewGameScreen = true;
+ }
- if (_transactionMode == kTransactionRollback) {
- if (_videoMode.fullscreen != _oldVideoMode.fullscreen) {
- errors |= OSystem::kTransactionFullscreenFailed;
+#ifdef USE_RGB_COLOR
+ if (_oldState.gameFormat != _currentState.gameFormat) {
+ setupNewGameScreen = true;
+ }
+
+ // Check whether the requested format can actually be used.
+ Common::List<Graphics::PixelFormat> supportedFormats = getSupportedFormats();
+ // In case the requested format is not usable we will fall back to CLUT8.
+ if (Common::find(supportedFormats.begin(), supportedFormats.end(), _currentState.gameFormat) == supportedFormats.end()) {
+ _currentState.gameFormat = Graphics::PixelFormat::createFormatCLUT8();
+ transactionError |= OSystem::kTransactionFormatNotSupported;
+ }
+#endif
- _videoMode.fullscreen = _oldVideoMode.fullscreen;
- } else if (_videoMode.mode != _oldVideoMode.mode) {
- errors |= OSystem::kTransactionModeSwitchFailed;
+ do {
+ uint requestedWidth = _currentState.gameWidth;
+ uint requestedHeight = _currentState.gameHeight;
+ const uint desiredAspect = getDesiredGameScreenAspect();
+ requestedHeight = intToFrac(requestedWidth) / desiredAspect;
- _videoMode.mode = _oldVideoMode.mode;
- _videoMode.scaleFactor = _oldVideoMode.scaleFactor;
+ if (!loadVideoMode(requestedWidth, requestedHeight,
#ifdef USE_RGB_COLOR
- } else if (_videoMode.format != _oldVideoMode.format) {
- errors |= OSystem::kTransactionFormatNotSupported;
+ _currentState.gameFormat
+#else
+ Graphics::PixelFormat::createFormatCLUT8()
+#endif
+ )
+ // HACK: This is really nasty but we don't have any guarantees of
+ // a context existing before, which means we don't know the maximum
+ // supported texture size before this. Thus, we check whether the
+ // requested game resolution is supported over here.
+ || ( _currentState.gameWidth > (uint)Texture::getMaximumTextureSize()
+ || _currentState.gameHeight > (uint)Texture::getMaximumTextureSize())) {
+ if (_transactionMode == kTransactionActive) {
+ // Try to setup the old state in case its valid and is
+ // actually different from the new one.
+ if (_oldState.valid && _oldState != _currentState) {
+ // Give some hints on what failed to set up.
+ if ( _oldState.gameWidth != _currentState.gameWidth
+ || _oldState.gameHeight != _currentState.gameHeight) {
+ transactionError |= OSystem::kTransactionSizeChangeFailed;
+ }
- _videoMode.format = _oldVideoMode.format;
- _screenFormat = _videoMode.format;
+#ifdef USE_RGB_COLOR
+ if (_oldState.gameFormat != _currentState.gameFormat) {
+ transactionError |= OSystem::kTransactionFormatNotSupported;
+ }
#endif
- } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) {
- errors |= OSystem::kTransactionSizeChangeFailed;
- _videoMode.screenWidth = _oldVideoMode.screenWidth;
- _videoMode.screenHeight = _oldVideoMode.screenHeight;
- _videoMode.overlayWidth = _oldVideoMode.overlayWidth;
- _videoMode.overlayHeight = _oldVideoMode.overlayHeight;
- }
+ if (_oldState.aspectRatioCorrection != _currentState.aspectRatioCorrection) {
+ transactionError |= OSystem::kTransactionAspectRatioFailed;
+ }
- if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&
- _videoMode.mode == _oldVideoMode.mode &&
- _videoMode.screenWidth == _oldVideoMode.screenWidth &&
- _videoMode.screenHeight == _oldVideoMode.screenHeight) {
+ if (_oldState.graphicsMode != _currentState.graphicsMode) {
+ transactionError |= OSystem::kTransactionModeSwitchFailed;
+ }
- _oldVideoMode.setup = false;
- }
- }
+ // Roll back to the old state.
+ _currentState = _oldState;
+ _transactionMode = kTransactionRollback;
- if (_transactionDetails.sizeChanged || _transactionDetails.needRefresh) {
- unloadGFXMode();
- if (!loadGFXMode()) {
- if (_oldVideoMode.setup) {
- _transactionMode = kTransactionRollback;
- errors |= endGFXTransaction();
+ // Try to set up the old state.
+ continue;
+ }
}
- } else {
- clearOverlay();
- _videoMode.setup = true;
- _screenChangeCount++;
+ // DON'T use error(), as this tries to bring up the debug
+ // console, which WON'T WORK now that we might no have a
+ // proper screen.
+ warning("OpenGLGraphicsManager::endGFXTransaction: Could not load any graphics mode!");
+ g_system->quit();
}
+
+ // In case we reach this we have a valid state, yay.
+ _transactionMode = kTransactionNone;
+ _currentState.valid = true;
+ } while (_transactionMode == kTransactionRollback);
+
+ if (setupNewGameScreen) {
+ delete _gameScreen;
+ _gameScreen = nullptr;
+
+ GLenum glIntFormat, glFormat, glType;
#ifdef USE_RGB_COLOR
- } else if (_transactionDetails.filterChanged || _transactionDetails.formatChanged) {
-#else
- } else if (_transactionDetails.filterChanged) {
+ if (_currentState.gameFormat.bytesPerPixel == 1) {
#endif
- loadTextures();
- internUpdateScreen();
- } else if (_transactionDetails.needUpdatescreen) {
- internUpdateScreen();
+ const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType);
+ assert(supported);
+ _gameScreen = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat);
+ _gameScreen->setPalette(0, 255, _gamePalette);
+#ifdef USE_RGB_COLOR
+ } else {
+ const bool supported = getGLPixelFormat(_currentState.gameFormat, glIntFormat, glFormat, glType);
+ assert(supported);
+ _gameScreen = new Texture(glIntFormat, glFormat, glType, _currentState.gameFormat);
+ }
+#endif
+
+ _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
+ _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR);
+ // We fill the screen to all black or index 0 for CLUT8.
+ if (_currentState.gameFormat.bytesPerPixel == 1) {
+ _gameScreen->fill(0);
+ } else {
+ _gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0));
+ }
}
- _transactionMode = kTransactionNone;
- return (OSystem::TransactionError)errors;
-}
+ // Update our display area and cursor scaling. This makes sure we pick up
+ // aspect ratio correction and game screen changes correctly.
+ recalculateDisplayArea();
+ recalculateCursorScaling();
-//
-// Screen
-//
+ // Something changed, so update the screen change ID.
+ ++_screenChangeID;
-int16 OpenGLGraphicsManager::getHeight() {
- return _videoMode.screenHeight;
+ // Since transactionError is a ORd list of TransactionErrors this is
+ // clearly wrong. But our API is simply broken.
+ return (OSystem::TransactionError)transactionError;
}
-int16 OpenGLGraphicsManager::getWidth() {
- return _videoMode.screenWidth;
+int OpenGLGraphicsManager::getScreenChangeID() const {
+ return _screenChangeID;
}
-void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
- assert(colors);
-
+void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
+ Graphics::PixelFormat requestedFormat;
#ifdef USE_RGB_COLOR
- assert(_screenFormat.bytesPerPixel == 1);
+ if (!format) {
+ requestedFormat = Graphics::PixelFormat::createFormatCLUT8();
+ } else {
+ requestedFormat = *format;
+ }
+ _currentState.gameFormat = requestedFormat;
#endif
- // Save the screen palette
- memcpy(_gamePalette + start * 3, colors, num * 3);
-
- _screenNeedsRedraw = true;
-
- if (_cursorPaletteDisabled)
- _cursorNeedsRedraw = true;
+ _currentState.gameWidth = width;
+ _currentState.gameHeight = height;
}
-void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
- assert(colors);
-
-#ifdef USE_RGB_COLOR
- assert(_screenFormat.bytesPerPixel == 1);
-#endif
+int16 OpenGLGraphicsManager::getWidth() {
+ return _currentState.gameWidth;
+}
- // Copies current palette to buffer
- memcpy(colors, _gamePalette + start * 3, num * 3);
+int16 OpenGLGraphicsManager::getHeight() {
+ return _currentState.gameHeight;
}
void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
- assert(x >= 0 && x < _screenData.w);
- assert(y >= 0 && y < _screenData.h);
- assert(h > 0 && y + h <= _screenData.h);
- assert(w > 0 && x + w <= _screenData.w);
-
- // Copy buffer data to game screen internal buffer
- const byte *src = (const byte *)buf;
- byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch + x * _screenData.format.bytesPerPixel;
- for (int i = 0; i < h; i++) {
- memcpy(dst, src, w * _screenData.format.bytesPerPixel);
- src += pitch;
- dst += _screenData.pitch;
- }
-
- // Extend dirty area if not full screen redraw is flagged
- if (!_screenNeedsRedraw) {
- const Common::Rect dirtyRect(x, y, x + w, y + h);
- _screenDirtyRect.extend(dirtyRect);
- }
+ _gameScreen->copyRectToTexture(x, y, w, h, buf, pitch);
}
-Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
- return &_screenData;
+void OpenGLGraphicsManager::fillScreen(uint32 col) {
+ // FIXME: This does not conform to the OSystem specs because fillScreen
+ // is always taking CLUT8 color values and use color indexed mode. This is,
+ // however, plain odd and probably was a forgotten when we introduced
+ // RGB support. Thus, we simply do the "sane" thing here and hope OSystem
+ // gets fixed one day.
+ _gameScreen->fill(col);
}
-void OpenGLGraphicsManager::unlockScreen() {
- _screenNeedsRedraw = true;
+void OpenGLGraphicsManager::setShakePos(int shakeOffset) {
+ _gameScreenShakeOffset = shakeOffset;
}
-void OpenGLGraphicsManager::fillScreen(uint32 col) {
- if (_gameTexture == NULL)
+void OpenGLGraphicsManager::updateScreen() {
+ if (!_gameScreen) {
return;
+ }
-#ifdef USE_RGB_COLOR
- if (_screenFormat.bytesPerPixel == 1) {
- memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
- } else if (_screenFormat.bytesPerPixel == 2) {
- uint16 *pixels = (uint16 *)_screenData.pixels;
- uint16 col16 = (uint16)col;
- for (int i = 0; i < _screenData.w * _screenData.h; i++) {
- pixels[i] = col16;
- }
- } else if (_screenFormat.bytesPerPixel == 3) {
- uint8 *pixels = (uint8 *)_screenData.pixels;
- byte r = (col >> 16) & 0xFF;
- byte g = (col >> 8) & 0xFF;
- byte b = col & 0xFF;
- for (int i = 0; i < _screenData.w * _screenData.h; i++) {
- pixels[0] = r;
- pixels[1] = g;
- pixels[2] = b;
- pixels += 3;
+ // Clear the screen buffer
+ GLCALL(glClear(GL_COLOR_BUFFER_BIT));
+
+ const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight();
+
+ // First step: Draw the (virtual) game screen.
+ glPushMatrix();
+
+ // Adjust game screen shake position
+ GLCALL(glTranslatef(0, shakeOffset, 0));
+
+ // Draw the game screen
+ _gameScreen->draw(_displayX, _displayY, _displayWidth, _displayHeight);
+
+ glPopMatrix();
+
+ // Second step: Draw the overlay if visible.
+ if (_overlayVisible) {
+ _overlay->draw(0, 0, _outputScreenWidth, _outputScreenHeight);
+ }
+
+ // Third step: Draw the cursor if visible.
+ if (_cursorVisible && _cursor) {
+ glPushMatrix();
+
+ // Adjust game screen shake position, but only when the overlay is not
+ // visible.
+ if (!_overlayVisible) {
+ GLCALL(glTranslatef(0, shakeOffset, 0));
}
- } else if (_screenFormat.bytesPerPixel == 4) {
- uint32 *pixels = (uint32 *)_screenData.pixels;
- for (int i = 0; i < _screenData.w * _screenData.h; i++) {
- pixels[i] = col;
+
+ _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled,
+ _cursorWidthScaled, _cursorHeightScaled);
+
+ glPopMatrix();
+ }
+
+#ifdef USE_OSD
+ // Fourth step: Draw the OSD.
+ if (_osdAlpha > 0) {
+ Common::StackLock lock(_osdMutex);
+
+ // Update alpha value.
+ const int diff = g_system->getMillis(false) - _osdFadeStartTime;
+ if (diff > 0) {
+ if (diff >= kOSDFadeOutDuration) {
+ // Back to full transparency.
+ _osdAlpha = 0;
+ } else {
+ // Do a fade out.
+ _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration;
+ }
}
+
+ // Set the OSD transparency.
+ GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f));
+
+ // Draw the OSD texture.
+ _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight);
+
+ // Reset color.
+ GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
}
-#else
- memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
#endif
- _screenNeedsRedraw = true;
}
-void OpenGLGraphicsManager::updateScreen() {
- assert(_transactionMode == kTransactionNone);
- internUpdateScreen();
+Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
+ return _gameScreen->getSurface();
}
-void OpenGLGraphicsManager::setShakePos(int shakeOffset) {
- assert(_transactionMode == kTransactionNone);
- _shakePos = shakeOffset;
+void OpenGLGraphicsManager::unlockScreen() {
+ _gameScreen->flagDirty();
}
-void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect &rect) {
+void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) {
}
void OpenGLGraphicsManager::clearFocusRectangle() {
}
-//
-// Overlay
-//
-
-void OpenGLGraphicsManager::showOverlay() {
- assert(_transactionMode == kTransactionNone);
+int16 OpenGLGraphicsManager::getOverlayWidth() {
+ if (_overlay) {
+ return _overlay->getWidth();
+ } else {
+ return 0;
+ }
+}
- if (_overlayVisible)
- return;
+int16 OpenGLGraphicsManager::getOverlayHeight() {
+ if (_overlay) {
+ return _overlay->getHeight();
+ } else {
+ return 0;
+ }
+}
+void OpenGLGraphicsManager::showOverlay() {
_overlayVisible = true;
-
- clearOverlay();
}
void OpenGLGraphicsManager::hideOverlay() {
- assert(_transactionMode == kTransactionNone);
-
- if (!_overlayVisible)
- return;
-
_overlayVisible = false;
-
- clearOverlay();
}
Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
- return _overlayFormat;
+ return _overlay->getFormat();
}
-void OpenGLGraphicsManager::clearOverlay() {
- // Set all pixels to 0
- memset(_overlayData.pixels, 0, _overlayData.h * _overlayData.pitch);
- _overlayNeedsRedraw = true;
+void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
+ _overlay->copyRectToTexture(x, y, w, h, buf, pitch);
}
-void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {
- const byte *src = (byte *)_overlayData.pixels;
- byte *dst = (byte *)buf;
- for (int i = 0; i < _overlayData.h; i++) {
- // Copy overlay data to buffer
- memcpy(dst, src, _overlayData.pitch);
- dst += pitch;
- src += _overlayData.pitch;
- }
+void OpenGLGraphicsManager::clearOverlay() {
+ _overlay->fill(0);
}
-void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
- assert(_transactionMode == kTransactionNone);
-
- if (_overlayTexture == NULL)
- return;
-
- const byte *src = (const byte *)buf;
-
- // Clip the coordinates
- if (x < 0) {
- w += x;
- src -= x * 2;
- x = 0;
- }
-
- if (y < 0) {
- h += y;
- src -= y * pitch;
- y = 0;
- }
-
- if (w > _overlayData.w - x)
- w = _overlayData.w - x;
-
- if (h > _overlayData.h - y)
- h = _overlayData.h - y;
-
- if (w <= 0 || h <= 0)
- return;
+void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {
+ const Graphics::Surface *overlayData = _overlay->getSurface();
- // Copy buffer data to internal overlay surface
- byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch;
- for (int i = 0; i < h; i++) {
- memcpy(dst + x * _overlayData.format.bytesPerPixel, src, w * _overlayData.format.bytesPerPixel);
- src += pitch;
- dst += _overlayData.pitch;
- }
+ const byte *src = (const byte *)overlayData->getPixels();
+ byte *dst = (byte *)buf;
- // Extend dirty area if not full screen redraw is flagged
- if (!_overlayNeedsRedraw) {
- const Common::Rect dirtyRect(x, y, x + w, y + h);
- _overlayDirtyRect.extend(dirtyRect);
+ for (uint h = overlayData->h; h > 0; --h) {
+ memcpy(dst, src, overlayData->w * overlayData->format.bytesPerPixel);
+ dst += pitch;
+ src += overlayData->pitch;
}
}
-int16 OpenGLGraphicsManager::getOverlayHeight() {
- return _videoMode.overlayHeight;
-}
-
-int16 OpenGLGraphicsManager::getOverlayWidth() {
- return _videoMode.overlayWidth;
-}
-
-//
-// Cursor
-//
-
bool OpenGLGraphicsManager::showMouse(bool visible) {
- if (_cursorVisible == visible)
- return visible;
-
bool last = _cursorVisible;
_cursorVisible = visible;
-
return last;
}
void OpenGLGraphicsManager::warpMouse(int x, int y) {
- int scaledX = x;
- int scaledY = y;
-
- int16 currentX = _cursorState.x;
- int16 currentY = _cursorState.y;
-
+ int16 currentX = _cursorX;
+ int16 currentY = _cursorY;
adjustMousePosition(currentX, currentY);
- // Do not adjust the real screen position, when the current game / overlay
- // coordinates match the requested coordinates. This avoids a slight
- // movement which might occur otherwise when the mouse is at a subpixel
- // position.
- if (x == currentX && y == currentY)
+ // Check whether the (virtual) coordinate actually changed. If not, then
+ // simply do nothing. This avoids ugly "jittering" due to the actual
+ // output screen having a bigger resolution than the virtual coordinates.
+ if (currentX == x && currentY == y) {
return;
+ }
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight;
-
- if (!_overlayVisible) {
- scaledX *= _videoMode.scaleFactor;
- scaledY *= _videoMode.scaleFactor;
+ // Scale the virtual coordinates into actual physical coordinates.
+ if (_overlayVisible) {
+ if (!_overlay) {
+ return;
}
+
+ // It might be confusing that we actually have to handle something
+ // here when the overlay is visible. This is because for very small
+ // resolutions we have a minimal overlay size and have to adjust
+ // for that.
+ x = (x * _outputScreenWidth) / _overlay->getWidth();
+ y = (y * _outputScreenHeight) / _overlay->getHeight();
} else {
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _displayWidth / _videoMode.overlayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _displayHeight / _videoMode.overlayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- scaledX = scaledX * _displayWidth / _videoMode.screenWidth;
- if (_displayHeight != _videoMode.screenHeight)
- scaledY = scaledY * _displayHeight / _videoMode.screenHeight;
+ if (!_gameScreen) {
+ return;
}
- scaledX += _displayX;
- scaledY += _displayY;
+ x = (x * _displayWidth) / _gameScreen->getWidth();
+ y = (y * _displayHeight) / _gameScreen->getHeight();
+
+ x += _displayX;
+ y += _displayY;
}
- setMousePosition(scaledX, scaledY);
- setInternalMousePosition(scaledX, scaledY);
+ setMousePosition(x, y);
+ setInternalMousePosition(x, y);
+}
+
+namespace {
+template<typename DstPixel, typename SrcPixel>
+void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) {
+ const uint srcAdd = srcPitch - w * sizeof(SrcPixel);
+ const uint dstAdd = dstPitch - w * sizeof(DstPixel);
+
+ while (h-- > 0) {
+ for (uint x = w; x > 0; --x, ++dst, ++src) {
+ if (*src == keyColor) {
+ *dst &= ~alphaMask;
+ }
+ }
+
+ dst = (DstPixel *)((byte *)dst + dstAdd);
+ src = (const SrcPixel *)((const byte *)src + srcAdd);
+ }
}
+} // End of anonymous namespace
void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
+ Graphics::PixelFormat inputFormat;
#ifdef USE_RGB_COLOR
- if (format)
- _cursorFormat = *format;
- else
- _cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
+ if (format) {
+ inputFormat = *format;
+ } else {
+ inputFormat = Graphics::PixelFormat::createFormatCLUT8();
+ }
#else
- assert(keycolor <= 255);
- _cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
+ inputFormat = Graphics::PixelFormat::createFormatCLUT8();
#endif
- // Allocate space for cursor data
- if (_cursorData.w != w || _cursorData.h != h ||
- _cursorData.format.bytesPerPixel != _cursorFormat.bytesPerPixel)
- _cursorData.create(w, h, _cursorFormat);
+ // In case the color format has changed we will need to create the texture.
+ if (!_cursor || _cursor->getFormat() != inputFormat) {
+ delete _cursor;
+ _cursor = nullptr;
- // Save cursor data
- memcpy(_cursorData.pixels, buf, h * _cursorData.pitch);
+ GLenum glIntFormat, glFormat, glType;
+
+ if (inputFormat.bytesPerPixel == 1) {
+ // In case this is not supported this is a serious programming
+ // error and the assert a bit below will trigger!
+ const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType);
+ assert(supported);
+ _cursor = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormatAlpha);
+ } else {
+ // Try to use the format specified as input directly. We can only
+ // do so when it actually has alpha bits.
+ if (inputFormat.aBits() != 0 && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType)) {
+ _cursor = new Texture(glIntFormat, glFormat, glType, inputFormat);
+ }
+
+ // Otherwise fall back to the default alpha format.
+ if (!_cursor) {
+ const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType);
+ assert(supported);
+ _cursor = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha);
+ }
+ }
+
+ assert(_cursor);
+ _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR);
+ }
- // Set cursor info
- _cursorState.w = w;
- _cursorState.h = h;
- _cursorState.hotX = hotspotX;
- _cursorState.hotY = hotspotY;
_cursorKeyColor = keycolor;
+ _cursorHotspotX = hotspotX;
+ _cursorHotspotY = hotspotY;
_cursorDontScale = dontScale;
- _cursorNeedsRedraw = true;
- refreshCursorScale();
+ _cursor->allocate(w, h);
+ if (inputFormat.bytesPerPixel == 1) {
+ // For CLUT8 cursors we can simply copy the input data into the
+ // texture.
+ _cursor->copyRectToTexture(0, 0, w, h, buf, w * inputFormat.bytesPerPixel);
+ } else {
+ // Otherwise it is a bit more ugly because we have to handle a key
+ // color properly.
+
+ Graphics::Surface *dst = _cursor->getSurface();
+ const uint srcPitch = w * inputFormat.bytesPerPixel;
+
+ // Copy the cursor data to the actual texture surface. This will make
+ // sure that the data is also converted to the expected format.
+ Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch,
+ w, h, dst->format, inputFormat);
+
+ // We apply the color key by setting the alpha bits of the pixels to
+ // fully transparent.
+ const uint32 aMask = (0xFF >> dst->format.aLoss) << dst->format.aShift;
+ if (dst->format.bytesPerPixel == 2) {
+ if (inputFormat.bytesPerPixel == 2) {
+ applyColorKey<uint16, uint16>((uint16 *)dst->getPixels(), (const uint16 *)buf, w, h,
+ dst->pitch, srcPitch, keycolor, aMask);
+ } else if (inputFormat.bytesPerPixel == 4) {
+ applyColorKey<uint16, uint32>((uint16 *)dst->getPixels(), (const uint32 *)buf, w, h,
+ dst->pitch, srcPitch, keycolor, aMask);
+ }
+ } else {
+ if (inputFormat.bytesPerPixel == 2) {
+ applyColorKey<uint32, uint16>((uint32 *)dst->getPixels(), (const uint16 *)buf, w, h,
+ dst->pitch, srcPitch, keycolor, aMask);
+ } else if (inputFormat.bytesPerPixel == 4) {
+ applyColorKey<uint32, uint32>((uint32 *)dst->getPixels(), (const uint32 *)buf, w, h,
+ dst->pitch, srcPitch, keycolor, aMask);
+ }
+ }
+
+ // Flag the texture as dirty.
+ _cursor->flagDirty();
+ }
+
+ // In case we actually use a palette set that up properly.
+ if (inputFormat.bytesPerPixel == 1) {
+ updateCursorPalette();
+ }
+
+ // Update the scaling.
+ recalculateCursorScaling();
}
void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) {
- assert(colors);
+ // FIXME: For some reason client code assumes that usage of this function
+ // automatically enables the cursor palette.
+ _cursorPaletteEnabled = true;
- // Save the cursor palette
memcpy(_cursorPalette + start * 3, colors, num * 3);
-
- _cursorPaletteDisabled = false;
- _cursorNeedsRedraw = true;
+ updateCursorPalette();
}
-//
-// Misc
-//
-
void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
- assert(_transactionMode == kTransactionNone);
- assert(msg);
-
#ifdef USE_OSD
- // Split the message into separate lines.
- _osdLines.clear();
+ // HACK: Actually no client code should use graphics functions from
+ // another thread. But the MT-32 emulator still does, thus we need to
+ // make sure this doesn't happen while a updateScreen call is done.
+ Common::StackLock lock(_osdMutex);
+ // Slip up the lines.
+ Common::Array<Common::String> osdLines;
Common::StringTokenizer tokenizer(msg, "\n");
- while (!tokenizer.empty())
- _osdLines.push_back(tokenizer.nextToken());
+ while (!tokenizer.empty()) {
+ osdLines.push_back(tokenizer.nextToken());
+ }
- // Request update of the texture
- _requireOSDUpdate = true;
+ // Do the actual drawing like the SDL backend.
+ const Graphics::Font *font = getFontOSD();
+ Graphics::Surface *dst = _osd->getSurface();
+ _osd->fill(0);
+ _osd->flagDirty();
- // Init the OSD display parameters, and the fade out
+ // Determine a rect which would contain the message string (clipped to the
+ // screen dimensions).
+ const int vOffset = 6;
+ const int lineSpacing = 1;
+ const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
+ int width = 0;
+ int height = lineHeight * osdLines.size() + 2 * vOffset;
+ for (uint i = 0; i < osdLines.size(); i++) {
+ width = MAX(width, font->getStringWidth(osdLines[i]) + 14);
+ }
+
+ // Clip the rect
+ width = MIN<int>(width, dst->w);
+ height = MIN<int>(height, dst->h);
+
+ int dstX = (dst->w - width) / 2;
+ int dstY = (dst->h - height) / 2;
+
+ // Draw a dark gray rect.
+ const uint32 color = dst->format.RGBToColor(40, 40, 40);
+ dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);
+
+ // Render the message, centered, and in white
+ const uint32 white = dst->format.RGBToColor(255, 255, 255);
+ for (uint i = 0; i < osdLines.size(); ++i) {
+ font->drawString(dst, osdLines[i],
+ dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
+ white, Graphics::kTextAlignCenter);
+ }
+
+ // Init the OSD display parameters.
_osdAlpha = kOSDInitialAlpha;
_osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay;
#endif
}
-//
-// Intern
-//
+void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
+ assert(_gameScreen->hasPalette());
-void OpenGLGraphicsManager::setFullscreenMode(bool enable) {
- assert(_transactionMode == kTransactionActive);
+ memcpy(_gamePalette + start * 3, colors, num * 3);
+ _gameScreen->setPalette(start, num, colors);
- if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
- return;
+ // We might need to update the cursor palette here.
+ updateCursorPalette();
+}
- if (_transactionMode == kTransactionActive) {
- _videoMode.fullscreen = enable;
- _transactionDetails.needRefresh = true;
- }
+void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
+ assert(_gameScreen->hasPalette());
+
+ memcpy(colors, _gamePalette + start * 3, num * 3);
}
-void OpenGLGraphicsManager::refreshGameScreen() {
- if (_screenNeedsRedraw)
- _screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h);
-
- int x = _screenDirtyRect.left;
- int y = _screenDirtyRect.top;
- int w = _screenDirtyRect.width();
- int h = _screenDirtyRect.height();
-
- if (_screenData.format.bytesPerPixel == 1) {
- // Create a temporary RGB888 surface
- byte *surface = new byte[w * h * 3];
-
- // Convert the paletted buffer to RGB888
- const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch;
- src += x * _screenData.format.bytesPerPixel;
- byte *dst = surface;
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 3];
- dst[1] = _gamePalette[src[j] * 3 + 1];
- dst[2] = _gamePalette[src[j] * 3 + 2];
- dst += 3;
- }
- src += _screenData.pitch;
+void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
+ _outputScreenWidth = width;
+ _outputScreenHeight = height;
+
+ // Setup coordinates system.
+ GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight));
+
+ GLCALL(glMatrixMode(GL_PROJECTION));
+ GLCALL(glLoadIdentity());
+#ifdef USE_GLES
+ GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1));
+#else
+ GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1));
+#endif
+ GLCALL(glMatrixMode(GL_MODELVIEW));
+ GLCALL(glLoadIdentity());
+
+ uint overlayWidth = width;
+ uint overlayHeight = height;
+
+ // WORKAROUND: We can only support surfaces up to the maximum supported
+ // texture size. Thus, in case we encounter a physical size bigger than
+ // this maximum texture size we will simply use an overlay as big as
+ // possible and then scale it to the physical display size. This sounds
+ // bad but actually all recent chips should support full HD resolution
+ // anyway. Thus, it should not be a real issue for modern hardware.
+ if ( overlayWidth > (uint)Texture::getMaximumTextureSize()
+ || overlayHeight > (uint)Texture::getMaximumTextureSize()) {
+ const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
+
+ if (outputAspect > (frac_t)FRAC_ONE) {
+ overlayWidth = Texture::getMaximumTextureSize();
+ overlayHeight = intToFrac(overlayWidth) / outputAspect;
+ } else {
+ overlayHeight = Texture::getMaximumTextureSize();
+ overlayWidth = fracToInt(overlayHeight * outputAspect);
}
+ }
- // Update the texture
- _gameTexture->updateBuffer(surface, w * 3, x, y, w, h);
+ // HACK: We limit the minimal overlay size to 256x200, which is the
+ // minimum of the dimensions of the two resolutions 256x240 (NES) and
+ // 320x200 (many DOS games use this). This hopefully assure that our
+ // GUI has working layouts.
+ overlayWidth = MAX<uint>(overlayWidth, 256);
+ overlayHeight = MAX<uint>(overlayHeight, 200);
+
+ if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) {
+ delete _overlay;
+ _overlay = nullptr;
+
+ GLenum glIntFormat, glFormat, glType;
+ const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType);
+ assert(supported);
+ _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha);
+ // We always filter the overlay with GL_LINEAR. This assures it's
+ // readable in case it needs to be scaled and does not affect it
+ // otherwise.
+ _overlay->enableLinearFiltering(true);
+ }
+ _overlay->allocate(overlayWidth, overlayHeight);
+ _overlay->fill(0);
- // Free the temp surface
- delete[] surface;
- } else {
- // Update the texture
- _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch +
- x * _screenData.format.bytesPerPixel, _screenData.pitch, x, y, w, h);
+#ifdef USE_OSD
+ if (!_osd || _osd->getFormat() != _defaultFormatAlpha) {
+ delete _osd;
+ _osd = nullptr;
+
+ GLenum glIntFormat, glFormat, glType;
+ const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType);
+ assert(supported);
+ _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha);
+ // We always filter the osd with GL_LINEAR. This assures it's
+ // readable in case it needs to be scaled and does not affect it
+ // otherwise.
+ _osd->enableLinearFiltering(true);
}
+ _osd->allocate(_overlay->getWidth(), _overlay->getHeight());
+ _osd->fill(0);
+#endif
- _screenNeedsRedraw = false;
- _screenDirtyRect = Common::Rect();
+ // Re-setup the scaling for the screen and cursor
+ recalculateDisplayArea();
+ recalculateCursorScaling();
+
+ // Something changed, so update the screen change ID.
+ ++_screenChangeID;
}
-void OpenGLGraphicsManager::refreshOverlay() {
- if (_overlayNeedsRedraw)
- _overlayDirtyRect = Common::Rect(0, 0, _overlayData.w, _overlayData.h);
-
- int x = _overlayDirtyRect.left;
- int y = _overlayDirtyRect.top;
- int w = _overlayDirtyRect.width();
- int h = _overlayDirtyRect.height();
-
- if (_overlayData.format.bytesPerPixel == 1) {
- // Create a temporary RGB888 surface
- byte *surface = new byte[w * h * 3];
-
- // Convert the paletted buffer to RGB888
- const byte *src = (byte *)_overlayData.pixels + y * _overlayData.pitch;
- src += x * _overlayData.format.bytesPerPixel;
- byte *dst = surface;
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 3];
- dst[1] = _gamePalette[src[j] * 3 + 1];
- dst[2] = _gamePalette[src[j] * 3 + 2];
- dst += 3;
- }
- src += _screenData.pitch;
- }
+void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) {
+ // Initialize all extensions.
+ initializeGLExtensions();
- // Update the texture
- _overlayTexture->updateBuffer(surface, w * 3, x, y, w, h);
+ // Disable 3D properties.
+ GLCALL(glDisable(GL_CULL_FACE));
+ GLCALL(glDisable(GL_DEPTH_TEST));
+ GLCALL(glDisable(GL_LIGHTING));
+ GLCALL(glDisable(GL_FOG));
+ GLCALL(glDisable(GL_DITHER));
+ GLCALL(glShadeModel(GL_FLAT));
+ GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
- // Free the temp surface
- delete[] surface;
- } else {
- // Update the texture
- _overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch +
- x * _overlayData.format.bytesPerPixel, _overlayData.pitch, x, y, w, h);
- }
+ // Default to black as clear color.
+ GLCALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
+ GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
- _overlayNeedsRedraw = false;
- _overlayDirtyRect = Common::Rect();
-}
+ // Setup alpha blend (for overlay and cursor).
+ GLCALL(glEnable(GL_BLEND));
+ GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-void OpenGLGraphicsManager::refreshCursor() {
- _cursorNeedsRedraw = false;
-
- // Allocate a texture big enough for cursor
- _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
-
- // Create a temporary RGBA8888 surface
- byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
- memset(surface, 0, _cursorState.w * _cursorState.h * 4);
-
- byte *dst = surface;
-
- // Convert the paletted cursor to RGBA8888
- if (_cursorFormat.bytesPerPixel == 1) {
- // Select palette
- byte *palette;
- if (_cursorPaletteDisabled)
- palette = _gamePalette;
- else
- palette = _cursorPalette;
-
- // Convert the paletted cursor to RGBA8888
- const byte *src = (byte *)_cursorData.pixels;
- for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
- // Check for keycolor
- if (src[i] != _cursorKeyColor) {
- dst[0] = palette[src[i] * 3];
- dst[1] = palette[src[i] * 3 + 1];
- dst[2] = palette[src[i] * 3 + 2];
- dst[3] = 255;
- }
- dst += 4;
- }
- } else {
- const bool gotNoAlpha = (_cursorFormat.aLoss == 8);
-
- // Convert the RGB cursor to RGBA8888
- if (_cursorFormat.bytesPerPixel == 2) {
- const uint16 *src = (uint16 *)_cursorData.pixels;
- for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
- // Check for keycolor
- if (src[i] != _cursorKeyColor) {
- _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
-
- if (gotNoAlpha)
- dst[3] = 255;
- }
- dst += 4;
- }
- } else if (_cursorFormat.bytesPerPixel == 4) {
- const uint32 *src = (uint32 *)_cursorData.pixels;
- for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
- // Check for keycolor
- if (src[i] != _cursorKeyColor) {
- _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
-
- if (gotNoAlpha)
- dst[3] = 255;
- }
- dst += 4;
- }
- }
- }
+ // Enable rendering with vertex and coord arrays.
+ GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
+ GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
- // Update the texture with new cursor
- _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h);
+ GLCALL(glEnable(GL_TEXTURE_2D));
- // Free the temp surface
- delete[] surface;
-}
+ // We use a "pack" alignment (when reading from textures) to 4 here,
+ // since the only place where we really use it is the BMP screenshot
+ // code and that requires the same alignment too.
+ GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
-void OpenGLGraphicsManager::refreshCursorScale() {
- // Calculate the scale factors of the screen.
- // We also totally ignore the aspect of the overlay cursor, since aspect
- // ratio correction only applies to the game screen.
- // TODO: It might make sense to always ignore scaling of the mouse cursor
- // when the overlay is visible.
- uint screenScaleFactorX = _videoMode.hardwareWidth * 10000 / _videoMode.screenWidth;
- uint screenScaleFactorY = _videoMode.hardwareHeight * 10000 / _videoMode.screenHeight;
-
- // Ignore scaling when the cursor should not be scaled.
- if (_cursorDontScale) {
- screenScaleFactorX = 10000;
- screenScaleFactorY = 10000;
- }
+ // Query information needed by textures.
+ Texture::queryTextureInformation();
- // Apply them (without any possible) aspect ratio correction to the
- // overlay.
- _cursorState.rW = (int16)(_cursorState.w * screenScaleFactorX / 10000);
- _cursorState.rH = (int16)(_cursorState.h * screenScaleFactorY / 10000);
- _cursorState.rHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000);
- _cursorState.rHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000);
-
- // Only apply scaling when it's desired.
- if (_cursorDontScale) {
- screenScaleFactorX = 10000;
- screenScaleFactorY = 10000;
- } else {
- // Make sure we properly scale the cursor according to the desired aspect.
- int width, height;
- calculateDisplaySize(width, height);
- screenScaleFactorX = (width * 10000 / _videoMode.screenWidth);
- screenScaleFactorY = (height * 10000 / _videoMode.screenHeight);
+ // Refresh the output screen dimensions if some are set up.
+ if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
+ setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
}
- // Apply the scale cursor scaling for the game screen.
- _cursorState.vW = (int16)(_cursorState.w * screenScaleFactorX / 10000);
- _cursorState.vH = (int16)(_cursorState.h * screenScaleFactorY / 10000);
- _cursorState.vHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000);
- _cursorState.vHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000);
-}
+ // TODO: Should we try to convert textures into one of those formats if
+ // possible? For example, when _gameScreen is CLUT8 we might want to use
+ // defaultFormat now.
+ _defaultFormat = defaultFormat;
+ _defaultFormatAlpha = defaultFormatAlpha;
-void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) {
- if (_videoMode.mode == OpenGL::GFX_ORIGINAL) {
- width = _videoMode.screenWidth;
- height = _videoMode.screenHeight;
- } else {
- width = _videoMode.hardwareWidth;
- height = _videoMode.hardwareHeight;
+ if (_gameScreen) {
+ _gameScreen->recreateInternalTexture();
+ }
+
+ if (_overlay) {
+ _overlay->recreateInternalTexture();
+ }
- uint aspectRatio = (_videoMode.hardwareWidth * 10000 + 5000) / _videoMode.hardwareHeight;
- uint desiredAspectRatio = getAspectRatio();
+ if (_cursor) {
+ _cursor->recreateInternalTexture();
+ }
- // Adjust one screen dimension for mantaining the aspect ratio
- if (aspectRatio < desiredAspectRatio)
- height = (width * 10000 + 5000) / desiredAspectRatio;
- else if (aspectRatio > desiredAspectRatio)
- width = (height * desiredAspectRatio + 5000) / 10000;
+#ifdef USE_OSD
+ if (_osd) {
+ _osd->recreateInternalTexture();
}
+#endif
}
-void OpenGLGraphicsManager::refreshDisplaySize() {
- calculateDisplaySize(_displayWidth, _displayHeight);
+void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
+ if (_overlayVisible) {
+ // It might be confusing that we actually have to handle something
+ // here when the overlay is visible. This is because for very small
+ // resolutions we have a minimal overlay size and have to adjust
+ // for that.
+ // This can also happen when the overlay is smaller than the actual
+ // display size because of texture size limitations.
+ if (_overlay) {
+ x = (x * _overlay->getWidth()) / _outputScreenWidth;
+ y = (y * _overlay->getHeight()) / _outputScreenHeight;
+ }
+ } else if (_gameScreen) {
+ x -= _displayX;
+ y -= _displayY;
+
+ const int16 width = _gameScreen->getWidth();
+ const int16 height = _gameScreen->getHeight();
+
+ x = (x * width) / _displayWidth;
+ y = (y * height) / _displayHeight;
- // Adjust x and y for centering the screen
- _displayX = (_videoMode.hardwareWidth - _displayWidth) / 2;
- _displayY = (_videoMode.hardwareHeight - _displayHeight) / 2;
+ // Make sure we only supply valid coordinates.
+ x = CLIP<int16>(x, 0, width - 1);
+ y = CLIP<int16>(y, 0, height - 1);
+ }
}
-void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &gltype) {
+bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const {
if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
- bpp = 4;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_RGBA;
- gltype = GL_UNSIGNED_INT_8_8_8_8;
- } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) { // RGB888
- bpp = 3;
- intFormat = GL_RGB;
- glFormat = GL_RGB;
- gltype = GL_UNSIGNED_BYTE;
+ glType = GL_UNSIGNED_INT_8_8_8_8;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565
- bpp = 2;
- intFormat = GL_RGB;
+ glIntFormat = GL_RGB;
glFormat = GL_RGB;
- gltype = GL_UNSIGNED_SHORT_5_6_5;
- } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGB5551
- bpp = 2;
- intFormat = GL_RGBA;
+ glType = GL_UNSIGNED_SHORT_5_6_5;
+ return true;
+ } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551
+ glIntFormat = GL_RGBA;
glFormat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_5_5_5_1;
+ glType = GL_UNSIGNED_SHORT_5_5_5_1;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444
- bpp = 2;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4;
- } else if (pixelFormat.bytesPerPixel == 1) { // CLUT8
- // If uses a palette, create texture as RGB888. The pixel data will be converted
- // later.
- bpp = 3;
- intFormat = GL_RGB;
- glFormat = GL_RGB;
- gltype = GL_UNSIGNED_BYTE;
+ glType = GL_UNSIGNED_SHORT_4_4_4_4;
+ return true;
#ifndef USE_GLES
} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555
// GL_BGRA does not exist in every GLES implementation so should not be configured if
// USE_GLES is set.
- bpp = 2;
- intFormat = GL_RGB;
+ glIntFormat = GL_RGB;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ glType = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888
- bpp = 4;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
+ glType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444
- bpp = 2;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
- bpp = 4;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_RGBA;
- gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
+ glType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888
- bpp = 4;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_BYTE;
- } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0)) { // BGR888
- bpp = 3;
- intFormat = GL_RGB;
- glFormat = GL_BGR;
- gltype = GL_UNSIGNED_BYTE;
+ glType = GL_UNSIGNED_INT_8_8_8_8;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565
- bpp = 2;
- intFormat = GL_RGB;
+ glIntFormat = GL_RGB;
glFormat = GL_BGR;
- gltype = GL_UNSIGNED_SHORT_5_6_5;
+ glType = GL_UNSIGNED_SHORT_5_6_5;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551
- bpp = 2;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_SHORT_5_5_5_1;
+ glType = GL_UNSIGNED_SHORT_5_5_5_1;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444
- bpp = 2;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ return true;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444
- bpp = 2;
- intFormat = GL_RGBA;
+ glIntFormat = GL_RGBA;
glFormat = GL_BGRA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4;
+ glType = GL_UNSIGNED_SHORT_4_4_4_4;
+ return true;
#endif
} else {
- error("OpenGLGraphicsManager: Pixel format not supported");
+ return false;
}
}
-void OpenGLGraphicsManager::internUpdateScreen() {
- // Clear the screen buffer
- glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR();
-
- if (_screenNeedsRedraw || !_screenDirtyRect.isEmpty())
- // Refresh texture if dirty
- refreshGameScreen();
-
- int scaleFactor = _videoMode.hardwareHeight / _videoMode.screenHeight;
-
- glPushMatrix();
-
- // Adjust game screen shake position
- glTranslatef(0, _shakePos * scaleFactor, 0); CHECK_GL_ERROR();
-
- // Draw the game screen
- _gameTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight);
-
- glPopMatrix();
-
- if (_overlayVisible) {
- if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty())
- // Refresh texture if dirty
- refreshOverlay();
-
- // Draw the overlay
- _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight);
- }
-
- if (_cursorVisible) {
- if (_cursorNeedsRedraw)
- // Refresh texture if dirty
- refreshCursor();
-
- glPushMatrix();
-
- // Adjust mouse shake position, unless the overlay is visible
- glTranslatef(0, _overlayVisible ? 0 : _shakePos * scaleFactor, 0); CHECK_GL_ERROR();
-
- // Draw the cursor
- if (_overlayVisible)
- _cursorTexture->drawTexture(_cursorState.x - _cursorState.rHotX,
- _cursorState.y - _cursorState.rHotY, _cursorState.rW, _cursorState.rH);
- else
- _cursorTexture->drawTexture(_cursorState.x - _cursorState.vHotX,
- _cursorState.y - _cursorState.vHotY, _cursorState.vW, _cursorState.vH);
-
- glPopMatrix();
- }
+frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const {
+ const uint width = _currentState.gameWidth;
+ const uint height = _currentState.gameHeight;
-#ifdef USE_OSD
- if (_osdAlpha > 0) {
- if (_requireOSDUpdate) {
- updateOSD();
- _requireOSDUpdate = false;
+ if (_currentState.aspectRatioCorrection) {
+ // In case we enable aspect ratio correction we force a 4/3 ratio.
+ // But just for 320x200 and 640x400 games, since other games do not need
+ // this.
+ if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
+ return intToFrac(4) / 3;
}
-
- // Update alpha value
- const int diff = g_system->getMillis() - _osdFadeStartTime;
- if (diff > 0) {
- if (diff >= kOSDFadeOutDuration) {
- // Back to full transparency
- _osdAlpha = 0;
- } else {
- // Do a fade out
- _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration;
- }
- }
- // Set the osd transparency
- glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); CHECK_GL_ERROR();
-
- // Draw the osd texture
- _osdTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
-
- // Reset color
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CHECK_GL_ERROR();
}
-#endif
-}
-
-void OpenGLGraphicsManager::initGL() {
- // Check available GL Extensions
- GLTexture::initGLExtensions();
-
- // Disable 3D properties
- glDisable(GL_CULL_FACE); CHECK_GL_ERROR();
- glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR();
- glDisable(GL_LIGHTING); CHECK_GL_ERROR();
- glDisable(GL_FOG); CHECK_GL_ERROR();
- glDisable(GL_DITHER); CHECK_GL_ERROR();
- glShadeModel(GL_FLAT); CHECK_GL_ERROR();
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); CHECK_GL_ERROR();
- // Setup alpha blend (For overlay and cursor)
- glEnable(GL_BLEND); CHECK_GL_ERROR();
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR();
-
- // Enable rendering with vertex and coord arrays
- glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR();
- glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR();
-
- glEnable(GL_TEXTURE_2D); CHECK_GL_ERROR();
-
- // Setup the GL viewport
- glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); CHECK_GL_ERROR();
-
- // Setup coordinates system
- glMatrixMode(GL_PROJECTION); CHECK_GL_ERROR();
- glLoadIdentity(); CHECK_GL_ERROR();
-#ifdef USE_GLES
- glOrthof(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR();
-#else
- glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR();
-#endif
- glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR();
- glLoadIdentity(); CHECK_GL_ERROR();
+ return intToFrac(width) / height;
}
-void OpenGLGraphicsManager::loadTextures() {
-#ifdef USE_RGB_COLOR
- if (_transactionDetails.formatChanged && _gameTexture) {
- delete _gameTexture;
- _gameTexture = 0;
+void OpenGLGraphicsManager::recalculateDisplayArea() {
+ if (!_gameScreen || _outputScreenHeight == 0) {
+ return;
}
-#endif
-
- if (!_gameTexture) {
- byte bpp;
- GLenum intformat;
- GLenum format;
- GLenum type;
-#ifdef USE_RGB_COLOR
- getGLPixelFormat(_screenFormat, bpp, intformat, format, type);
-#else
- getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type);
-#endif
- _gameTexture = new GLTexture(bpp, intformat, format, type);
- } else
- _gameTexture->refresh();
-
- _overlayFormat = Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
-
- if (!_overlayTexture) {
- byte bpp;
- GLenum intformat;
- GLenum format;
- GLenum type;
- getGLPixelFormat(_overlayFormat, bpp, intformat, format, type);
- _overlayTexture = new GLTexture(bpp, intformat, format, type);
- } else
- _overlayTexture->refresh();
-
- if (!_cursorTexture)
- _cursorTexture = new GLTexture(4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
- else
- _cursorTexture->refresh();
-
- GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST;
- _gameTexture->setFilter(filter);
- _overlayTexture->setFilter(filter);
- _cursorTexture->setFilter(filter);
-
- // Allocate texture memory and finish refreshing
- _gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight);
- _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
- _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
-
- if (
-#ifdef USE_RGB_COLOR
- _transactionDetails.formatChanged ||
-#endif
- _oldVideoMode.screenWidth != _videoMode.screenWidth ||
- _oldVideoMode.screenHeight != _videoMode.screenHeight)
- _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight,
-#ifdef USE_RGB_COLOR
- _screenFormat
-#else
- Graphics::PixelFormat::createFormatCLUT8()
-#endif
- );
-
-
- if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth ||
- _oldVideoMode.overlayHeight != _videoMode.overlayHeight)
- _overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight,
- _overlayFormat);
- _screenNeedsRedraw = true;
- _overlayNeedsRedraw = true;
- _cursorNeedsRedraw = true;
+ const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
+ const frac_t desiredAspect = getDesiredGameScreenAspect();
- // We need to setup a proper unpack alignment value here, else we will
- // get problems with the texture updates, in case the surface data is
- // not properly aligned.
- // It is noteworthy this assumes the OSD uses the same BPP as the overlay
- // and that the cursor works with any alignment setting.
- int newAlignment = Common::gcd(_gameTexture->getBytesPerPixel(), _overlayTexture->getBytesPerPixel());
- assert(newAlignment == 1 || newAlignment == 2 || newAlignment == 4);
- glPixelStorei(GL_UNPACK_ALIGNMENT, newAlignment);
+ _displayWidth = _outputScreenWidth;
+ _displayHeight = _outputScreenHeight;
- // We use a "pack" alignment (when reading from textures) to 4 here,
- // since the only place where we really use it is the BMP screenshot
- // code and that requires the same alignment too.
- glPixelStorei(GL_PACK_ALIGNMENT, 4);
-
-#ifdef USE_OSD
- if (!_osdTexture)
- _osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
- else
- _osdTexture->refresh();
-
- _osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
+ // Adjust one dimension for mantaining the aspect ratio.
+ if (outputAspect < desiredAspect) {
+ _displayHeight = intToFrac(_displayWidth) / desiredAspect;
+ } else if (outputAspect > desiredAspect) {
+ _displayWidth = fracToInt(_displayHeight * desiredAspect);
+ }
- // Update the OSD in case it is used right now
- _requireOSDUpdate = true;
-#endif
+ // We center the screen in the middle for now.
+ _displayX = (_outputScreenWidth - _displayWidth ) / 2;
+ _displayY = (_outputScreenHeight - _displayHeight) / 2;
}
-bool OpenGLGraphicsManager::loadGFXMode() {
- // Initialize OpenGL settings
- initGL();
-
- loadTextures();
-
- refreshCursorScale();
-
- refreshDisplaySize();
-
- internUpdateScreen();
-
- return true;
-}
+void OpenGLGraphicsManager::updateCursorPalette() {
+ if (!_cursor || !_cursor->hasPalette()) {
+ return;
+ }
-void OpenGLGraphicsManager::unloadGFXMode() {
+ if (_cursorPaletteEnabled) {
+ _cursor->setPalette(0, 256, _cursorPalette);
+ } else {
+ _cursor->setPalette(0, 256, _gamePalette);
+ }
+ // We remove all alpha bits from the palette entry of the color key.
+ // This makes sure its properly handled as color key.
+ const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat();
+ const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift;
+
+ if (hardwareFormat.bytesPerPixel == 2) {
+ uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor;
+ *palette &= ~aMask;
+ } else if (hardwareFormat.bytesPerPixel == 4) {
+ uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor;
+ *palette &= ~aMask;
+ } else {
+ warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel);
+ }
}
-void OpenGLGraphicsManager::setScale(int newScale) {
- assert(_transactionMode == kTransactionActive);
-
- if (newScale == _videoMode.scaleFactor)
+void OpenGLGraphicsManager::recalculateCursorScaling() {
+ if (!_cursor || !_gameScreen) {
return;
+ }
- _videoMode.scaleFactor = newScale;
- _transactionDetails.sizeChanged = true;
-}
+ // By default we use the unscaled versions.
+ _cursorHotspotXScaled = _cursorHotspotX;
+ _cursorHotspotYScaled = _cursorHotspotY;
+ _cursorWidthScaled = _cursor->getWidth();
+ _cursorHeightScaled = _cursor->getHeight();
-void OpenGLGraphicsManager::toggleAntialiasing() {
- assert(_transactionMode == kTransactionActive);
+ // In case scaling is actually enabled we will scale the cursor according
+ // to the game screen.
+ if (!_cursorDontScale) {
+ const uint screenScaleFactorX = _displayWidth * 10000 / _gameScreen->getWidth();
+ const uint screenScaleFactorY = _displayHeight * 10000 / _gameScreen->getHeight();
- _videoMode.antialiasing = !_videoMode.antialiasing;
- _transactionDetails.filterChanged = true;
-}
+ _cursorHotspotXScaled = (_cursorHotspotXScaled * screenScaleFactorX) / 10000;
+ _cursorWidthScaled = (_cursorWidthScaled * screenScaleFactorX) / 10000;
-uint OpenGLGraphicsManager::getAspectRatio() const {
- // In case we enable aspect ratio correction we force a 4/3 ratio.
- // But just for 320x200 and 640x400 games, since other games do not need
- // this.
- // TODO: This makes OpenGL Normal behave like OpenGL Conserve, when aspect
- // ratio correction is enabled, but it's better than the previous 4/3 mode
- // mess at least...
- if (_videoMode.aspectRatioCorrection
- && ((_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200)
- || (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400)))
- return 13333;
- else if (_videoMode.mode == OpenGL::GFX_NORMAL)
- return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight;
- else
- return _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
+ _cursorHotspotYScaled = (_cursorHotspotYScaled * screenScaleFactorY) / 10000;
+ _cursorHeightScaled = (_cursorHeightScaled * screenScaleFactorY) / 10000;
+ }
}
-void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
- if (_overlayVisible)
- return;
-
- x -= _displayX;
- y -= _displayY;
-
- if (_displayWidth != _videoMode.screenWidth)
- x = x * _videoMode.screenWidth / _displayWidth;
- if (_displayHeight != _videoMode.screenHeight)
- y = y * _videoMode.screenHeight / _displayHeight;
+#ifdef USE_OSD
+const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
+ return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
+#endif
-bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
- int width = _videoMode.hardwareWidth;
- int height = _videoMode.hardwareHeight;
+void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
+ const uint width = _outputScreenWidth;
+ const uint height = _outputScreenHeight;
// A line of a BMP image must have a size divisible by 4.
// We calculate the padding bytes needed here.
// Since we use a 3 byte per pixel mode, we can use width % 4 here, since
// it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
// usual way of computing the padding bytes required).
- const int linePaddingSize = width % 4;
- const int lineSize = width * 3 + linePaddingSize;
+ const uint linePaddingSize = width % 4;
+ const uint lineSize = width * 3 + linePaddingSize;
// Allocate memory for screenshot
uint8 *pixels = new uint8[lineSize * height];
// Get pixel data from OpenGL buffer
-#ifdef USE_GLES
- glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR();
-#else
- if (_formatBGR) {
- glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR();
- } else {
- glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR();
+ GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels));
+
+ // BMP stores as BGR. Since we can't assume that GL_BGR is supported we
+ // will swap the components from the RGB we read to BGR on our own.
+ for (uint y = height; y-- > 0;) {
+ uint8 *line = pixels + y * lineSize;
+
+ for (uint x = width; x > 0; --x, line += 3) {
+ SWAP(line[0], line[2]);
+ }
}
-#endif
// Open file
Common::DumpFile out;
@@ -1326,73 +1136,6 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
// Free allocated memory
delete[] pixels;
-
- return true;
-}
-
-const char *OpenGLGraphicsManager::getCurrentModeName() {
- const char *modeName = 0;
- const OSystem::GraphicsMode *g = getSupportedGraphicsModes();
- while (g->name) {
- if (g->id == _videoMode.mode) {
- modeName = g->description;
- break;
- }
- g++;
- }
- return modeName;
-}
-
-#ifdef USE_OSD
-const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
- return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
-}
-
-void OpenGLGraphicsManager::updateOSD() {
- // The font we are going to use:
- const Graphics::Font *font = getFontOSD();
-
- if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
- _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), _overlayFormat);
- else
- // Clear everything
- memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
-
- // Determine a rect which would contain the message string (clipped to the
- // screen dimensions).
- const int vOffset = 6;
- const int lineSpacing = 1;
- const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
- int width = 0;
- int height = lineHeight * _osdLines.size() + 2 * vOffset;
- for (uint i = 0; i < _osdLines.size(); i++) {
- width = MAX(width, font->getStringWidth(_osdLines[i]) + 14);
- }
-
- // Clip the rect
- if (width > _osdSurface.w)
- width = _osdSurface.w;
- if (height > _osdSurface.h)
- height = _osdSurface.h;
-
- int dstX = (_osdSurface.w - width) / 2;
- int dstY = (_osdSurface.h - height) / 2;
-
- // Draw a dark gray rect (R = 40, G = 40, B = 40)
- const uint16 color = 0x294B;
- _osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);
-
- // Render the message, centered, and in white
- for (uint i = 0; i < _osdLines.size(); i++) {
- font->drawString(&_osdSurface, _osdLines[i],
- dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
- 0xFFFF, Graphics::kTextAlignCenter);
- }
-
- // Update the texture
- _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
- _osdSurface.w, _osdSurface.h);
}
-#endif
-#endif
+} // End of namespace OpenGL
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 9d8d418d11..d2d0358407 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -8,338 +8,464 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public 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_GRAPHICS_OPENGL_H
-#define BACKENDS_GRAPHICS_OPENGL_H
+#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
+#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
-#include "backends/graphics/opengl/gltexture.h"
+#include "backends/graphics/opengl/opengl-sys.h"
#include "backends/graphics/graphics.h"
-#include "common/array.h"
-#include "common/rect.h"
-#include "graphics/font.h"
-#include "graphics/pixelformat.h"
-// Uncomment this to enable the 'on screen display' code.
-#define USE_OSD 1
+#include "common/frac.h"
+#include "common/mutex.h"
+
+namespace Graphics {
+class Font;
+} // End of namespace Graphics
namespace OpenGL {
-// The OpenGL GFX modes. They have to be inside the OpenGL namespace so they
-// do not clash with the SDL GFX modes.
+
+// HACK: We use glColor in the OSD code. This might not be working on GL ES but
+// we still enable it because Tizen already shipped with it. Also, the
+// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp.
+#define USE_OSD 1
+
+class Texture;
+
enum {
- GFX_NORMAL = 0,
- GFX_CONSERVE = 1,
- GFX_ORIGINAL = 2
+ GFX_LINEAR = 0,
+ GFX_NEAREST = 1
};
-}
-
-/**
- * OpenGL graphics manager. This is an abstract class, it does not do the
- * window and OpenGL context initialization.
- * Derived classes should at least override internUpdateScreen for doing
- * the buffers swap, and implement loadGFXMode for handling the window/context if
- * needed. If USE_RGB_COLOR is enabled, getSupportedFormats must be implemented.
- */
class OpenGLGraphicsManager : public GraphicsManager {
public:
OpenGLGraphicsManager();
virtual ~OpenGLGraphicsManager();
+ // GraphicsManager API
virtual bool hasFeature(OSystem::Feature f);
virtual void setFeatureState(OSystem::Feature f, bool enable);
virtual bool getFeatureState(OSystem::Feature f);
- static const OSystem::GraphicsMode *supportedGraphicsModes();
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
virtual int getDefaultGraphicsMode() const;
virtual bool setGraphicsMode(int mode);
virtual int getGraphicsMode() const;
- virtual void resetGraphicsScale();
+
+ virtual void resetGraphicsScale() {}
+
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const;
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;
#endif
- virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL);
- virtual int getScreenChangeID() const;
virtual void beginGFXTransaction();
virtual OSystem::TransactionError endGFXTransaction();
- virtual int16 getHeight();
+ virtual int getScreenChangeID() const;
+
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format);
+
virtual int16 getWidth();
-protected:
- // PaletteManager API
- virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(byte *colors, uint start, uint num);
+ virtual int16 getHeight();
-public:
virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
virtual void fillScreen(uint32 col);
- virtual void updateScreen();
+
virtual void setShakePos(int shakeOffset);
- virtual void setFocusRectangle(const Common::Rect &rect);
+
+ virtual void updateScreen();
+
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
+
+ virtual void setFocusRectangle(const Common::Rect& rect);
virtual void clearFocusRectangle();
+ virtual int16 getOverlayWidth();
+ virtual int16 getOverlayHeight();
+
virtual void showOverlay();
virtual void hideOverlay();
+
virtual Graphics::PixelFormat getOverlayFormat() const;
+
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
virtual void clearOverlay();
virtual void grabOverlay(void *buf, int pitch);
- virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
- virtual int16 getOverlayHeight();
- virtual int16 getOverlayWidth();
virtual bool showMouse(bool visible);
virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format);
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual void displayMessageOnOSD(const char *msg);
+
+ // PaletteManager interface
+ virtual void setPalette(const byte *colors, uint start, uint num);
+ virtual void grabPalette(byte *colors, uint start, uint num);
+
protected:
/**
- * Setup OpenGL settings
+ * Set up the actual screen size available for the OpenGL code to do any
+ * drawing.
+ *
+ * @param width The width of the screen.
+ * @param height The height of the screen.
+ */
+ void setActualScreenSize(uint width, uint height);
+
+ /**
+ * Notify the manager of a OpenGL context change. This should be the first
+ * thing to call when you create an OpenGL (ES) context!
+ *
+ * @param defaultFormat The new default format for the game screen
+ * (this is used for the CLUT8 game screens).
+ * @param defaultFromatAlpha The new default format with an alpha channel
+ * (this is used for the overlay and cursor).
+ */
+ void notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha);
+
+ /**
+ * Adjust the physical mouse coordinates according to the currently visible screen.
+ */
+ void adjustMousePosition(int16 &x, int16 &y);
+
+ /**
+ * Set up the mouse position for graphics output.
+ *
+ * @param x X coordinate in physical coordinates.
+ * @param y Y coordinate in physical coordinates.
+ */
+ void setMousePosition(int x, int y) { _cursorX = x; _cursorY = y; }
+
+ /**
+ * Query the mouse position in physical coordinates.
*/
- virtual void initGL();
+ void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; }
/**
- * Creates and refreshs OpenGL textures.
+ * Set up the mouse position for the (event) system.
+ *
+ * @param x X coordinate in physical coordinates.
+ * @param y Y coordinate in physical coordinates.
*/
- virtual void loadTextures();
+ virtual void setInternalMousePosition(int x, int y) = 0;
+private:
//
- // GFX and video
+ // Transaction support
//
- enum {
- kTransactionNone = 0,
- kTransactionActive = 1,
- kTransactionRollback = 2
- };
-
- struct TransactionDetails {
- bool sizeChanged;
- bool needRefresh;
- bool needUpdatescreen;
- bool filterChanged;
+ struct VideoState {
+ VideoState() : valid(false), gameWidth(0), gameHeight(0),
#ifdef USE_RGB_COLOR
- bool formatChanged;
+ gameFormat(),
#endif
- };
- TransactionDetails _transactionDetails;
- int _transactionMode;
-
- struct VideoState {
- bool setup;
+ aspectRatioCorrection(false), graphicsMode(GFX_LINEAR) {
+ }
- bool fullscreen;
+ bool valid;
- int mode;
- int scaleFactor;
- bool antialiasing;
+ uint gameWidth, gameHeight;
+#ifdef USE_RGB_COLOR
+ Graphics::PixelFormat gameFormat;
+#endif
bool aspectRatioCorrection;
+ int graphicsMode;
- int screenWidth, screenHeight;
- int overlayWidth, overlayHeight;
- int hardwareWidth, hardwareHeight;
+ bool operator==(const VideoState &right) {
+ return gameWidth == right.gameWidth && gameHeight == right.gameHeight
#ifdef USE_RGB_COLOR
- Graphics::PixelFormat format;
+ && gameFormat == right.gameFormat
#endif
+ && aspectRatioCorrection == right.aspectRatioCorrection
+ && graphicsMode == right.graphicsMode;
+ }
+
+ bool operator!=(const VideoState &right) {
+ return !(*this == right);
+ }
};
- VideoState _videoMode, _oldVideoMode;
/**
- * Sets the OpenGL texture format for the given pixel format. If format is not support will raise an error.
+ * The currently setup video state.
*/
- virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &type);
+ VideoState _currentState;
- virtual void internUpdateScreen();
- virtual bool loadGFXMode();
- virtual void unloadGFXMode();
+ /**
+ * The old video state used when doing a transaction rollback.
+ */
+ VideoState _oldState;
+protected:
+ enum TransactionMode {
+ kTransactionNone = 0,
+ kTransactionActive = 1,
+ kTransactionRollback = 2
+ };
+
+ TransactionMode getTransactionMode() const { return _transactionMode; }
+
+private:
/**
- * Setup the fullscreen mode state.
+ * The current transaction mode.
*/
- void setFullscreenMode(bool enable);
+ TransactionMode _transactionMode;
/**
- * Query the fullscreen state.
+ * The current screen change ID.
*/
- inline bool getFullscreenMode() const { return _videoMode.fullscreen; }
+ int _screenChangeID;
+protected:
/**
- * Set the scale factor.
+ * Set up the requested video mode. This takes parameters which describe
+ * what resolution the game screen requests (this is possibly aspect ratio
+ * corrected!).
*
- * This can only be used in a GFX transaction.
+ * A sub-class should take these parameters as hints. It might very well
+ * set up a mode which it thinks suites the situation best.
*
- * @param newScale New scale factor.
+ * @parma requestedWidth This is the requested actual game screen width.
+ * @param requestedHeight This is the requested actual game screen height.
+ * @param format This is the requested pixel format of the virtual game screen.
+ * @return true on success, false otherwise
*/
- void setScale(int newScale);
+ virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
/**
- * Query the scale factor.
+ * Save a screenshot of the full display as BMP to the given file. This
+ * uses Common::DumpFile for writing the screenshot.
+ *
+ * @param filename The output filename.
*/
- inline int getScale() const { return _videoMode.scaleFactor; }
+ void saveScreenshot(const Common::String &filename) const;
+
+private:
+ //
+ // OpenGL utilities
+ //
/**
- * Toggle the antialiasing state of the current video mode.
+ * Try to determine the internal parameters for a given pixel format.
*
- * This can only be used in a GFX transaction.
+ * @return true when the format can be used, false otherwise.
+ */
+ bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const;
+
+ //
+ // Actual hardware screen
+ //
+
+ /**
+ * The width of the physical output.
+ */
+ uint _outputScreenWidth;
+
+ /**
+ * The height of the physical output.
+ */
+ uint _outputScreenHeight;
+
+ /**
+ * @return The desired aspect of the game screen.
+ */
+ frac_t getDesiredGameScreenAspect() const;
+
+ /**
+ * Recalculates the area used to display the game screen.
*/
- void toggleAntialiasing();
+ void recalculateDisplayArea();
/**
- * Query the antialiasing state.
+ * The X coordinate of the game screen.
*/
- inline bool getAntialiasingState() const { return _videoMode.antialiasing; }
+ uint _displayX;
- // Drawing coordinates for the current display mode and scale
- int _displayX;
- int _displayY;
- int _displayWidth;
- int _displayHeight;
+ /**
+ * The Y coordinate of the game screen.
+ */
+ uint _displayY;
- virtual const char *getCurrentModeName();
+ /**
+ * The width of the game screen in physical coordinates.
+ */
+ uint _displayWidth;
- virtual void calculateDisplaySize(int &width, int &height);
- virtual void refreshDisplaySize();
+ /**
+ * The height of the game screen in physical coordinates.
+ */
+ uint _displayHeight;
- uint getAspectRatio() const;
+ /**
+ * The default pixel format of the backend.
+ */
+ Graphics::PixelFormat _defaultFormat;
- void setFormatIsBGR(bool isBGR) { _formatBGR = isBGR; }
- bool _formatBGR;
+ /**
+ * The default pixel format with an alpha channel.
+ */
+ Graphics::PixelFormat _defaultFormatAlpha;
//
// Game screen
//
- GLTexture *_gameTexture;
- Graphics::Surface _screenData;
- int _screenChangeCount;
- bool _screenNeedsRedraw;
- Common::Rect _screenDirtyRect;
-#ifdef USE_RGB_COLOR
- Graphics::PixelFormat _screenFormat;
-#endif
- byte *_gamePalette;
+ /**
+ * The virtual game screen.
+ */
+ Texture *_gameScreen;
- virtual void refreshGameScreen();
+ /**
+ * The game palette if in CLUT8 mode.
+ */
+ byte _gamePalette[3 * 256];
- // Shake mode
- int _shakePos;
+ /**
+ * The offset by which the screen is moved vertically.
+ */
+ int _gameScreenShakeOffset;
//
// Overlay
//
- GLTexture *_overlayTexture;
- Graphics::Surface _overlayData;
- Graphics::PixelFormat _overlayFormat;
- bool _overlayVisible;
- bool _overlayNeedsRedraw;
- Common::Rect _overlayDirtyRect;
- virtual void refreshOverlay();
+ /**
+ * The overlay screen.
+ */
+ Texture *_overlay;
+
+ /**
+ * Whether the overlay is visible or not.
+ */
+ bool _overlayVisible;
//
- // Mouse
+ // Cursor
//
- struct MousePos {
- // The mouse position in hardware screen coordinates.
- int16 x, y;
- // The size and hotspot of the original cursor image.
- int16 w, h;
- int16 hotX, hotY;
+ /**
+ * Set up the correct cursor palette.
+ */
+ void updateCursorPalette();
- // The size and hotspot of the scaled cursor, in real coordinates.
- int16 rW, rH;
- int16 rHotX, rHotY;
+ /**
+ * The cursor image.
+ */
+ Texture *_cursor;
- // The size and hotspot of the scaled cursor, in game coordinates.
- int16 vW, vH;
- int16 vHotX, vHotY;
+ /**
+ * X coordinate of the cursor in phyiscal coordinates.
+ */
+ uint _cursorX;
- MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),
- rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
- vHotX(0), vHotY(0) {}
- };
+ /**
+ * Y coordinate of the cursor in physical coordinates.
+ */
+ uint _cursorY;
- GLTexture *_cursorTexture;
- Graphics::Surface _cursorData;
- Graphics::PixelFormat _cursorFormat;
- byte *_cursorPalette;
- bool _cursorPaletteDisabled;
- MousePos _cursorState;
- bool _cursorVisible;
+ /**
+ * The X offset for the cursor hotspot in unscaled coordinates.
+ */
+ uint _cursorHotspotX;
+
+ /**
+ * The Y offset for the cursor hotspot in unscaled coordinates.
+ */
+ uint _cursorHotspotY;
+
+ /**
+ * Recalculate the cursor scaling. Scaling is always done according to
+ * the game screen.
+ */
+ void recalculateCursorScaling();
+
+ /**
+ * The X offset for the cursor hotspot in scaled coordinates.
+ */
+ uint _cursorHotspotXScaled;
+
+ /**
+ * The Y offset for the cursor hotspot in scaled coordinates.
+ */
+ uint _cursorHotspotYScaled;
+
+ /**
+ * The width of the cursor scaled coordinates.
+ */
+ uint _cursorWidthScaled;
+
+ /**
+ * The height of the cursor scaled coordinates.
+ */
+ uint _cursorHeightScaled;
+
+ /**
+ * The key color.
+ */
uint32 _cursorKeyColor;
- bool _cursorDontScale;
- bool _cursorNeedsRedraw;
/**
- * Set up the mouse position for graphics output.
- *
- * @param x X coordinate in native coordinates.
- * @param y Y coordinate in native coordinates.
+ * Whether the cursor is actually visible.
*/
- void setMousePosition(int x, int y) { _cursorState.x = x; _cursorState.y = y; }
+ bool _cursorVisible;
- virtual void refreshCursor();
- virtual void refreshCursorScale();
+ /**
+ * Whether no cursor scaling should be applied.
+ */
+ bool _cursorDontScale;
/**
- * Set up the mouse position for the (event) system.
- *
- * @param x X coordinate in native coordinates.
- * @param y Y coordinate in native coordinates.
+ * Whether the special cursor palette is enabled.
*/
- virtual void setInternalMousePosition(int x, int y) = 0;
+ bool _cursorPaletteEnabled;
/**
- * Adjusts hardware screen coordinates to either overlay or game screen
- * coordinates depending on whether the overlay is visible or not.
- *
- * @param x X coordinate of the mouse position.
- * @param y Y coordinate of the mouse position.
+ * The special cursor palette in case enabled.
*/
- virtual void adjustMousePosition(int16 &x, int16 &y);
+ byte _cursorPalette[3 * 256];
+#ifdef USE_OSD
//
- // Misc
+ // OSD
//
- virtual bool saveScreenshot(const char *filename);
-
-#ifdef USE_OSD
+protected:
/**
* Returns the font used for on screen display
*/
virtual const Graphics::Font *getFontOSD();
+private:
/**
- * Update the OSD texture / surface.
+ * The OSD's contents.
*/
- void updateOSD();
+ Texture *_osd;
/**
- * The OSD contents.
+ * Current opacity level of the OSD.
*/
- Common::Array<Common::String> _osdLines;
-
- GLTexture *_osdTexture;
- Graphics::Surface _osdSurface;
uint8 _osdAlpha;
+
+ /**
+ * When fading the OSD has started.
+ */
uint32 _osdFadeStartTime;
- bool _requireOSDUpdate;
+
+ /**
+ * Mutex to allow displayMessageOnOSD to be used from the audio thread.
+ */
+ Common::Mutex _osdMutex;
+
enum {
kOSDFadeOutDelay = 2 * 1000,
kOSDFadeOutDuration = 500,
@@ -348,4 +474,6 @@ protected:
#endif
};
+} // End of namespace OpenGL
+
#endif
diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/opengl-sys.h
index 439593577d..a3524b28d2 100644
--- a/backends/graphics/opengl/glerrorcheck.cpp
+++ b/backends/graphics/opengl/opengl-sys.h
@@ -8,25 +8,25 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#include "common/scummsys.h"
+#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_H
+#define BACKENDS_GRAPHICS_OPENGL_OPENGL_H
-#if defined(DEBUG) && defined(USE_OPENGL)
+// The purpose of this header is to include the OpenGL headers in an uniform
+// fashion. A notable example for a non standard port is the Tizen port.
-#include "backends/graphics/opengl/glerrorcheck.h"
-#include "common/textconsole.h"
-#include "common/str.h"
+#include "common/scummsys.h"
#ifdef WIN32
#if defined(ARRAYSIZE) && !defined(_WINDOWS_)
@@ -37,31 +37,21 @@
#undef ARRAYSIZE
#endif
-#if defined(USE_GLES)
+// HACK: In case common/util.h has been included already we need to make sure
+// to define ARRAYSIZE again in case of Windows.
+#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H)
+#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
+#endif
+
+#if defined(TIZEN)
+#include <FGraphicsOpengl.h>
+using namespace Tizen::Graphics::Opengl;
+#elif defined(USE_GLES)
#include <GLES/gl.h>
-#elif defined(MACOSX)
-#include <OpenGL/gl.h>
+#elif defined(SDL_BACKEND)
+#include <SDL_opengl.h>
#else
#include <GL/gl.h>
#endif
-static Common::String getGlErrStr(GLenum error) {
- switch (error) {
- case GL_NO_ERROR: return "GL_NO_ERROR";
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
- }
-
- return Common::String::format("(Unknown GL error code 0x%x)", error);
-}
-
-void checkGlError(const char *file, int line) {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
- warning("%s:%d: GL error: %s", file, line, getGlErrStr(error).c_str());
-}
-
#endif
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
new file mode 100644
index 0000000000..8f17ed7eeb
--- /dev/null
+++ b/backends/graphics/opengl/texture.cpp
@@ -0,0 +1,371 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/graphics/opengl/texture.h"
+#include "backends/graphics/opengl/extensions.h"
+#include "backends/graphics/opengl/debug.h"
+
+#include "common/rect.h"
+#include "common/textconsole.h"
+
+namespace OpenGL {
+
+static GLuint nextHigher2(GLuint v) {
+ if (v == 0)
+ return 1;
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return ++v;
+}
+
+GLint Texture::_maxTextureSize = 0;
+
+void Texture::queryTextureInformation() {
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize);
+ debug(5, "OpenGL maximum texture size: %d", _maxTextureSize);
+}
+
+Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
+ : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST),
+ _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) {
+ recreateInternalTexture();
+}
+
+Texture::~Texture() {
+ releaseInternalTexture();
+ _textureData.free();
+}
+
+void Texture::releaseInternalTexture() {
+ GLCALL(glDeleteTextures(1, &_glTexture));
+ _glTexture = 0;
+}
+
+void Texture::recreateInternalTexture() {
+ // Get a new texture name.
+ GLCALL(glGenTextures(1, &_glTexture));
+
+ // Set up all texture parameters.
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+ GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+ // In case there is an actual texture setup we reinitialize it.
+ if (_textureData.getPixels()) {
+ // Allocate storage for OpenGL texture.
+ GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w,
+ _textureData.h, 0, _glFormat, _glType, NULL));
+
+ // Mark dirts such that it will be completely refreshed the next time.
+ flagDirty();
+ }
+}
+
+void Texture::enableLinearFiltering(bool enable) {
+ if (enable) {
+ _glFilter = GL_LINEAR;
+ } else {
+ _glFilter = GL_NEAREST;
+ }
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+}
+
+void Texture::allocate(uint width, uint height) {
+ uint texWidth = width, texHeight = height;
+ if (!g_extNPOTSupported) {
+ texWidth = nextHigher2(texWidth);
+ texHeight = nextHigher2(texHeight);
+ }
+
+ // In case the needed texture dimension changed we will reinitialize the
+ // texture.
+ if (texWidth != _textureData.w || texHeight != _textureData.h) {
+ // Create a buffer for the texture data.
+ _textureData.create(texWidth, texHeight, _format);
+
+ // Set the texture.
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+
+ // Allocate storage for OpenGL texture.
+ GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w,
+ _textureData.h, 0, _glFormat, _glType, NULL));
+ }
+
+ // Create a sub-buffer for raw access.
+ _userPixelData = _textureData.getSubArea(Common::Rect(width, height));
+}
+
+void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) {
+ Graphics::Surface *dstSurf = getSurface();
+ assert(x + w <= dstSurf->w);
+ assert(y + h <= dstSurf->h);
+
+ // *sigh* Common::Rect::extend behaves unexpected whenever one of the two
+ // parameters is an empty rect. Thus, we check whether the current dirty
+ // area is valid. In case it is not we simply use the parameters as new
+ // dirty area. Otherwise, we simply call extend.
+ if (_dirtyArea.isEmpty()) {
+ _dirtyArea = Common::Rect(x, y, x + w, y + h);
+ } else {
+ _dirtyArea.extend(Common::Rect(x, y, x + w, y + h));
+ }
+
+ const byte *src = (const byte *)srcPtr;
+ byte *dst = (byte *)dstSurf->getBasePtr(x, y);
+ const uint pitch = dstSurf->pitch;
+ const uint bytesPerPixel = dstSurf->format.bytesPerPixel;
+
+ if (srcPitch == pitch && x == 0 && w == dstSurf->w) {
+ memcpy(dst, src, h * pitch);
+ } else {
+ while (h-- > 0) {
+ memcpy(dst, src, w * bytesPerPixel);
+ dst += pitch;
+ src += srcPitch;
+ }
+ }
+}
+
+void Texture::fill(uint32 color) {
+ Graphics::Surface *dst = getSurface();
+ dst->fillRect(Common::Rect(dst->w, dst->h), color);
+
+ flagDirty();
+}
+
+void Texture::draw(GLuint x, GLuint y, GLuint w, GLuint h) {
+ // Only do any processing when the Texture is initialized.
+ if (!_textureData.getPixels()) {
+ return;
+ }
+
+ // First update any potentional changes.
+ updateTexture();
+
+ // Set the texture.
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+
+ // Calculate the texture rect that will be drawn.
+ const GLfloat texWidth = (GLfloat)_userPixelData.w / _textureData.w;
+ const GLfloat texHeight = (GLfloat)_userPixelData.h / _textureData.h;
+ const GLfloat texcoords[4*2] = {
+ 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight
+ };
+ GLCALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
+
+ // Calculate the screen rect where the texture will be drawn.
+ const GLshort vertices[4*2] = {
+ (GLshort)x, (GLshort)y,
+ (GLshort)(x + w), (GLshort)y,
+ (GLshort)x, (GLshort)(y + h),
+ (GLshort)(x + w), (GLshort)(y + h)
+ };
+ GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
+
+ // Draw the texture to the screen buffer.
+ GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
+}
+
+void Texture::updateTexture() {
+ if (!isDirty()) {
+ return;
+ }
+
+ Common::Rect dirtyArea = getDirtyArea();
+
+ // In case we use linear filtering we might need to duplicate the last
+ // pixel row/column to avoid glitches with filtering.
+ if (_glFilter == GL_LINEAR) {
+ if (dirtyArea.right == _userPixelData.w && _userPixelData.w != _textureData.w) {
+ uint height = dirtyArea.height();
+
+ const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, dirtyArea.top);
+ byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, dirtyArea.top);
+
+ while (height-- > 0) {
+ memcpy(dst, src, _textureData.format.bytesPerPixel);
+ dst += _textureData.pitch;
+ src += _textureData.pitch;
+ }
+
+ // Extend the dirty area.
+ ++dirtyArea.right;
+ }
+
+ if (dirtyArea.bottom == _userPixelData.h && _userPixelData.h != _textureData.h) {
+ const byte *src = (const byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h - 1);
+ byte *dst = (byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h);
+ memcpy(dst, src, dirtyArea.width() * _textureData.format.bytesPerPixel);
+
+ // Extend the dirty area.
+ ++dirtyArea.bottom;
+ }
+ }
+
+ // Set the texture.
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+
+ // Update the actual texture.
+ // Although we keep track of the dirty part of the texture buffer we
+ // cannot take advantage of the left/right boundries here because it is
+ // not possible to specify a pitch to glTexSubImage2D. To be precise, with
+ // plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However,
+ // OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left
+ // with the following options:
+ //
+ // 1) (As we do right now) Simply always update the whole texture lines of
+ // rect changed. This is simplest to implement. In case performance is
+ // really an issue we can think of switching to another method.
+ //
+ // 2) Copy the dirty rect to a temporary buffer and upload that by using
+ // glTexSubImage2D. This is what the Android backend does. It is more
+ // complicated though.
+ //
+ // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL
+ // graphics manager did but it is much slower! Thus, we do not use it.
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(),
+ _glFormat, _glType, _textureData.getBasePtr(0, dirtyArea.top)));
+
+ // We should have handled everything, thus not dirty anymore.
+ clearDirty();
+}
+
+Common::Rect Texture::getDirtyArea() const {
+ if (_allDirty) {
+ return Common::Rect(_userPixelData.w, _userPixelData.h);
+ } else {
+ return _dirtyArea;
+ }
+}
+
+TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
+ : Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) {
+ memset(_palette, 0, sizeof(byte) * format.bytesPerPixel);
+}
+
+TextureCLUT8::~TextureCLUT8() {
+ delete[] _palette;
+ _palette = nullptr;
+ _clut8Data.free();
+}
+
+void TextureCLUT8::allocate(uint width, uint height) {
+ Texture::allocate(width, height);
+
+ // We only need to reinitialize our CLUT8 surface when the output size
+ // changed.
+ if (width == _clut8Data.w && height == _clut8Data.h) {
+ return;
+ }
+
+ _clut8Data.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+}
+
+Graphics::PixelFormat TextureCLUT8::getFormat() const {
+ return Graphics::PixelFormat::createFormatCLUT8();
+}
+
+namespace {
+template<typename ColorType>
+inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) {
+ while (colors-- > 0) {
+ *dst++ = format.RGBToColor(src[0], src[1], src[2]);
+ src += 3;
+ }
+}
+} // End of anonymous namespace
+
+void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) {
+ const Graphics::PixelFormat &hardwareFormat = getHardwareFormat();
+
+ if (hardwareFormat.bytesPerPixel == 2) {
+ convertPalette<uint16>((uint16 *)_palette + start, palData, colors, hardwareFormat);
+ } else if (hardwareFormat.bytesPerPixel == 4) {
+ convertPalette<uint32>((uint32 *)_palette + start, palData, colors, hardwareFormat);
+ } else {
+ warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", hardwareFormat.bytesPerPixel);
+ }
+
+ // A palette changes means we need to refresh the whole surface.
+ flagDirty();
+}
+
+namespace {
+template<typename PixelType>
+inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint height, uint dstPitch, uint srcPitch, const PixelType *palette) {
+ uint srcAdd = srcPitch - width;
+ uint dstAdd = dstPitch - width * sizeof(PixelType);
+
+ while (height-- > 0) {
+ for (uint x = width; x > 0; --x) {
+ *dst++ = palette[*src++];
+ }
+
+ dst = (PixelType *)((byte *)dst + dstAdd);
+ src += srcAdd;
+ }
+}
+} // End of anonymous namespace
+
+void TextureCLUT8::updateTexture() {
+ if (!isDirty()) {
+ return;
+ }
+
+ // Do the palette look up
+ Graphics::Surface *outSurf = Texture::getSurface();
+
+ Common::Rect dirtyArea = getDirtyArea();
+
+ if (outSurf->format.bytesPerPixel == 2) {
+ doPaletteLookUp<uint16>((uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
+ (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
+ dirtyArea.width(), dirtyArea.height(),
+ outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette);
+ } else if (outSurf->format.bytesPerPixel == 4) {
+ doPaletteLookUp<uint32>((uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
+ (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
+ dirtyArea.width(), dirtyArea.height(),
+ outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette);
+ } else {
+ warning("TextureCLUT8::updateTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel);
+ }
+
+ // Do generic handling of updating the texture.
+ Texture::updateTexture();
+}
+
+} // End of namespace OpenGL
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
new file mode 100644
index 0000000000..e28d980de4
--- /dev/null
+++ b/backends/graphics/opengl/texture.h
@@ -0,0 +1,175 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
+#define BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
+
+#include "backends/graphics/opengl/opengl-sys.h"
+
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+
+namespace OpenGL {
+
+/**
+ * An OpenGL texture wrapper. It automatically takes care of all OpenGL
+ * texture handling issues and also provides access to the texture data.
+ */
+class Texture {
+public:
+ /**
+ * Create a new texture with the specific internal format.
+ *
+ * @param glIntFormat The internal format to use.
+ * @param glFormat The input format.
+ * @param glType The input type.
+ * @param format The format used for the texture input.
+ */
+ Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
+ virtual ~Texture();
+
+ /**
+ * Destroy the OpenGL texture name.
+ */
+ void releaseInternalTexture();
+
+ /**
+ * Create the OpenGL texture name and flag the whole texture as dirty.
+ */
+ void recreateInternalTexture();
+
+ /**
+ * Enable or disable linear texture filtering.
+ *
+ * @param enable true to enable and false to disable.
+ */
+ void enableLinearFiltering(bool enable);
+
+ /**
+ * Allocate texture space for the desired dimensions. This wraps any
+ * handling of requirements for POT textures.
+ *
+ * @param width The desired logical width.
+ * @param height The desired logical height.
+ */
+ virtual void allocate(uint width, uint height);
+
+ void copyRectToTexture(uint x, uint y, uint w, uint h, const void *src, uint srcPitch);
+
+ void fill(uint32 color);
+
+ void draw(GLuint x, GLuint y, GLuint w, GLuint h);
+
+ void flagDirty() { _allDirty = true; }
+ bool isDirty() const { return _allDirty || !_dirtyArea.isEmpty(); }
+
+ uint getWidth() const { return _userPixelData.w; }
+ uint getHeight() const { return _userPixelData.h; }
+
+ /**
+ * @return The hardware format of the texture data.
+ */
+ const Graphics::PixelFormat &getHardwareFormat() const { return _format; }
+
+ /**
+ * @return The logical format of the texture data.
+ */
+ virtual Graphics::PixelFormat getFormat() const { return _format; }
+
+ virtual Graphics::Surface *getSurface() { return &_userPixelData; }
+ virtual const Graphics::Surface *getSurface() const { return &_userPixelData; }
+
+ /**
+ * @return Whether the texture data is using a palette.
+ */
+ virtual bool hasPalette() const { return false; }
+
+ virtual void setPalette(uint start, uint colors, const byte *palData) {}
+
+ virtual void *getPalette() { return 0; }
+ virtual const void *getPalette() const { return 0; }
+
+ /**
+ * Query texture related OpenGL information from the context. This only
+ * queries the maximum texture size for now.
+ */
+ static void queryTextureInformation();
+
+ /**
+ * @return Return the maximum texture dimensions supported.
+ */
+ static GLint getMaximumTextureSize() { return _maxTextureSize; }
+protected:
+ virtual void updateTexture();
+
+ Common::Rect getDirtyArea() const;
+private:
+ const GLenum _glIntFormat;
+ const GLenum _glFormat;
+ const GLenum _glType;
+ const Graphics::PixelFormat _format;
+
+ GLint _glFilter;
+ GLuint _glTexture;
+
+ Graphics::Surface _textureData;
+ Graphics::Surface _userPixelData;
+
+ bool _allDirty;
+ Common::Rect _dirtyArea;
+ void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); }
+
+ static GLint _maxTextureSize;
+};
+
+class TextureCLUT8 : public Texture {
+public:
+ TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
+ virtual ~TextureCLUT8();
+
+ virtual void allocate(uint width, uint height);
+
+ virtual Graphics::PixelFormat getFormat() const;
+
+ virtual bool hasPalette() const { return true; }
+
+ virtual void setPalette(uint start, uint colors, const byte *palData);
+
+ virtual void *getPalette() { return _palette; }
+ virtual const void *getPalette() const { return _palette; }
+
+ virtual Graphics::Surface *getSurface() { return &_clut8Data; }
+ virtual const Graphics::Surface *getSurface() const { return &_clut8Data; }
+
+protected:
+ virtual void updateTexture();
+
+private:
+ Graphics::Surface _clut8Data;
+ byte *_palette;
+};
+
+} // End of namespace OpenGL
+
+#endif
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index c5605cae87..e39cd35870 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -8,496 +8,353 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#include "common/scummsys.h"
-
-#if defined(SDL_BACKEND) && defined(USE_OPENGL)
-
#include "backends/graphics/openglsdl/openglsdl-graphics.h"
-#include "backends/platform/sdl/sdl.h"
-#include "common/config-manager.h"
+
#include "common/textconsole.h"
+#include "common/config-manager.h"
+#ifdef USE_OSD
#include "common/translation.h"
+#endif
-OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource)
- :
- SdlGraphicsManager(eventSource),
- _hwscreen(0),
- _screenResized(false),
- _activeFullscreenMode(-2),
- _lastFullscreenModeWidth(0),
- _lastFullscreenModeHeight(0),
- _desktopWidth(0),
- _desktopHeight(0),
- _ignoreResizeFrames(0) {
-
- // Initialize SDL video subsystem
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
- error("Could not initialize SDL: %s", SDL_GetError());
+OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource)
+ : SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0),
+ _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
+ _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
+ // Setup OpenGL attributes for SDL
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ // Retrieve a list of working fullscreen modes
+ const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
+ if (availableModes != (void *)-1) {
+ for (;*availableModes; ++availableModes) {
+ const SDL_Rect *mode = *availableModes;
+
+ _fullscreenVideoModes.push_back(VideoMode(mode->w, mode->h));
+ }
+
+ // Sort the modes in ascending order.
+ Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end());
}
- // This is also called in initSDL(), but initializing graphics
- // may reset it.
- SDL_EnableUNICODE(1);
-
- // Disable OS cursor
- SDL_ShowCursor(SDL_DISABLE);
-
- // Get desktop resolution
- // TODO: In case the OpenGL manager is created *after* a plain SDL manager
- // has been used, this will return the last setup graphics mode rather
- // than the desktop resolution. We should really look into a way to
- // properly retrieve the desktop resolution.
- const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
- if (videoInfo->current_w > 0 && videoInfo->current_h > 0) {
- _desktopWidth = videoInfo->current_w;
- _desktopHeight = videoInfo->current_h;
+ // In case SDL is fine with every mode we will force the desktop mode.
+ // TODO? We could also try to add some default resolutions here.
+ if (_fullscreenVideoModes.empty() && desktopWidth && desktopHeight) {
+ _fullscreenVideoModes.push_back(VideoMode(desktopWidth, desktopHeight));
}
- if (ConfMan.hasKey("last_fullscreen_mode_width") && ConfMan.hasKey("last_fullscreen_mode_height")) {
- _lastFullscreenModeWidth = ConfMan.getInt("last_fullscreen_mode_width");
- _lastFullscreenModeHeight = ConfMan.getInt("last_fullscreen_mode_height");
+ // Get information about display sizes from the previous runs.
+ if (ConfMan.hasKey("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain)) {
+ _desiredFullscreenWidth = ConfMan.getInt("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain);
+ _desiredFullscreenHeight = ConfMan.getInt("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain);
+ } else {
+ // Use the desktop resolutions when no previous default has been setup.
+ _desiredFullscreenWidth = desktopWidth;
+ _desiredFullscreenHeight = desktopHeight;
}
}
OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {
- // Unregister the event observer
- if (g_system->getEventManager()->getEventDispatcher() != NULL)
- g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
}
-void OpenGLSdlGraphicsManager::initEventObserver() {
+void OpenGLSdlGraphicsManager::activateManager() {
+ OpenGLGraphicsManager::activateManager();
+ initEventSource();
+
// Register the graphics manager as a event observer
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
}
+void OpenGLSdlGraphicsManager::deactivateManager() {
+ // Unregister the event observer
+ if (g_system->getEventManager()->getEventDispatcher()) {
+ g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
+ }
+
+ deinitEventSource();
+ OpenGLGraphicsManager::deactivateManager();
+}
+
bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
- return
- (f == OSystem::kFeatureFullscreenMode) ||
- (f == OSystem::kFeatureIconifyWindow) ||
- OpenGLGraphicsManager::hasFeature(f);
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ case OSystem::kFeatureIconifyWindow:
+ return true;
+
+ default:
+ return OpenGLGraphicsManager::hasFeature(f);
+ }
}
void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ assert(getTransactionMode() != kTransactionNone);
+ _wantsFullScreen = enable;
+ // When we switch to windowed mode we will ignore resize events. This
+ // avoids bad resizes to the (former) fullscreen resolution.
+ if (!enable) {
+ _ignoreResizeEvents = 10;
+ }
+ break;
+
case OSystem::kFeatureIconifyWindow:
- if (enable)
+ if (enable) {
SDL_WM_IconifyWindow();
+ }
break;
+
default:
OpenGLGraphicsManager::setFeatureState(f, enable);
}
}
-#ifdef USE_RGB_COLOR
-
-Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const {
- assert(!_supportedFormats.empty());
- return _supportedFormats;
-}
-
-void OpenGLSdlGraphicsManager::detectSupportedFormats() {
-
- // Clear old list
- _supportedFormats.clear();
-
- // Some tables with standard formats that we always list
- // as "supported". If frontend code tries to use one of
- // these, we will perform the necessary format
- // conversion in the background. Of course this incurs a
- // performance hit, but on desktop ports this should not
- // matter. We still push the currently active format to
- // the front, so if frontend code just uses the first
- // available format, it will get one that is "cheap" to
- // use.
- const Graphics::PixelFormat RGBList[] = {
-#if defined(ENABLE_32BIT)
- Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), // RGBA8888
-#ifndef USE_GLES
- Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), // ARGB8888
-#endif
- Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), // RGB888
-#endif
- Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), // RGB565
- Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0), // RGB5551
- Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555
- Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444
-#ifndef USE_GLES
- Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) // ARGB4444
-#endif
- };
-#ifndef USE_GLES
- const Graphics::PixelFormat BGRList[] = {
-#ifdef ENABLE_32BIT
- Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), // ABGR8888
- Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0), // BGRA8888
- Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), // BGR888
-#endif
- Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0), // BGR565
- Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0), // BGRA5551
- Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12), // ABGR4444
- Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) // BGRA4444
- };
-#endif
-
- Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
- if (_hwscreen) {
- // Get our currently set hardware format
- format = Graphics::PixelFormat(_hwscreen->format->BytesPerPixel,
- 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss,
- 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss,
- _hwscreen->format->Rshift, _hwscreen->format->Gshift,
- _hwscreen->format->Bshift, _hwscreen->format->Ashift);
-
- // Workaround to SDL not providing an accurate Aloss value on Mac OS X.
- if (_hwscreen->format->Amask == 0)
- format.aLoss = 8;
-
- // Push it first, as the prefered format if available
- for (int i = 0; i < ARRAYSIZE(RGBList); i++) {
- if (RGBList[i] == format) {
- _supportedFormats.push_back(format);
- break;
- }
- }
-#ifndef USE_GLES
- for (int i = 0; i < ARRAYSIZE(BGRList); i++) {
- if (BGRList[i] == format) {
- _supportedFormats.push_back(format);
- break;
- }
+bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ if (_hwScreen) {
+ return (_hwScreen->flags & SDL_FULLSCREEN) != 0;
+ } else {
+ return _wantsFullScreen;
}
-#endif
- }
- // Push some RGB formats
- for (int i = 0; i < ARRAYSIZE(RGBList); i++) {
- if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
- continue;
- if (RGBList[i] != format)
- _supportedFormats.push_back(RGBList[i]);
- }
-#ifndef USE_GLES
- // Push some BGR formats
- for (int i = 0; i < ARRAYSIZE(BGRList); i++) {
- if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel))
- continue;
- if (BGRList[i] != format)
- _supportedFormats.push_back(BGRList[i]);
+ default:
+ return OpenGLGraphicsManager::getFeatureState(f);
}
-#endif
- _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8());
}
-#endif
+bool OpenGLSdlGraphicsManager::setGraphicsMode(int mode) {
+ // HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This
+ // assures that the launcher (which requests 320x200) has a reasonable
+ // size. It also makes small games have a reasonable size (i.e. at least
+ // 640x400). We follow the same logic here until we have a better way to
+ // give hints to our backend for that.
+ _graphicsScale = 2;
-void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) {
- SDL_WarpMouse(x, y);
+ return OpenGLGraphicsManager::setGraphicsMode(mode);
}
-void OpenGLSdlGraphicsManager::updateScreen() {
- if (_ignoreResizeFrames)
- _ignoreResizeFrames -= 1;
+void OpenGLSdlGraphicsManager::resetGraphicsScale() {
+ OpenGLGraphicsManager::resetGraphicsScale();
- OpenGLGraphicsManager::updateScreen();
+ // HACK: See OpenGLSdlGraphicsManager::setGraphicsMode.
+ _graphicsScale = 1;
}
-//
-// Intern
-//
-
-bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
- SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL);
-
- // SDL_ListModes() returns -1 in case any dimension is okay. In that
- // case we'll reuse the current desktop resolution for fullscreen.
- if (availableModes == (void *)-1) {
- _videoMode.hardwareWidth = _desktopWidth;
- _videoMode.hardwareHeight = _desktopHeight;
- _activeFullscreenMode = -2;
- return true;
- }
-
- // If -2, autodetect the fullscreen mode
- // The last used fullscreen mode will be prioritized, if there is no last fullscreen
- // mode, the desktop resolution will be used, and in case the desktop resolution
- // is not available as a fullscreen mode, the one with smallest metric will be selected.
- if (_activeFullscreenMode == -2) {
- // Desktop resolution
- int desktopModeIndex = -1;
-
- // Best metric mode
- const SDL_Rect *bestMode = availableModes[0];
- int bestModeIndex = 0;
- uint bestMetric = (uint)-1;
-
- // Iterate over all available fullscreen modes
- for (int i = 0; const SDL_Rect *mode = availableModes[i]; i++) {
- // Try to setup the last used fullscreen mode
- if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) {
- _videoMode.hardwareWidth = _lastFullscreenModeWidth;
- _videoMode.hardwareHeight = _lastFullscreenModeHeight;
- _activeFullscreenMode = i;
- return true;
- }
+#ifdef USE_RGB_COLOR
+Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> formats;
- if (mode->w == _desktopWidth && mode->h == _desktopHeight)
- desktopModeIndex = i;
+ // RGBA8888
+ formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+ // RGB565
+ formats.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ // RGBA5551
+ formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
+ // RGBA4444
+ formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0));
- if (mode->w < _videoMode.overlayWidth)
- continue;
- if (mode->h < _videoMode.overlayHeight)
- continue;
+#ifndef USE_GLES
+ // ARGB8888, this should not be here, but Sword25 requires it. :-/
+ formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
- uint metric = mode->w * mode->h - _videoMode.overlayWidth * _videoMode.overlayHeight;
- if (metric < bestMetric) {
- bestMode = mode;
- bestMetric = metric;
- bestModeIndex = i;
- }
- }
+ // RGB555, this is used by SCUMM HE 16 bit games.
+ formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+#endif
- if (desktopModeIndex >= 0) {
- _videoMode.hardwareWidth = _desktopWidth;
- _videoMode.hardwareHeight = _desktopHeight;
+ formats.push_back(Graphics::PixelFormat::createFormatCLUT8());
- _activeFullscreenMode = desktopModeIndex;
- return true;
- } else if (bestMode) {
- _videoMode.hardwareWidth = bestMode->w;
- _videoMode.hardwareHeight = bestMode->h;
+ return formats;
+}
+#endif
- _activeFullscreenMode = bestModeIndex;
- return true;
- }
- } else {
- // Use last fullscreen mode if looping backwards from the first mode
- if (_activeFullscreenMode == -1) {
- do {
- _activeFullscreenMode++;
- } while(availableModes[_activeFullscreenMode]);
- _activeFullscreenMode--;
- }
+void OpenGLSdlGraphicsManager::updateScreen() {
+ if (_ignoreResizeEvents) {
+ --_ignoreResizeEvents;
+ }
- // Use first fullscreen mode if looping from last mode
- if (!availableModes[_activeFullscreenMode])
- _activeFullscreenMode = 0;
+ OpenGLGraphicsManager::updateScreen();
- // Check if the fullscreen mode is valid
- if (availableModes[_activeFullscreenMode]) {
- _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w;
- _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h;
- return true;
- }
- }
+ // Swap OpenGL buffers
+ SDL_GL_SwapBuffers();
+}
- // Could not find any suiting fullscreen mode, return false.
- return false;
+void OpenGLSdlGraphicsManager::notifyVideoExpose() {
}
-bool OpenGLSdlGraphicsManager::loadGFXMode() {
- // If the screen was resized, do not change its size
- if (!_screenResized) {
- const int scaleFactor = getScale();
- _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor;
- _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor;
-
- // The only modes where we need to adapt the aspect ratio are 320x200
- // and 640x400. That is since our aspect ratio correction in fact is
- // only used to ensure that the original pixel size aspect for these
- // modes is used.
- // (Non-square pixels on old monitors vs square pixel on new ones).
- if (_videoMode.aspectRatioCorrection) {
- if (_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200)
- _videoMode.overlayHeight = _videoMode.hardwareHeight = 240 * scaleFactor;
- else if (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400)
- _videoMode.overlayHeight = _videoMode.hardwareHeight = 480 * scaleFactor;
+void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) {
+ if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) {
+ // We save that we handled a resize event here. We need to know this
+ // so we do not overwrite the users requested window size whenever we
+ // switch aspect ratio or similar.
+ _gotResize = true;
+ if (!setupMode(width, height)) {
+ warning("OpenGLSdlGraphicsManager::notifyResize: Resize failed ('%s')", SDL_GetError());
+ g_system->quit();
}
}
+}
- _screenResized = false;
+void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
+ adjustMousePosition(point.x, point.y);
+}
- // Setup OpenGL attributes for SDL
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
+ setMousePosition(mouse.x, mouse.y);
+}
- const bool isFullscreen = getFullscreenMode();
+void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) {
+ SDL_WarpMouse(x, y);
+}
- // In case we have an fullscreen mode and we are not in a rollback, detect
- // a proper mode to use. In case we are in a rollback, we already detected
- // a proper mode when setting up that mode, thus there is no need to run
- // the detection again.
- if (isFullscreen && _transactionMode != kTransactionRollback) {
- if (!setupFullscreenMode())
- // Failed setuping a fullscreen mode
- return false;
+bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
+ // In some cases we might not want to load the requested video mode. This
+ // will assure that the window size is not altered.
+ if (_ignoreLoadVideoMode) {
+ _ignoreLoadVideoMode = false;
+ return true;
}
- _videoMode.overlayWidth = _videoMode.hardwareWidth;
- _videoMode.overlayHeight = _videoMode.hardwareHeight;
+ // This function should never be called from notifyResize thus we know
+ // that the requested size came from somewhere else.
+ _gotResize = false;
- uint32 flags = SDL_OPENGL;
+ // Save the requested dimensions.
+ _lastRequestedWidth = requestedWidth;
+ _lastRequestedHeight = requestedHeight;
- if (isFullscreen)
- flags |= SDL_FULLSCREEN;
- else
- flags |= SDL_RESIZABLE;
-
- // Create our window
- _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32, flags);
-#ifdef USE_RGB_COLOR
- detectSupportedFormats();
-#endif
+ // Apply the currently saved scale setting.
+ requestedWidth *= _graphicsScale;
+ requestedHeight *= _graphicsScale;
- if (_hwscreen == NULL) {
- // DON'T use error(), as this tries to bring up the debug
- // console, which WON'T WORK now that _hwscreen is hosed.
-
- if (!_oldVideoMode.setup) {
- warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
- g_system->quit();
- } else
- // Cancel GFX load, and go back to last mode
- return false;
- }
+ // Set up the mode.
+ return setupMode(requestedWidth, requestedHeight);
+}
- // Check if the screen is BGR format
- setFormatIsBGR(_hwscreen->format->Rshift != 0);
+bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
+ // In case we request a fullscreen mode we will use the mode the user
+ // has chosen last time or the biggest mode available.
+ if (_wantsFullScreen) {
+ if (_desiredFullscreenWidth && _desiredFullscreenHeight) {
+ // In case only a distinct set of modes is available we check
+ // whether the requested mode is actually available.
+ if (!_fullscreenVideoModes.empty()) {
+ VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
+ _fullscreenVideoModes.end(),
+ VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
+ // It's not available fall back to default.
+ if (i == _fullscreenVideoModes.end()) {
+ _desiredFullscreenWidth = 0;
+ _desiredFullscreenHeight = 0;
+ }
+ }
+ }
- if (isFullscreen) {
- _lastFullscreenModeWidth = _videoMode.hardwareWidth;
- _lastFullscreenModeHeight = _videoMode.hardwareHeight;
- ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth);
- ConfMan.setInt("last_fullscreen_mode_height", _lastFullscreenModeHeight);
- }
+ // In case no desired mode has been set we default to the biggest mode
+ // available or the requested mode in case we don't know any
+ // any fullscreen modes.
+ if (!_desiredFullscreenWidth || !_desiredFullscreenHeight) {
+ if (!_fullscreenVideoModes.empty()) {
+ VideoModeArray::const_iterator i = _fullscreenVideoModes.end();
+ --i;
+
+ _desiredFullscreenWidth = i->width;
+ _desiredFullscreenHeight = i->height;
+ } else {
+ _desiredFullscreenWidth = width;
+ _desiredFullscreenHeight = height;
+ }
+ }
- // Call and return parent implementation of this method
- return OpenGLGraphicsManager::loadGFXMode();
-}
+ // Remember our choice.
+ ConfMan.setInt("last_fullscreen_mode_width", _desiredFullscreenWidth, Common::ConfigManager::kApplicationDomain);
+ ConfMan.setInt("last_fullscreen_mode_height", _desiredFullscreenHeight, Common::ConfigManager::kApplicationDomain);
-void OpenGLSdlGraphicsManager::unloadGFXMode() {
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
+ // Use our choice.
+ width = _desiredFullscreenWidth;
+ height = _desiredFullscreenHeight;
}
-}
-
-void OpenGLSdlGraphicsManager::internUpdateScreen() {
- // Call to parent implementation of this method
- OpenGLGraphicsManager::internUpdateScreen();
-
- // Swap OpenGL buffers
- SDL_GL_SwapBuffers();
-}
-#ifdef USE_OSD
-void OpenGLSdlGraphicsManager::displayModeChangedMsg() {
- const char *newModeName = getCurrentModeName();
- if (newModeName) {
- const int scaleFactor = getScale();
-
- Common::String osdMessage = Common::String::format(
- "%s: %s\n%d x %d -> %d x %d",
- _("Current display mode"),
- newModeName,
- _videoMode.screenWidth * scaleFactor,
- _videoMode.screenHeight * scaleFactor,
- _hwscreen->w, _hwscreen->h
- );
- displayMessageOnOSD(osdMessage.c_str());
+ // WORKAROUND: Working around infamous SDL bugs when switching
+ // resolutions too fast. This might cause the event system to supply
+ // incorrect mouse position events otherwise.
+ // Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779
+ const uint32 curTime = SDL_GetTicks();
+ if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) {
+ for (int i = 10; i > 0; --i) {
+ SDL_PumpEvents();
+ SDL_Delay(10);
+ }
}
-}
-void OpenGLSdlGraphicsManager::displayScaleChangedMsg() {
- const int scaleFactor = getScale();
- Common::String osdMessage = Common::String::format(
- "%s: x%d\n%d x %d -> %d x %d",
- _("Current scale"),
- scaleFactor,
- _videoMode.screenWidth, _videoMode.screenHeight,
- _videoMode.overlayWidth, _videoMode.overlayHeight
- );
- displayMessageOnOSD(osdMessage.c_str());
-}
-#endif
+ _lastVideoModeLoad = curTime;
-bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
- if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
- if (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS ||
- event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS ||
- event.kbd.keycode == 'a' || event.kbd.keycode == 'f')
- return true;
- } else if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_SHIFT)) == (Common::KBD_CTRL|Common::KBD_SHIFT)) {
- if (event.kbd.keycode == 'a' || event.kbd.keycode == 'f')
- return true;
- } else if ((event.kbd.flags & (Common::KBD_ALT)) == (Common::KBD_ALT) && event.kbd.keycode == 's') {
- return true;
+ uint32 flags = SDL_OPENGL;
+ if (_wantsFullScreen) {
+ flags |= SDL_FULLSCREEN;
+ } else {
+ flags |= SDL_RESIZABLE;
}
- return false;
-}
-void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) {
- beginGFXTransaction();
- const bool isFullscreen = getFullscreenMode();
+ _hwScreen = SDL_SetVideoMode(width, height, 32, flags);
- if (isFullscreen && loop) {
- _activeFullscreenMode += loop;
- setFullscreenMode(true);
- } else {
- _activeFullscreenMode = -2;
- setFullscreenMode(!isFullscreen);
+ if (!_hwScreen) {
+ // We treat fullscreen requests as a "hint" for now. This means in
+ // case it is not available we simply ignore it.
+ if (_wantsFullScreen) {
+ _hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE);
}
+ }
- // HACK: We need to force a refresh here, since we change the
- // fullscreen mode.
- _transactionDetails.needRefresh = true;
- endGFXTransaction();
-
- // Ignore resize events for the next 10 frames
- _ignoreResizeFrames = 10;
+ if (_hwScreen) {
+ const Graphics::PixelFormat rgba8888 = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ notifyContextChange(rgba8888, rgba8888);
+ setActualScreenSize(_hwScreen->w, _hwScreen->h);
+ }
-#ifdef USE_OSD
- Common::String osdMessage;
- if (getFullscreenMode())
- osdMessage = Common::String::format("%s\n%d x %d",
- _("Fullscreen mode"),
- _hwscreen->w, _hwscreen->h
- );
- else
- osdMessage = Common::String::format("%s\n%d x %d",
- _("Windowed mode"),
- _hwscreen->w, _hwscreen->h
- );
- displayMessageOnOSD(osdMessage.c_str());
-#endif
+ return _hwScreen != nullptr;
}
bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
switch (event.type) {
+ case Common::EVENT_KEYUP:
+ return isHotkey(event);
+
case Common::EVENT_KEYDOWN:
if (event.kbd.hasFlags(Common::KBD_ALT)) {
- // Alt-Return and Alt-Enter toggle full screen mode
- if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) {
- toggleFullScreen(0);
+ if ( event.kbd.keycode == Common::KEYCODE_RETURN
+ || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) {
+ // Alt-Return and Alt-Enter toggle full screen mode
+ beginGFXTransaction();
+ setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode));
+ endGFXTransaction();
+
+#ifdef USE_OSD
+ if (getFeatureState(OSystem::kFeatureFullscreenMode)) {
+ displayMessageOnOSD("Fullscreen mode");
+ } else {
+ displayMessageOnOSD("Windowed mode");
+ }
+#endif
return true;
}
- // Alt-S create a screenshot
- if (event.kbd.keycode == 's') {
+ if (event.kbd.keycode == Common::KEYCODE_s) {
+ // Alt-s creates a screenshot
Common::String filename;
for (int n = 0;; n++) {
@@ -509,169 +366,167 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
break;
SDL_RWclose(file);
}
- if (saveScreenshot(filename.c_str()))
- debug("Saved screenshot '%s'", filename.c_str());
- else
- warning("Could not save screenshot");
- return true;
- }
- }
- if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) {
- // Ctrl-Alt-Return and Ctrl-Alt-Enter switch between full screen modes
- if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) {
- toggleFullScreen(1);
+ saveScreenshot(filename.c_str());
+ debug("Saved screenshot '%s'", filename.c_str());
+
return true;
}
+ } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
+ if ( event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
+ || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) {
+ // Ctrl+Alt+Plus/Minus Increase/decrease the size
+ const int direction = (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS) ? +1 : -1;
+
+ if (getFeatureState(OSystem::kFeatureFullscreenMode)) {
+ // In case we are in fullscreen we will choose the previous
+ // or next mode.
+
+ // In case no modes are available we do nothing.
+ if (_fullscreenVideoModes.empty()) {
+ return true;
+ }
+
+ // Look for the current mode.
+ VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
+ _fullscreenVideoModes.end(),
+ VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
+ if (i == _fullscreenVideoModes.end()) {
+ return true;
+ }
+
+ // Cycle through the modes in the specified direction.
+ if (direction > 0) {
+ ++i;
+ if (i == _fullscreenVideoModes.end()) {
+ i = _fullscreenVideoModes.begin();
+ }
+ } else {
+ if (i == _fullscreenVideoModes.begin()) {
+ i = _fullscreenVideoModes.end();
+ }
+ --i;
+ }
+
+ _desiredFullscreenWidth = i->width;
+ _desiredFullscreenHeight = i->height;
+
+ // Try to setup the mode.
+ if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) {
+ warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError());
+ g_system->quit();
+ }
+ } else {
+ // Calculate the next scaling setting. We approximate the
+ // current scale setting in case the user resized the
+ // window. Then we apply the direction change.
+ _graphicsScale = MAX<int>(_hwScreen->w / _lastRequestedWidth, _hwScreen->h / _lastRequestedHeight);
+ _graphicsScale = MAX<int>(_graphicsScale + direction, 1);
+
+ // Since we overwrite a user resize here we reset its
+ // flag here. This makes enabling AR smoother because it
+ // will change the window size like in surface SDL.
+ _gotResize = false;
+
+ // Try to setup the mode.
+ if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) {
+ warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError());
+ g_system->quit();
+ }
+ }
- // Ctrl-Alt-a switch between display modes
- if (event.kbd.keycode == 'a') {
- beginGFXTransaction();
- setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
- endGFXTransaction();
#ifdef USE_OSD
- Common::String osdMessage;
- if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
- osdMessage = Common::String::format("%s\n%d x %d -> %d x %d",
- _("Enabled aspect ratio correction"),
- _videoMode.screenWidth, _videoMode.screenHeight,
- _hwscreen->w, _hwscreen->h);
- else
- osdMessage = Common::String::format("%s\n%d x %d -> %d x %d",
- _("Disabled aspect ratio correction"),
- _videoMode.screenWidth, _videoMode.screenHeight,
- _hwscreen->w, _hwscreen->h);
- displayMessageOnOSD(osdMessage.c_str());
+ const Common::String osdMsg = Common::String::format("Resolution: %dx%d", _hwScreen->w, _hwScreen->h);
+ displayMessageOnOSD(osdMsg.c_str());
#endif
- internUpdateScreen();
+
return true;
- }
+ } else if (event.kbd.keycode == Common::KEYCODE_a) {
+ // In case the user changed the window size manually we will
+ // not change the window size again here.
+ _ignoreLoadVideoMode = _gotResize;
- // Ctrl-Alt-f toggles antialiasing
- if (event.kbd.keycode == 'f') {
+ // Ctrl+Alt+a toggles the aspect ratio correction state.
beginGFXTransaction();
- toggleAntialiasing();
+ setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
endGFXTransaction();
+ // Make sure we do not ignore the next resize. This
+ // effectively checks whether loadVideoMode has been called.
+ assert(!_ignoreLoadVideoMode);
+
#ifdef USE_OSD
- // TODO: This makes guesses about what internal antialiasing
- // modes we use, we might want to consider a better way of
- // displaying information to the user.
- if (getAntialiasingState())
- displayMessageOnOSD(_("Active filter mode: Linear"));
- else
- displayMessageOnOSD(_("Active filter mode: Nearest"));
+ Common::String osdMsg = "Aspect ratio correction: ";
+ osdMsg += getFeatureState(OSystem::kFeatureAspectRatioCorrection) ? "enabled" : "disabled";
+ displayMessageOnOSD(osdMsg.c_str());
#endif
+
return true;
- }
+ } else if (event.kbd.keycode == Common::KEYCODE_f) {
+ // Ctrl+Alt+f toggles the graphics modes.
+
+ // We are crazy we will allow the OpenGL base class to
+ // introduce new graphics modes like shaders for special
+ // filtering. If some other OpenGL subclass needs this,
+ // we can think of refactoring this.
+ int mode = getGraphicsMode();
+ const OSystem::GraphicsMode *supportedModes = getSupportedGraphicsModes();
+ const OSystem::GraphicsMode *modeDesc = nullptr;
+
+ // Search the current mode.
+ for (; supportedModes->name; ++supportedModes) {
+ if (supportedModes->id == mode) {
+ modeDesc = supportedModes;
+ break;
+ }
+ }
+ assert(modeDesc);
- SDLKey sdlKey = (SDLKey)event.kbd.keycode;
-
- // Ctrl+Alt+Plus/Minus Increase/decrease the scale factor
- if ((sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS ||
- sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS)) {
- int factor = getScale();
- factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1;
- if (0 < factor && factor < 4) {
- // Check if the desktop resolution has been detected
- if (_desktopWidth > 0 && _desktopHeight > 0)
- // If the new scale factor is too big, do not scale
- if (_videoMode.screenWidth * factor > _desktopWidth ||
- _videoMode.screenHeight * factor > _desktopHeight)
- return false;
-
- beginGFXTransaction();
- setScale(factor);
- endGFXTransaction();
-#ifdef USE_OSD
- displayScaleChangedMsg();
-#endif
- return true;
+ // Try to use the next mode in the list.
+ ++modeDesc;
+ if (!modeDesc->name) {
+ modeDesc = getSupportedGraphicsModes();
}
- }
- const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3);
- const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3);
+ // Never ever try to resize the window when we simply want to
+ // switch the graphics mode. This assures that the window size
+ // does not change.
+ _ignoreLoadVideoMode = true;
+
+ beginGFXTransaction();
+ setGraphicsMode(modeDesc->id);
+ endGFXTransaction();
+
+ // Make sure we do not ignore the next resize. This
+ // effectively checks whether loadVideoMode has been called.
+ assert(!_ignoreLoadVideoMode);
- // Ctrl-Alt-<number key> will change the GFX mode
- if (isNormalNumber || isKeypadNumber) {
- if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 3) {
-#ifdef USE_OSD
- int lastMode = _videoMode.mode;
-#endif
- // We need to query the scale and set it up, because
- // setGraphicsMode sets the default scale to 2
- int oldScale = getScale();
- beginGFXTransaction();
- setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1));
- setScale(oldScale);
- endGFXTransaction();
#ifdef USE_OSD
- if (lastMode != _videoMode.mode)
- displayModeChangedMsg();
+ const Common::String osdMsg = Common::String::format("Graphics mode: %s", _(modeDesc->description));
+ displayMessageOnOSD(osdMsg.c_str());
#endif
- internUpdateScreen();
- }
- }
- }
- if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_SHIFT)) {
- // Ctrl-Shift-Return and Ctrl-Shift-Enter switch backwards between full screen modes
- if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) {
- toggleFullScreen(-1);
return true;
}
}
- break;
-
- case Common::EVENT_KEYUP:
- return isHotkey(event);
+ // Fall through
default:
- break;
+ return false;
}
-
- return false;
-}
-
-void OpenGLSdlGraphicsManager::notifyVideoExpose() {
}
-void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) {
- // Do not resize if ignoring resize events.
- if (!_ignoreResizeFrames && !getFullscreenMode()) {
- bool scaleChanged = false;
- beginGFXTransaction();
- _videoMode.hardwareWidth = width;
- _videoMode.hardwareHeight = height;
-
- _screenResized = true;
-
- int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth,
- _videoMode.hardwareHeight / _videoMode.screenHeight);
-
- if (getScale() != scale) {
- scaleChanged = true;
- setScale(MAX(MIN(scale, 3), 1));
- }
-
- _transactionDetails.sizeChanged = true;
- endGFXTransaction();
-#ifdef USE_OSD
- if (scaleChanged)
- displayScaleChangedMsg();
-#endif
+bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
+ if (event.kbd.hasFlags(Common::KBD_ALT)) {
+ return event.kbd.keycode == Common::KEYCODE_RETURN
+ || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER
+ || event.kbd.keycode == Common::KEYCODE_s;
+ } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
+ return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
+ || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS
+ || event.kbd.keycode == Common::KEYCODE_a
+ || event.kbd.keycode == Common::KEYCODE_f;
}
-}
-
-void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
- adjustMousePosition(point.x, point.y);
-}
-void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
- setMousePosition(mouse.x, mouse.y);
+ return false;
}
-
-#endif
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 1587183328..9934ca79e2 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -8,117 +8,109 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public 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_GRAPHICS_OPENGLSDL_H
-#define BACKENDS_GRAPHICS_OPENGLSDL_H
+#ifndef BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H
+#define BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H
-#include "backends/platform/sdl/sdl-sys.h"
-#if defined(ARRAYSIZE) && !defined(_WINDOWS_)
-#undef ARRAYSIZE
-#endif
-#include "backends/graphics/sdl/sdl-graphics.h"
#include "backends/graphics/opengl/opengl-graphics.h"
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "backends/platform/sdl/sdl-sys.h"
+#include "common/array.h"
#include "common/events.h"
-/**
- * SDL OpenGL graphics manager
- */
-class OpenGLSdlGraphicsManager : public OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver {
+class OpenGLSdlGraphicsManager : public OpenGL::OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver {
public:
- OpenGLSdlGraphicsManager(SdlEventSource *eventSource);
+ OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource);
virtual ~OpenGLSdlGraphicsManager();
+ // GraphicsManager API
+ virtual void activateManager();
+ virtual void deactivateManager();
+
virtual bool hasFeature(OSystem::Feature f);
virtual void setFeatureState(OSystem::Feature f, bool enable);
+ virtual bool getFeatureState(OSystem::Feature f);
+
+ virtual bool setGraphicsMode(int mode);
+ virtual void resetGraphicsScale();
#ifdef USE_RGB_COLOR
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
- virtual void initEventObserver();
- virtual bool notifyEvent(const Common::Event &event);
-
virtual void updateScreen();
- // SdlGraphicsManager interface
+ // EventObserver API
+ virtual bool notifyEvent(const Common::Event &event);
+
+ // SdlGraphicsManager API
virtual void notifyVideoExpose();
virtual void notifyResize(const uint width, const uint height);
virtual void transformMouseCoordinates(Common::Point &point);
virtual void notifyMousePos(Common::Point mouse);
protected:
- virtual void internUpdateScreen();
+ virtual void setInternalMousePosition(int x, int y);
- virtual bool loadGFXMode();
- virtual void unloadGFXMode();
- virtual bool isHotkey(const Common::Event &event);
+ virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format);
+private:
+ bool setupMode(uint width, uint height);
-#ifdef USE_RGB_COLOR
- Common::List<Graphics::PixelFormat> _supportedFormats;
+ uint32 _lastVideoModeLoad;
+ SDL_Surface *_hwScreen;
- /**
- * Update the list of supported pixel formats.
- * This method is invoked by loadGFXMode().
- */
- void detectSupportedFormats();
-#endif
+ uint _lastRequestedWidth;
+ uint _lastRequestedHeight;
+ uint _graphicsScale;
+ bool _ignoreLoadVideoMode;
+ bool _gotResize;
- /**
- * Toggles fullscreen.
- * @loop loop direction for switching fullscreen mode, if 0 toggles it.
- */
- virtual void toggleFullScreen(int loop);
+ bool _wantsFullScreen;
+ uint _ignoreResizeEvents;
- int _activeFullscreenMode;
+ struct VideoMode {
+ VideoMode() : width(0), height(0) {}
+ VideoMode(uint w, uint h) : width(w), height(h) {}
- /**
- * Setup the fullscreen mode.
- * @return false if failed finding a mode, true otherwise.
- */
- virtual bool setupFullscreenMode();
+ bool operator<(const VideoMode &right) const {
+ if (width < right.width) {
+ return true;
+ } else if (width == right.width && height < right.height) {
+ return true;
+ } else {
+ return false;
+ }
+ }
- virtual void setInternalMousePosition(int x, int y);
+ bool operator==(const VideoMode &right) const {
+ return width == right.width && height == right.height;
+ }
- int _lastFullscreenModeWidth;
- int _lastFullscreenModeHeight;
- int _desktopWidth;
- int _desktopHeight;
-
- // Hardware screen
- SDL_Surface *_hwscreen;
-
- // If screen was resized by the user
- bool _screenResized;
-
- // Ignore resize events for the number of updateScreen() calls.
- // Normaly resize events are user generated when resizing the window
- // from its borders, but in some cases a resize event can be generated
- // after a fullscreen change.
- int _ignoreResizeFrames;
-
-#ifdef USE_OSD
- /**
- * Displays a mode change message in OSD
- */
- void displayModeChangedMsg();
-
- /**
- * Displays a scale change message in OSD
- */
- void displayScaleChangedMsg();
-#endif
+ bool operator!=(const VideoMode &right) const {
+ return !(*this == right);
+ }
+
+ uint width, height;
+ };
+ typedef Common::Array<VideoMode> VideoModeArray;
+ VideoModeArray _fullscreenVideoModes;
+
+ uint _desiredFullscreenWidth;
+ uint _desiredFullscreenHeight;
+
+ virtual bool isHotkey(const Common::Event &event);
};
#endif
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 2eca4b8aab..417f4faf54 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -26,10 +26,15 @@
SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source)
: _eventSource(source) {
- _eventSource->setGraphicsManager(this);
}
SdlGraphicsManager::~SdlGraphicsManager() {
- _eventSource->setGraphicsManager(0);
}
+void SdlGraphicsManager::initEventSource() {
+ _eventSource->setGraphicsManager(this);
+}
+
+void SdlGraphicsManager::deinitEventSource() {
+ _eventSource->setGraphicsManager(0);
+}
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index ea9149fccb..4d4338af16 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -80,6 +80,9 @@ public:
virtual void notifyMousePos(Common::Point mouse) = 0;
protected:
+ void initEventSource();
+ void deinitEventSource();
+
SdlEventSource *_eventSource;
};
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 02e58ab319..c946b8e747 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,19 +136,12 @@ 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
_transactionMode(kTransactionNone) {
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
- error("Could not initialize SDL: %s", SDL_GetError());
- }
-
- // This is also called in initSDL(), but initializing graphics
- // may reset it.
- SDL_EnableUNICODE(1);
-
// allocate palette storage
_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
@@ -163,8 +157,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect");
#endif
- SDL_ShowCursor(SDL_DISABLE);
-
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
@@ -191,10 +183,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
}
SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
- // Unregister the event observer
- if (g_system->getEventManager()->getEventDispatcher() != NULL)
- g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
-
unloadGFXMode();
if (_mouseSurface)
SDL_FreeSurface(_mouseSurface);
@@ -209,11 +197,24 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
free(_mouseData);
}
-void SurfaceSdlGraphicsManager::initEventObserver() {
+void SurfaceSdlGraphicsManager::activateManager() {
+ GraphicsManager::activateManager();
+ initEventSource();
+
// Register the graphics manager as a event observer
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
}
+void SurfaceSdlGraphicsManager::deactivateManager() {
+ // Unregister the event observer
+ if (g_system->getEventManager()->getEventDispatcher()) {
+ g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
+ }
+
+ deinitEventSource();
+ GraphicsManager::deactivateManager();
+}
+
bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) {
return
(f == OSystem::kFeatureFullscreenMode) ||
@@ -261,10 +262,6 @@ bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
}
}
-const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::supportedGraphicsModes() {
- return s_supportedGraphicsModes;
-}
-
const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const {
return s_supportedGraphicsModes;
}
@@ -765,9 +762,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 +1196,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;
@@ -1293,15 +1303,13 @@ Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() {
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- _framebuffer.pixels = _screen->pixels;
- _framebuffer.w = _screen->w;
- _framebuffer.h = _screen->h;
- _framebuffer.pitch = _screen->pitch;
+ _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels,
#ifdef USE_RGB_COLOR
- _framebuffer.format = _screenFormat;
+ _screenFormat
#else
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
+ Graphics::PixelFormat::createFormatCLUT8()
#endif
+ );
return &_framebuffer;
}
@@ -1325,8 +1333,8 @@ void SurfaceSdlGraphicsManager::unlockScreen() {
void SurfaceSdlGraphicsManager::fillScreen(uint32 col) {
Graphics::Surface *screen = lockScreen();
- if (screen && screen->pixels)
- memset(screen->pixels, col, screen->h * screen->pitch);
+ if (screen && screen->getPixels())
+ memset(screen->getPixels(), col, screen->h * screen->pitch);
unlockScreen();
}
@@ -2047,15 +2055,12 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
Graphics::Surface dst;
- dst.pixels = _osdSurface->pixels;
- dst.w = _osdSurface->w;
- dst.h = _osdSurface->h;
- dst.pitch = _osdSurface->pitch;
- dst.format = Graphics::PixelFormat(_osdSurface->format->BytesPerPixel,
- 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss,
- 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss,
- _osdSurface->format->Rshift, _osdSurface->format->Gshift,
- _osdSurface->format->Bshift, _osdSurface->format->Ashift);
+ dst.init(_osdSurface->w, _osdSurface->h, _osdSurface->pitch, _osdSurface->pixels,
+ Graphics::PixelFormat(_osdSurface->format->BytesPerPixel,
+ 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss,
+ 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss,
+ _osdSurface->format->Rshift, _osdSurface->format->Gshift,
+ _osdSurface->format->Bshift, _osdSurface->format->Ashift));
// The font we are going to use:
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 21444cc25d..00c05ff2bf 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -80,13 +80,13 @@ public:
SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource);
virtual ~SurfaceSdlGraphicsManager();
- virtual void initEventObserver();
+ virtual void activateManager();
+ virtual void deactivateManager();
virtual bool hasFeature(OSystem::Feature f);
virtual void setFeatureState(OSystem::Feature f, bool enable);
virtual bool getFeatureState(OSystem::Feature f);
- static const OSystem::GraphicsMode *supportedGraphicsModes();
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
virtual int getDefaultGraphicsMode() const;
virtual bool setGraphicsMode(int mode);
@@ -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/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 1e8d1c08c3..a54a2acbdc 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -128,7 +128,7 @@ public:
* @param name name of the keymap to push
* @param transparent if true keymapper will iterate down the
* stack if it cannot find a key in the new map
- * @return true if succesful
+ * @return true if successful
*/
bool pushKeymap(const String& name, bool transparent = false);
diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp
index 5cefe668cd..d2c60bec9d 100644
--- a/backends/midi/timidity.cpp
+++ b/backends/midi/timidity.cpp
@@ -148,7 +148,7 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
int MidiDriver_TIMIDITY::open() {
char *res;
- char timidity_host[MAXHOSTNAMELEN];
+ char timidity_host[NI_MAXHOST];
int timidity_port, data_port, i;
/* count ourselves open */
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..1222d9a363 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -40,14 +40,6 @@ MODULE_OBJS += \
keymapper/remap-dialog.o
endif
-ifdef USE_OPENGL
-MODULE_OBJS += \
- graphics/opengl/glerrorcheck.o \
- graphics/opengl/gltexture.o \
- graphics/opengl/opengl-graphics.o \
- graphics/openglsdl/openglsdl-graphics.o
-endif
-
ifdef ENABLE_VKEYBD
MODULE_OBJS += \
vkeybd/image-map.o \
@@ -57,6 +49,15 @@ MODULE_OBJS += \
vkeybd/virtual-keyboard-parser.o
endif
+# OpenGL specific source files.
+ifdef USE_OPENGL
+MODULE_OBJS += \
+ graphics/opengl/debug.o \
+ graphics/opengl/extensions.o \
+ graphics/opengl/opengl-graphics.o \
+ graphics/opengl/texture.o
+endif
+
# SDL specific source files.
# We cannot just check $BACKEND = sdl, as various other backends
# derive from the SDL backend, and they all need the following files.
@@ -70,12 +71,17 @@ 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 += \
audiocd/sdl/sdl-audiocd.o
endif
+
+ifdef USE_OPENGL
+MODULE_OBJS += \
+ graphics/openglsdl/openglsdl-graphics.o
+endif
endif
ifdef POSIX
@@ -120,9 +126,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 +220,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..5e3d1d0db6 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -146,7 +146,8 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
_touchpad_scale(66),
_dpad_scale(4),
_fingersDown(0),
- _trackball_scale(2) {
+ _trackball_scale(2),
+ _joystick_scale(10) {
_fsFactory = new POSIXFilesystemFactory();
@@ -450,7 +451,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..704ce12f60 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -231,6 +231,7 @@ private:
int _touchpad_scale;
int _trackball_scale;
int _dpad_scale;
+ int _joystick_scale;
int _fingersDown;
void clipMouse(Common::Point &p);
@@ -274,7 +275,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/android/android.mk b/backends/platform/android/android.mk
index f498c671de..915bf8ac60 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -25,13 +25,19 @@ PATH_RESOURCES = $(PATH_DIST)/res
PORT_DISTFILES = $(PATH_DIST)/README.Android
+# FIXME: OUYA specific.
+# "values-television" not present in vanilla Android.
+# $(PATH_RESOURCES)/../res-ouya/values-television/margins.xml \
+
RESOURCES = \
$(PATH_RESOURCES)/values/strings.xml \
+ $(PATH_RESOURCES)/values/margins.xml \
$(PATH_RESOURCES)/layout/main.xml \
$(PATH_RESOURCES)/layout/splash.xml \
$(PATH_RESOURCES)/drawable/gradient.xml \
$(PATH_RESOURCES)/drawable/scummvm.png \
- $(PATH_RESOURCES)/drawable/scummvm_big.png
+ $(PATH_RESOURCES)/drawable/scummvm_big.png \
+ $(PATH_RESOURCES)/drawable-xhdpi/ouya_icon.png
PLUGIN_RESOURCES = \
$(PATH_RESOURCES)/values/strings.xml \
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index db1261e432..5c42db9347 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -64,6 +64,10 @@ enum {
JE_RMB_DOWN = 11,
JE_RMB_UP = 12,
JE_MOUSE_MOVE = 13,
+ JE_GAMEPAD = 14,
+ JE_JOYSTICK = 15,
+ JE_MMB_DOWN = 16,
+ JE_MMB_UP = 17,
JE_QUIT = 0x1000
};
@@ -109,6 +113,25 @@ enum {
JKEYCODE_DPAD_CENTER = 23
};
+// gamepad
+enum {
+ JKEYCODE_BUTTON_A = 96,
+ JKEYCODE_BUTTON_B = 97,
+ JKEYCODE_BUTTON_C = 98,
+ JKEYCODE_BUTTON_X = 99,
+ JKEYCODE_BUTTON_Y = 100,
+ JKEYCODE_BUTTON_Z = 101,
+ JKEYCODE_BUTTON_L1 = 102,
+ JKEYCODE_BUTTON_R1 = 103,
+ JKEYCODE_BUTTON_L2 = 104,
+ JKEYCODE_BUTTON_R2 = 105,
+ JKEYCODE_BUTTON_THUMBL = 106,
+ JKEYCODE_BUTTON_THUMBR = 107,
+ JKEYCODE_BUTTON_START = 108,
+ JKEYCODE_BUTTON_SELECT = 109,
+ JKEYCODE_BUTTON_MODE = 110,
+};
+
// meta modifier
enum {
JMETA_SHIFT = 0x01,
@@ -827,6 +850,94 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
return;
+ case JE_GAMEPAD:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_KEYUP;
+ break;
+ default:
+ LOGE("unhandled jaction on gamepad key: %d", arg1);
+ return;
+ }
+
+ switch (arg2) {
+ case JKEYCODE_BUTTON_A:
+ case JKEYCODE_BUTTON_B:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = (arg2 == JKEYCODE_BUTTON_A?
+ Common::EVENT_LBUTTONDOWN :
+ Common::EVENT_RBUTTONDOWN);
+ break;
+ case JACTION_UP:
+ e.type = (arg2 == JKEYCODE_BUTTON_A?
+ Common::EVENT_LBUTTONUP :
+ Common::EVENT_RBUTTONUP);
+ break;
+ }
+
+ e.mouse = getEventManager()->getMousePos();
+
+ break;
+
+ case JKEYCODE_BUTTON_X:
+ e.kbd.keycode = Common::KEYCODE_ESCAPE;
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+ break;
+
+ default:
+ LOGW("unmapped gamepad key: %d", arg2);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ break;
+
+ case JE_JOYSTICK:
+ e.mouse = getEventManager()->getMousePos();
+
+ switch (arg1) {
+ case JACTION_MULTIPLE:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ // already multiplied by 100
+ e.mouse.x += arg2 * _joystick_scale / _eventScaleX;
+ e.mouse.y += arg3 * _joystick_scale / _eventScaleY;
+
+ clipMouse(e.mouse);
+
+ break;
+ default:
+ LOGE("unhandled jaction on joystick: %d", arg1);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_MMB_DOWN:
+ e.type = Common::EVENT_MAINMENU;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_MMB_UP:
+ // No action
+
+ return;
+
case JE_QUIT:
e.type = Common::EVENT_QUIT;
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index cd0fd88484..882dcff9a4 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -552,7 +552,7 @@ Graphics::Surface *OSystem_Android::lockScreen() {
GLTHREADCHECK;
Graphics::Surface *surface = _game_texture->surface();
- assert(surface->pixels);
+ assert(surface->getPixels());
return surface;
}
@@ -645,7 +645,7 @@ void OSystem_Android::grabOverlay(void *buf, int pitch) {
assert(surface->format.bytesPerPixel == sizeof(uint16));
byte *dst = (byte *)buf;
- const byte *src = (const byte *)surface->pixels;
+ const byte *src = (const byte *)surface->getPixels();
uint h = surface->h;
do {
diff --git a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java
index 999815593f..8990515b84 100644
--- a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java
+++ b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java
@@ -14,6 +14,7 @@ public class MouseHelper {
private long _rmbGuardTime;
private boolean _rmbPressed;
private boolean _lmbPressed;
+ private boolean _mmbPressed;
/**
* Class initialization fails when this throws an exception.
@@ -114,6 +115,23 @@ public class MouseHelper {
_rmbPressed = false;
}
+ boolean mmbDown = (buttonState & MotionEvent.BUTTON_TERTIARY) == MotionEvent.BUTTON_TERTIARY;
+ if (mmbDown) {
+ if (!_mmbPressed) {
+ // middle mouse button was pressed just now
+ _scummvm.pushEvent(ScummVMEvents.JE_MMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ }
+
+ _mmbPressed = true;
+ } else {
+ if (_mmbPressed) {
+ // middle mouse button was released just now
+ _scummvm.pushEvent(ScummVMEvents.JE_MMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ }
+
+ _mmbPressed = false;
+ }
+
return true;
}
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 829a948435..5d041dafd2 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -240,6 +240,14 @@ public class ScummVMActivity extends Activity {
return false;
}
+ @Override
+ public boolean onGenericMotionEvent(final MotionEvent e) {
+ if (_events != null)
+ return _events.onGenericMotionEvent(e);
+
+ return false;
+ }
+
private void showKeyboard(boolean show) {
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
InputMethodManager imm = (InputMethodManager)
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
index 5f51ffac6c..702215341b 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
@@ -9,6 +9,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.GestureDetector;
+import android.view.InputDevice;
import android.view.inputmethod.InputMethodManager;
public class ScummVMEvents implements
@@ -31,6 +32,10 @@ public class ScummVMEvents implements
public static final int JE_RMB_DOWN = 11;
public static final int JE_RMB_UP = 12;
public static final int JE_MOUSE_MOVE = 13;
+ public static final int JE_GAMEPAD = 14;
+ public static final int JE_JOYSTICK = 15;
+ public static final int JE_MMB_DOWN = 16;
+ public static final int JE_MMB_UP = 17;
public static final int JE_QUIT = 0x1000;
final protected Context _context;
@@ -63,6 +68,18 @@ public class ScummVMEvents implements
return true;
}
+ public boolean onGenericMotionEvent(final MotionEvent e) {
+ if((e.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
+ _scummvm.pushEvent(JE_JOYSTICK, e.getAction(),
+ (int)(e.getAxisValue(MotionEvent.AXIS_X)*100),
+ (int)(e.getAxisValue(MotionEvent.AXIS_Y)*100),
+ 0, 0);
+ return true;
+ }
+
+ return false;
+ }
+
final static int MSG_MENU_LONG_PRESS = 1;
final private Handler keyHandler = new Handler() {
@@ -177,6 +194,25 @@ public class ScummVMEvents implements
(int)(e.getEventTime() - e.getDownTime()),
e.getRepeatCount(), 0);
return true;
+ case KeyEvent.KEYCODE_BUTTON_A:
+ case KeyEvent.KEYCODE_BUTTON_B:
+ case KeyEvent.KEYCODE_BUTTON_C:
+ case KeyEvent.KEYCODE_BUTTON_X:
+ case KeyEvent.KEYCODE_BUTTON_Y:
+ case KeyEvent.KEYCODE_BUTTON_Z:
+ case KeyEvent.KEYCODE_BUTTON_L1:
+ case KeyEvent.KEYCODE_BUTTON_R1:
+ case KeyEvent.KEYCODE_BUTTON_L2:
+ case KeyEvent.KEYCODE_BUTTON_R2:
+ case KeyEvent.KEYCODE_BUTTON_THUMBL:
+ case KeyEvent.KEYCODE_BUTTON_THUMBR:
+ case KeyEvent.KEYCODE_BUTTON_START:
+ case KeyEvent.KEYCODE_BUTTON_SELECT:
+ case KeyEvent.KEYCODE_BUTTON_MODE:
+ _scummvm.pushEvent(JE_GAMEPAD, action, keyCode,
+ (int)(e.getEventTime() - e.getDownTime()),
+ e.getRepeatCount(), 0);
+ return true;
}
_scummvm.pushEvent(JE_KEY, action, keyCode,
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
index b174e93191..cc41c0d8a6 100644
--- a/backends/platform/android/texture.cpp
+++ b/backends/platform/android/texture.cpp
@@ -233,7 +233,7 @@ void GLESTexture::allocBuffer(GLuint w, GLuint h) {
_pixels = new byte[w * h * _surface.format.bytesPerPixel];
assert(_pixels);
- _surface.pixels = _pixels;
+ _surface.setPixels(_pixels);
fillBuffer(0);
@@ -256,7 +256,7 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
}
void GLESTexture::fillBuffer(uint32 color) {
- assert(_surface.pixels);
+ assert(_surface.getPixels());
if (_pixelFormat.bytesPerPixel == 1 ||
((color & 0xff) == ((color >> 8) & 0xff)))
@@ -377,7 +377,7 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
assert(_pixels);
// fixup surface, for the outside this is a CLUT8 surface
- _surface.pixels = _pixels;
+ _surface.setPixels(_pixels);
fillBuffer(0);
@@ -386,8 +386,8 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
}
void GLESFakePaletteTexture::fillBuffer(uint32 color) {
- assert(_surface.pixels);
- memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h);
+ assert(_surface.getPixels());
+ memset(_surface.getPixels(), color & 0xff, _surface.pitch * _surface.h);
setDirty();
}
diff --git a/backends/platform/bada/application.cpp b/backends/platform/bada/application.cpp
deleted file mode 100644
index e761649245..0000000000
--- a/backends/platform/bada/application.cpp
+++ /dev/null
@@ -1,111 +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 "engines/engine.h"
-
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/application.h"
-
-using namespace Osp::System;
-using namespace Osp::Ui::Controls;
-
-Application *BadaScummVM::createInstance() {
- return new BadaScummVM();
-}
-
-BadaScummVM::BadaScummVM() : _appForm(0) {
-}
-
-BadaScummVM::~BadaScummVM() {
- logEntered();
- if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
- system->destroyBackend();
- delete system;
- g_system = 0;
- }
-}
-
-bool BadaScummVM::OnAppInitializing(AppRegistry &appRegistry) {
- _appForm = systemStart(this);
- return (_appForm != NULL);
-}
-
-bool BadaScummVM::OnAppTerminating(AppRegistry &appRegistry,
- bool forcedTermination) {
- logEntered();
- return true;
-}
-
-void BadaScummVM::OnUserEventReceivedN(RequestId requestId,
- Osp::Base::Collection::IList *args) {
- logEntered();
-
- if (requestId == USER_MESSAGE_EXIT) {
- // normal program termination
- Terminate();
- } else if (requestId == USER_MESSAGE_EXIT_ERR) {
- // assertion failure termination
- String *message = NULL;
- if (args) {
- message = (String *)args->GetAt(0);
- }
- if (!message) {
- message = new String("Unknown error");
- }
-
- MessageBox messageBox;
- messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK);
- int modalResult;
- messageBox.ShowAndWait(modalResult);
- Terminate();
- }
-}
-
-void BadaScummVM::OnForeground(void) {
- logEntered();
- pauseGame(false);
-}
-
-void BadaScummVM::OnBackground(void) {
- logEntered();
- pauseGame(true);
-}
-
-void BadaScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
-}
-
-void BadaScummVM::OnLowMemory(void) {
-}
-
-void BadaScummVM::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);
- }
- }
-}
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/display.cpp b/backends/platform/dc/display.cpp
index cc5798fc10..54ee6000ed 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -711,11 +711,7 @@ Graphics::Surface *OSystem_Dreamcast::lockScreen()
if (!screen)
return 0;
- _framebuffer.pixels = screen;
- _framebuffer.w = _screen_w;
- _framebuffer.h = _screen_h;
- _framebuffer.pitch = SCREEN_W*2;
- _framebuffer.format = screenFormats[_screenFormat];
+ _framebuffer.init(_screen_w, _screen_h, SCREEN_W*2, screen, screenFormats[_screenFormat]);
return &_framebuffer;
}
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 339e5df62d..4026c7dde6 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -219,7 +219,7 @@ static int findGames(Game *games, int max, bool use_ini)
if (use_ini) {
ConfMan.loadDefaultConfigFile();
- Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains();
+ const Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains();
for(Common::ConfigManager::DomainMap::const_iterator i =
game_domains.begin(); curr_game < max && i != game_domains.end(); i++) {
Common::String path = (*i)._value["path"];
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..f109983fbc 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -296,7 +296,7 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int
// to save a few pennies/euro cents on the hardware.
if (_frameBufferExists) {
- bg = (u16 *)_framebuffer.pixels;
+ bg = (u16 *)_framebuffer.getPixels();
stride = _framebuffer.pitch;
} else {
bg = (u16 *)DS::get8BitBackBuffer();
@@ -455,7 +455,7 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int
dmaCopyHalfWords(3, src, dest1, w);
- if ((!_frameBufferExists) || (buf == _framebuffer.pixels)) {
+ if ((!_frameBufferExists) || (buf == _framebuffer.getPixels())) {
dmaCopyHalfWords(2, src, dest2, w);
}
@@ -476,7 +476,7 @@ void OSystem_DS::updateScreen() {
_frameBufferExists = false;
// Copy temp framebuffer back to screen
- copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h);
+ copyRectToScreen((byte *)_framebuffer.getPixels(), _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h);
}
DS::displayMode16BitFlipBuffer();
@@ -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();
}
@@ -755,11 +755,8 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() {
if (DS::isCpuScalerEnabled()) {
- _framebuffer.pixels = DS::getScalerBuffer();
- _framebuffer.w = DS::getGameWidth();
- _framebuffer.h = DS::getGameHeight();
- _framebuffer.pitch = DS::getGameWidth();
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
+ _framebuffer.init(DS::getGameWidth(), DS::getGameHeight(), DS::getGameWidth(),
+ DS::getScalerBuffer(), Graphics::PixelFormat::createFormatCLUT8());
} else {
@@ -780,11 +777,7 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() {
dmaCopyHalfWords(3, srcLine, destLine, width);
}
- _framebuffer.pixels = dest;
- _framebuffer.w = width;
- _framebuffer.h = height;
- _framebuffer.pitch = width;
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
+ _framebuffer.init(width, height, width, dest, Graphics::PixelFormat::createFormatCLUT8());
}
@@ -798,8 +791,8 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() {
for (int y = 0; y < DS::getGameHeight(); y++) {
DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++) {
- *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[(y * imageStrideInWords) + x];
-// *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x];
+ *(((u16 *) (_framebuffer.getPixels())) + y * (DS::getGameWidth() >> 1) + x) = image[(y * imageStrideInWords) + x];
+// *(((u16 *) (surf->getPixels())) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x];
}
}*/
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/gph/gph-backend.cpp b/backends/platform/gph/gph-backend.cpp
index 485780b472..e51d7d0781 100644
--- a/backends/platform/gph/gph-backend.cpp
+++ b/backends/platform/gph/gph-backend.cpp
@@ -172,7 +172,7 @@ void OSystem_GPH::initSDL() {
// Check if SDL has not been initialized
if (!_initedSDL) {
- uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO;
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm
index 0bfae30fc7..f2c1527658 100644
--- a/backends/platform/iphone/iphone_video.mm
+++ b/backends/platform/iphone/iphone_video.mm
@@ -365,7 +365,7 @@ const char *iPhone_getDocumentsDir() {
_mouseTexCoords[5] = _mouseTexCoords[7] = _videoContext.mouseHeight / (GLfloat)_videoContext.mouseTexture.h;
glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.pixels); printOpenGLError();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.getPixels()); printOpenGLError();
}
- (void)updateMainSurface {
@@ -377,7 +377,7 @@ const char *iPhone_getDocumentsDir() {
// Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases
// due to the iPhone internals having to convert the whole texture back from its internal format when used.
// In the future we could use several tiled textures instead.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.pixels); printOpenGLError();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.getPixels()); printOpenGLError();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
}
@@ -386,7 +386,7 @@ const char *iPhone_getDocumentsDir() {
glTexCoordPointer(2, GL_FLOAT, 0, _overlayTexCoords); printOpenGLError();
glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.pixels); printOpenGLError();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.getPixels()); printOpenGLError();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
}
diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp
index ed2c886213..a814495b80 100644
--- a/backends/platform/iphone/osys_main.cpp
+++ b/backends/platform/iphone/osys_main.cpp
@@ -77,8 +77,8 @@ OSystem_IPHONE::~OSystem_IPHONE() {
delete _mixer;
// Prevent accidental freeing of the screen texture here. This needs to be
// checked since we might use the screen texture as framebuffer in the case
- // of hi-color games for example.
- if (_framebuffer.pixels == _videoContext->screenTexture.pixels)
+ // of hi-color games for example. Otherwise this can lead to a double free.
+ if (_framebuffer.getPixels() != _videoContext->screenTexture.getPixels())
_framebuffer.free();
_mouseBuffer.free();
}
@@ -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/iphone/osys_video.mm b/backends/platform/iphone/osys_video.mm
index a11bf32c54..ce7f94f5bd 100644
--- a/backends/platform/iphone/osys_video.mm
+++ b/backends/platform/iphone/osys_video.mm
@@ -76,8 +76,8 @@ void OSystem_IPHONE::initSize(uint width, uint height, const Graphics::PixelForm
// In case we use the screen texture as frame buffer we reset the pixels
// pointer here to avoid freeing the screen texture.
- if (_framebuffer.pixels == _videoContext->screenTexture.pixels)
- _framebuffer.pixels = 0;
+ if (_framebuffer.getPixels() == _videoContext->screenTexture.getPixels())
+ _framebuffer.setPixels(0);
// Create the screen texture right here. We need to do this here, since
// when a game requests hi-color mode, we actually set the framebuffer
@@ -310,7 +310,7 @@ void OSystem_IPHONE::hideOverlay() {
void OSystem_IPHONE::clearOverlay() {
//printf("clearOverlay()\n");
- bzero(_videoContext->overlayTexture.getBasePtr(0, 0), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch);
+ bzero(_videoContext->overlayTexture.getPixels(), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch);
dirtyFullOverlayScreen();
}
@@ -319,7 +319,7 @@ void OSystem_IPHONE::grabOverlay(void *buf, int pitch) {
int h = _videoContext->overlayHeight;
byte *dst = (byte *)buf;
- const byte *src = (const byte *)_videoContext->overlayTexture.getBasePtr(0, 0);
+ const byte *src = (const byte *)_videoContext->overlayTexture.getPixels();
do {
memcpy(dst, src, _videoContext->overlayWidth * sizeof(uint16));
src += _videoContext->overlayTexture.pitch;
@@ -417,7 +417,7 @@ void OSystem_IPHONE::setMouseCursor(const void *buf, uint w, uint h, int hotspot
#endif
assert(pixelFormat.bytesPerPixel == 1 || pixelFormat.bytesPerPixel == 2);
- if (_mouseBuffer.w != w || _mouseBuffer.h != h || _mouseBuffer.format != pixelFormat || !_mouseBuffer.pixels)
+ if (_mouseBuffer.w != w || _mouseBuffer.h != h || _mouseBuffer.format != pixelFormat || !_mouseBuffer.getPixels())
_mouseBuffer.create(w, h, pixelFormat);
_videoContext->mouseWidth = w;
@@ -428,7 +428,7 @@ void OSystem_IPHONE::setMouseCursor(const void *buf, uint w, uint h, int hotspot
_mouseKeyColor = keycolor;
- memcpy(_mouseBuffer.getBasePtr(0, 0), buf, h * _mouseBuffer.pitch);
+ memcpy(_mouseBuffer.getPixels(), buf, h * _mouseBuffer.pitch);
_mouseDirty = true;
_mouseNeedTextureUpdate = true;
@@ -464,7 +464,7 @@ void OSystem_IPHONE::updateMouseTexture() {
else
palette = _gamePaletteRGBA5551;
- uint16 *mouseBuf = (uint16 *)mouseTexture.getBasePtr(0, 0);
+ uint16 *mouseBuf = (uint16 *)mouseTexture.getPixels();
for (uint x = 0; x < _videoContext->mouseWidth; ++x) {
for (uint y = 0; y < _videoContext->mouseHeight; ++y) {
const byte color = *(const byte *)_mouseBuffer.getBasePtr(x, y);
@@ -475,12 +475,12 @@ void OSystem_IPHONE::updateMouseTexture() {
}
}
} else {
- if (crossBlit((byte *)mouseTexture.getBasePtr(0, 0), (const byte *)_mouseBuffer.getBasePtr(0, 0), mouseTexture.pitch,
+ if (crossBlit((byte *)mouseTexture.getPixels(), (const byte *)_mouseBuffer.getPixels(), mouseTexture.pitch,
_mouseBuffer.pitch, _mouseBuffer.w, _mouseBuffer.h, mouseTexture.format, _mouseBuffer.format)) {
if (!_mouseBuffer.format.aBits()) {
// Apply color keying since the original cursor had no alpha channel.
- const uint16 *src = (const uint16 *)_mouseBuffer.getBasePtr(0, 0);
- uint8 *dstRaw = (uint8 *)mouseTexture.getBasePtr(0, 0);
+ const uint16 *src = (const uint16 *)_mouseBuffer.getPixels();
+ uint8 *dstRaw = (uint8 *)mouseTexture.getPixels();
for (uint y = 0; y < _mouseBuffer.h; ++y, dstRaw += mouseTexture.pitch) {
uint16 *dst = (uint16 *)dstRaw;
@@ -495,7 +495,7 @@ void OSystem_IPHONE::updateMouseTexture() {
} else {
// TODO: Log this!
// Make the cursor all transparent... we really need a better fallback ;-).
- memset(mouseTexture.getBasePtr(0, 0), 0, mouseTexture.h * mouseTexture.pitch);
+ memset(mouseTexture.getPixels(), 0, mouseTexture.h * mouseTexture.pitch);
}
}
diff --git a/backends/platform/maemo/debian/changelog b/backends/platform/maemo/debian/changelog
index ea44574e96..568edd0282 100644
--- a/backends/platform/maemo/debian/changelog
+++ b/backends/platform/maemo/debian/changelog
@@ -1,8 +1,14 @@
-scummvm (1.6.0~git) unstable; urgency=low
+scummvm (1.7.0~git) unstable; urgency=low
* Development snapshot
- -- Tarek Soliman <tsoliman@scummvm.org> Tue, 10 Jul 2012 23:02:00 -0500
+ -- Tarek Soliman <tsoliman@scummvm.org> Sat, 01 Jun 2013 21:03:52 -0500
+
+scummvm (1.6.0) unstable; urgency=low
+
+ * 1.6.0 release
+
+ -- Tarek Soliman <tsoliman@scummvm.org> Fri, 31 May 2013 23:02:00 -0500
scummvm (1.5.0) unstable; urgency=low
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..36e5085764 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -605,11 +605,7 @@ void OSystem_N64::updateScreen() {
}
Graphics::Surface *OSystem_N64::lockScreen() {
- _framebuffer.pixels = _offscreen_pal;
- _framebuffer.w = _gameWidth;
- _framebuffer.h = _gameHeight;
- _framebuffer.pitch = _screenWidth;
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
+ _framebuffer.init(_gameWidth, _gameHeight, _screenWidth, _offscreen_pal, Graphics::PixelFormat::createFormatCLUT8());
return &_framebuffer;
}
@@ -810,7 +806,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/openpandora/op-backend.cpp b/backends/platform/openpandora/op-backend.cpp
index 354aa24b24..60c3cc7191 100644
--- a/backends/platform/openpandora/op-backend.cpp
+++ b/backends/platform/openpandora/op-backend.cpp
@@ -160,7 +160,7 @@ void OSystem_OP::initSDL() {
// Check if SDL has not been initialized
if (!_initedSDL) {
- uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO;
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp
index e818305c29..58667c0230 100644
--- a/backends/platform/ps2/Gs2dScreen.cpp
+++ b/backends/platform/ps2/Gs2dScreen.cpp
@@ -392,12 +392,8 @@ void Gs2dScreen::copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w
Graphics::Surface *Gs2dScreen::lockScreen() {
WaitSema(g_DmacSema);
- _framebuffer.pixels = _screenBuf;
- _framebuffer.w = _width;
- _framebuffer.h = _height;
- _framebuffer.pitch = _width; // -not- _pitch; ! It's EE mem, not Tex
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
-
+ // -not- _pitch; ! It's EE mem, not Tex
+ _framebuffer.init(_width, _height, _width, _screenBuf, Graphics::PixelFormat::createFormatCLUT8());
return &_framebuffer;
}
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/audio.cpp b/backends/platform/psp/audio.cpp
index 4fab9fdd3f..dcbf0b2239 100644
--- a/backends/platform/psp/audio.cpp
+++ b/backends/platform/psp/audio.cpp
@@ -100,8 +100,6 @@ void PspAudio::threadFunction() {
PSP_DEBUG_PRINT("audio thread unpaused\n");
}
- PSP_DEBUG_PRINT("remaining samples[%d]\n", _remainingSamples);
-
PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill);
_callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data
nextBuffer(_bufferToFill);
diff --git a/backends/platform/psp/default_display_client.cpp b/backends/platform/psp/default_display_client.cpp
index bc252144fa..6d6eb641f7 100644
--- a/backends/platform/psp/default_display_client.cpp
+++ b/backends/platform/psp/default_display_client.cpp
@@ -192,11 +192,8 @@ void Screen::setScummvmPixelFormat(const Graphics::PixelFormat *format) {
Graphics::Surface *Screen::lockAndGetForEditing() {
DEBUG_ENTER_FUNC();
- _frameBuffer.pixels = _buffer.getPixels();
- _frameBuffer.w = _buffer.getSourceWidth();
- _frameBuffer.h = _buffer.getSourceHeight();
- _frameBuffer.pitch = _buffer.getBytesPerPixel() * _buffer.getWidth();
- _frameBuffer.format = _pixelFormat;
+ _frameBuffer.init(_buffer.getSourceWidth(), _buffer.getSourceHeight(), _buffer.getBytesPerPixel() * _buffer.getWidth(),
+ _buffer.getPixels(), _pixelFormat);
// We'll set to dirty once we unlock the screen
return &_frameBuffer;
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/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index 7a8b1e7b70..954f404ac6 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -80,15 +80,16 @@ bool OSystem_POSIX::hasFeature(Feature f) {
}
Common::String OSystem_POSIX::getDefaultConfigFileName() {
- char configFile[MAXPATHLEN];
+ Common::String configFile;
// On POSIX type systems, by default we store the config file inside
// to the HOME directory of the user.
const char *home = getenv("HOME");
- if (home != NULL && strlen(home) < MAXPATHLEN)
- snprintf(configFile, MAXPATHLEN, "%s/%s", home, _baseConfigName.c_str());
- else
- strcpy(configFile, _baseConfigName.c_str());
+ if (home != NULL && (strlen(home) + 1 + _baseConfigName.size()) < MAXPATHLEN) {
+ configFile = Common::String::format("%s/%s", home, _baseConfigName.c_str());
+ } else {
+ configFile = _baseConfigName;
+ }
return configFile;
}
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..178eeb96af 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"
@@ -65,10 +65,13 @@
OSystem_SDL::OSystem_SDL()
:
#ifdef USE_OPENGL
- _graphicsModes(0),
+ _desktopWidth(0),
+ _desktopHeight(0),
+ _graphicsModes(),
_graphicsMode(0),
- _sdlModesCount(0),
- _glModesCount(0),
+ _firstGLMode(0),
+ _defaultSDLMode(0),
+ _defaultGLMode(0),
#endif
_inited(false),
_initedSDL(false),
@@ -87,6 +90,9 @@ OSystem_SDL::~OSystem_SDL() {
// Hence, we perform the destruction on our own.
delete _savefileManager;
_savefileManager = 0;
+ if (_graphicsManager) {
+ _graphicsManager->deactivateManager();
+ }
delete _graphicsManager;
_graphicsManager = 0;
delete _eventManager;
@@ -97,15 +103,19 @@ 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;
-#ifdef USE_OPENGL
- delete[] _graphicsModes;
-#endif
-
delete _logger;
_logger = 0;
@@ -116,6 +126,12 @@ void OSystem_SDL::init() {
// Initialize SDL
initSDL();
+ // Enable unicode support if possible
+ SDL_EnableUNICODE(1);
+
+ // Disable OS cursor
+ SDL_ShowCursor(SDL_DISABLE);
+
if (!_logger)
_logger = new Backends::Log::Log(this);
@@ -131,18 +147,11 @@ 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();
#endif
-#ifdef USE_OPENGL
- // Setup a list with both SDL and OpenGL graphics modes
- setupGraphicsModes();
-#endif
}
void OSystem_SDL::initBackend() {
@@ -154,35 +163,41 @@ void OSystem_SDL::initBackend() {
if (_eventSource == 0)
_eventSource = new SdlEventSource();
- int graphicsManagerType = 0;
+#ifdef USE_OPENGL
+ // Query the desktop resolution. We simply hope nothing tried to change
+ // the resolution so far.
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ if (videoInfo && videoInfo->current_w > 0 && videoInfo->current_h > 0) {
+ _desktopWidth = videoInfo->current_w;
+ _desktopHeight = videoInfo->current_h;
+ }
+#endif
if (_graphicsManager == 0) {
#ifdef USE_OPENGL
+ // Setup a list with both SDL and OpenGL graphics modes. We only do
+ // this whenever the subclass did not already set up an graphics
+ // manager yet. This is because we don't know the type of the graphics
+ // manager of the subclass, thus we cannot easily switch between the
+ // OpenGL one and the set up one. It also is to be expected that the
+ // subclass does not want any switching of graphics managers anyway.
+ setupGraphicsModes();
+
if (ConfMan.hasKey("gfx_mode")) {
+ // If the gfx_mode is from OpenGL, create the OpenGL graphics manager
Common::String gfxMode(ConfMan.get("gfx_mode"));
- bool use_opengl = false;
- const OSystem::GraphicsMode *mode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
- int i = 0;
- while (mode->name) {
- if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) {
- _graphicsMode = i + _sdlModesCount;
- use_opengl = true;
+ for (uint i = _firstGLMode; i < _graphicsModeIds.size(); ++i) {
+ if (!scumm_stricmp(_graphicsModes[i].name, gfxMode.c_str())) {
+ _graphicsManager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource);
+ _graphicsMode = i;
+ break;
}
-
- mode++;
- ++i;
- }
-
- // If the gfx_mode is from OpenGL, create the OpenGL graphics manager
- if (use_opengl) {
- _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource);
- graphicsManagerType = 1;
}
}
#endif
+
if (_graphicsManager == 0) {
_graphicsManager = new SurfaceSdlGraphicsManager(_eventSource);
- graphicsManagerType = 0;
}
}
@@ -191,11 +206,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)
@@ -217,13 +240,7 @@ void OSystem_SDL::initBackend() {
// so the virtual keyboard can be initialized, but we have to add the
// graphics manager as an event observer after initializing the event
// manager.
- if (graphicsManagerType == 0)
- ((SurfaceSdlGraphicsManager *)_graphicsManager)->initEventObserver();
-#ifdef USE_OPENGL
- else if (graphicsManagerType == 1)
- ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver();
-#endif
-
+ _graphicsManager->activateManager();
}
#if defined(USE_TASKBAR)
@@ -244,22 +261,19 @@ void OSystem_SDL::engineDone() {
void OSystem_SDL::initSDL() {
// Check if SDL has not been initialized
if (!_initedSDL) {
- uint32 sdlFlags = 0;
+ // We always initialize the video subsystem because we will need it to
+ // be initialized before the graphics managers to retrieve the desktop
+ // resolution, for example. WebOS also requires this initialization
+ // or otherwise the application won't start.
+ uint32 sdlFlags = SDL_INIT_VIDEO;
+
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
-#ifdef WEBOS
- // WebOS needs this flag or otherwise the application won't start
- sdlFlags |= SDL_INIT_VIDEO;
-#endif
-
// Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
if (SDL_Init(sdlFlags) == -1)
error("Could not initialize SDL: %s", SDL_GetError());
- // Enable unicode support if possible
- SDL_EnableUNICODE(1);
-
_initedSDL = true;
}
}
@@ -355,17 +369,6 @@ Common::String OSystem_SDL::getSystemLanguage() const {
const LCID languageIdentifier = GetThreadLocale();
- // GetLocalInfo is only supported starting from Windows 2000, according to this:
- // http://msdn.microsoft.com/en-us/library/dd318101%28VS.85%29.aspx
- // On the other hand the locale constants used, seem to exist on Windows 98 too,
- // check this for that: http://msdn.microsoft.com/en-us/library/dd464799%28v=VS.85%29.aspx
- //
- // I am not exactly sure what is the truth now, it might be very well that this breaks
- // support for systems older than Windows 2000....
- //
- // TODO: Check whether this (or ScummVM at all ;-) works on a system with Windows 98 for
- // example and if it does not and we still want Windows 9x support, we should definitly
- // think of another solution.
if (GetLocaleInfo(languageIdentifier, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 &&
GetLocaleInfo(languageIdentifier, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) {
Common::String localeName = langName;
@@ -378,10 +381,15 @@ Common::String OSystem_SDL::getSystemLanguage() const {
}
#else // WIN32
// Activating current locale settings
- const char *locale = setlocale(LC_ALL, "");
+ const Common::String locale = setlocale(LC_ALL, "");
+
+ // Restore default C locale to prevent issues with
+ // portability of sscanf(), atof(), etc.
+ // See bug #3615148
+ setlocale(LC_ALL, "C");
// Detect the language from the locale
- if (!locale) {
+ if (locale.empty()) {
return ModularBackend::getSystemLanguage();
} else {
int length = 0;
@@ -390,14 +398,14 @@ Common::String OSystem_SDL::getSystemLanguage() const {
// ".UTF-8" or the like. We do this, since
// our translation languages are usually
// specified without any charset information.
- for (int i = 0; locale[i]; ++i, ++length) {
+ for (int size = locale.size(); length < size; ++length) {
// TODO: Check whether "@" should really be checked
// here.
- if (locale[i] == '.' || locale[i] == ' ' || locale[i] == '@')
+ if (locale[length] == '.' || locale[length] == ' ' || locale[length] == '@')
break;
}
- return Common::String(locale, length);
+ return Common::String(locale.c_str(), length);
}
#endif // WIN32
#else // USE_DETECTLANG
@@ -466,14 +474,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,39 +506,57 @@ 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
const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
- return _graphicsModes;
+ if (_graphicsModes.empty()) {
+ return _graphicsManager->getSupportedGraphicsModes();
+ } else {
+ return _graphicsModes.begin();
+ }
}
int OSystem_SDL::getDefaultGraphicsMode() const {
- // Return the default graphics mode from the current graphics manager
- if (_graphicsMode < _sdlModesCount)
+ if (_graphicsModes.empty()) {
return _graphicsManager->getDefaultGraphicsMode();
- else
- return _graphicsManager->getDefaultGraphicsMode() + _sdlModesCount;
+ } else {
+ // Return the default graphics mode from the current graphics manager
+ if (_graphicsMode < _firstGLMode)
+ return _defaultSDLMode;
+ else
+ return _defaultGLMode;
+ }
}
bool OSystem_SDL::setGraphicsMode(int mode) {
- const OSystem::GraphicsMode *srcMode;
- int i;
+ if (_graphicsModes.empty()) {
+ return _graphicsManager->setGraphicsMode(mode);
+ }
- // Check if mode is from SDL or OpenGL
- if (mode < _sdlModesCount) {
- srcMode = SurfaceSdlGraphicsManager::supportedGraphicsModes();
- i = 0;
- } else {
- srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
- i = _sdlModesCount;
+ // Check whether a invalid mode is requested.
+ if (mode < 0 || (uint)mode >= _graphicsModeIds.size()) {
+ return false;
}
// Very hacky way to set up the old graphics manager state, in case we
@@ -542,113 +575,121 @@ bool OSystem_SDL::setGraphicsMode(int mode) {
bool switchedManager = false;
- // Loop through modes
- while (srcMode->name) {
- if (i == mode) {
- // If the new mode and the current mode are not from the same graphics
- // manager, delete and create the new mode graphics manager
- if (_graphicsMode >= _sdlModesCount && mode < _sdlModesCount) {
- debug(1, "switching to plain SDL graphics");
- delete _graphicsManager;
- _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource);
- ((SurfaceSdlGraphicsManager *)_graphicsManager)->initEventObserver();
- _graphicsManager->beginGFXTransaction();
-
- switchedManager = true;
- } else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) {
- debug(1, "switching to OpenGL graphics");
- delete _graphicsManager;
- _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource);
- ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver();
- _graphicsManager->beginGFXTransaction();
-
- switchedManager = true;
- }
+ // If the new mode and the current mode are not from the same graphics
+ // manager, delete and create the new mode graphics manager
+ if (_graphicsMode >= _firstGLMode && mode < _firstGLMode) {
+ debug(1, "switching to plain SDL graphics");
+ _graphicsManager->deactivateManager();
+ delete _graphicsManager;
+ _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource);
+
+ switchedManager = true;
+ } else if (_graphicsMode < _firstGLMode && mode >= _firstGLMode) {
+ debug(1, "switching to OpenGL graphics");
+ _graphicsManager->deactivateManager();
+ delete _graphicsManager;
+ _graphicsManager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource);
+
+ switchedManager = true;
+ }
+
+ _graphicsMode = mode;
- _graphicsMode = mode;
+ if (switchedManager) {
+ _graphicsManager->activateManager();
- if (switchedManager) {
+ _graphicsManager->beginGFXTransaction();
#ifdef USE_RGB_COLOR
- _graphicsManager->initSize(screenWidth, screenHeight, &pixelFormat);
+ _graphicsManager->initSize(screenWidth, screenHeight, &pixelFormat);
#else
- _graphicsManager->initSize(screenWidth, screenHeight, 0);
+ _graphicsManager->initSize(screenWidth, screenHeight, 0);
#endif
- _graphicsManager->setFeatureState(kFeatureAspectRatioCorrection, arState);
- _graphicsManager->setFeatureState(kFeatureFullscreenMode, fullscreen);
- _graphicsManager->setFeatureState(kFeatureCursorPalette, cursorPalette);
+ _graphicsManager->setFeatureState(kFeatureAspectRatioCorrection, arState);
+ _graphicsManager->setFeatureState(kFeatureFullscreenMode, fullscreen);
+ _graphicsManager->setFeatureState(kFeatureCursorPalette, cursorPalette);
- // Worst part about this right now, tell the cursor manager to
- // resetup the cursor + cursor palette if necessarily
+ // Worst part about this right now, tell the cursor manager to
+ // resetup the cursor + cursor palette if necessarily
- // First we need to try to setup the old state on the new manager...
- if (_graphicsManager->endGFXTransaction() != kTransactionSuccess) {
- // Oh my god if this failed the client code might just explode.
- return false;
- }
-
- // Next setup the cursor again
- CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
- CursorMan.popCursor();
+ // First we need to try to setup the old state on the new manager...
+ if (_graphicsManager->endGFXTransaction() != kTransactionSuccess) {
+ // Oh my god if this failed the client code might just explode.
+ return false;
+ }
- // Next setup cursor palette if needed
- if (cursorPalette) {
- CursorMan.pushCursorPalette(0, 0, 0);
- CursorMan.popCursorPalette();
- }
+ // Next setup the cursor again
+ CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
+ CursorMan.popCursor();
- _graphicsManager->beginGFXTransaction();
- // Oh my god if this failed the client code might just explode.
- return _graphicsManager->setGraphicsMode(srcMode->id);
- } else {
- return _graphicsManager->setGraphicsMode(srcMode->id);
- }
+ // Next setup cursor palette if needed
+ if (cursorPalette) {
+ CursorMan.pushCursorPalette(0, 0, 0);
+ CursorMan.popCursorPalette();
}
- i++;
- srcMode++;
+ _graphicsManager->beginGFXTransaction();
+ // Oh my god if this failed the client code might just explode.
+ return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]);
+ } else {
+ return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]);
}
-
- return false;
}
int OSystem_SDL::getGraphicsMode() const {
- return _graphicsMode;
+ if (_graphicsModes.empty()) {
+ return _graphicsManager->getGraphicsMode();
+ } else {
+ return _graphicsMode;
+ }
}
void OSystem_SDL::setupGraphicsModes() {
- const OSystem::GraphicsMode *sdlGraphicsModes = SurfaceSdlGraphicsManager::supportedGraphicsModes();
- const OSystem::GraphicsMode *openglGraphicsModes = OpenGLSdlGraphicsManager::supportedGraphicsModes();
- _sdlModesCount = 0;
- _glModesCount = 0;
+ _graphicsModes.clear();
+ _graphicsModeIds.clear();
+ _defaultSDLMode = _defaultGLMode = -1;
// Count the number of graphics modes
- const OSystem::GraphicsMode *srcMode = sdlGraphicsModes;
+ const OSystem::GraphicsMode *srcMode;
+ int defaultMode;
+
+ GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource);
+ srcMode = manager->getSupportedGraphicsModes();
+ defaultMode = manager->getDefaultGraphicsMode();
while (srcMode->name) {
- _sdlModesCount++;
+ if (defaultMode == srcMode->id) {
+ _defaultSDLMode = _graphicsModes.size();
+ }
+ _graphicsModes.push_back(*srcMode);
srcMode++;
}
- srcMode = openglGraphicsModes;
+ delete manager;
+ assert(_defaultSDLMode != -1);
+
+ _firstGLMode = _graphicsModes.size();
+ manager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource);
+ srcMode = manager->getSupportedGraphicsModes();
+ defaultMode = manager->getDefaultGraphicsMode();
while (srcMode->name) {
- _glModesCount++;
+ if (defaultMode == srcMode->id) {
+ _defaultGLMode = _graphicsModes.size();
+ }
+ _graphicsModes.push_back(*srcMode);
srcMode++;
}
-
- // Allocate enough space for merged array of modes
- _graphicsModes = new OSystem::GraphicsMode[_glModesCount + _sdlModesCount + 1];
-
- // Copy SDL graphics modes
- memcpy((void *)_graphicsModes, sdlGraphicsModes, _sdlModesCount * sizeof(OSystem::GraphicsMode));
-
- // Copy OpenGL graphics modes
- memcpy((void *)(_graphicsModes + _sdlModesCount), openglGraphicsModes, _glModesCount * sizeof(OSystem::GraphicsMode));
+ delete manager;
+ manager = nullptr;
+ assert(_defaultGLMode != -1);
// Set a null mode at the end
- memset((void *)(_graphicsModes + _sdlModesCount + _glModesCount), 0, sizeof(OSystem::GraphicsMode));
+ GraphicsMode nullMode;
+ memset(&nullMode, 0, sizeof(nullMode));
+ _graphicsModes.push_back(nullMode);
// Set new internal ids for all modes
int i = 0;
- OSystem::GraphicsMode *mode = _graphicsModes;
+ OSystem::GraphicsMode *mode = _graphicsModes.begin();
while (mode->name) {
+ _graphicsModeIds.push_back(mode->id);
mode->id = i++;
mode++;
}
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index f05207b482..814cdd7c1b 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -30,6 +30,8 @@
#include "backends/events/sdl/sdl-events.h"
#include "backends/log/log.h"
+#include "common/array.h"
+
/**
* Base OSystem class for all SDL ports.
*/
@@ -68,10 +70,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;
@@ -105,15 +108,20 @@ protected:
Backends::Log::Log *_logger;
#ifdef USE_OPENGL
- OSystem::GraphicsMode *_graphicsModes;
+ int _desktopWidth, _desktopHeight;
+
+ typedef Common::Array<GraphicsMode> GraphicsModeArray;
+ GraphicsModeArray _graphicsModes;
+ Common::Array<int> _graphicsModeIds;
int _graphicsMode;
- int _sdlModesCount;
- int _glModesCount;
+ int _firstGLMode;
+ int _defaultSDLMode;
+ int _defaultGLMode;
/**
* Creates the merged graphics modes list
*/
- virtual void setupGraphicsModes();
+ void setupGraphicsModes();
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
virtual int getDefaultGraphicsMode() const;
diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl
index ffc4e88aff..2f76acf012 100644
--- a/backends/platform/symbian/AdaptAllMMPs.pl
+++ b/backends/platform/symbian/AdaptAllMMPs.pl
@@ -44,6 +44,15 @@ chdir("../../../");
"mmp/scummvm_toltecs.mmp",
"mmp/scummvm_pegasus.mmp",
"mmp/scummvm_wintermute.mmp",
+ # New engines
+ "mmp/scummvm_avalanche.mmp",
+ "mmp/scummvm_dreamweb.mmp",
+ "mmp/scummvm_fullpipe.mmp",
+ "mmp/scummvm_mortevielle.mmp",
+ "mmp/scummvm_neverhood.mmp",
+ "mmp/scummvm_sword25.mmp",
+ "mmp/scummvm_testbed.mmp",
+ "mmp/scummvm_zvision.mmp",
# Target Platform Project Files
"S60/ScummVM_S60.mmp",
"S60v3/ScummVM_S60v3.mmp",
@@ -79,10 +88,14 @@ Preparing to update all the Symbian MMP project files with objects from module.m
# some modules.mk files have #ifndef ENABLE_XXXX blocks:
my @section_empty = (""); # section standard: no #ifdef's in module.mk files
-my @sections_scumm = ("", "ENABLE_SCUMM_7_8", "ENABLE_HE"); # special sections for engine SCUMM
-my @sections_saga = ("", "ENABLE_IHNM", "ENABLE_SAGA2"); # special sections for engine SAGA
-my @sections_kyra = ("", "ENABLE_LOL","ENABLE_EOB"); # special sections for engine KYRA
my @sections_agos = ("", "ENABLE_AGOS2"); # special sections for engine AGOS
+my @section_video = ("", "USE_BINK", "USE_MPEG2"); # special sections for engine VIDEO ###, "USE_THEORADEC"
+my @sections_groovie = ("", "ENABLE_GROOVIE2"); # special sections for engine GROOVIE
+my @sections_kyra = ("", "ENABLE_LOL","ENABLE_EOB"); # special sections for engine KYRA
+my @sections_mohawk = ("", "ENABLE_CSTIME", "ENABLE_MYST", "ENABLE_RIVEN"); # special sections for engine MOHAWK
+my @sections_saga = ("", "ENABLE_IHNM", "ENABLE_SAGA2"); # special sections for engine SAGA
+my @sections_sci = ("", "ENABLE_SCI32"); # special sections for engine SCI
+my @sections_scumm = ("", "ENABLE_SCUMM_7_8", "ENABLE_HE"); # special sections for engine SCUMM
# files excluded from build, case insensitive, will be matched in filename string only
my @excludes_snd = (
@@ -126,13 +139,13 @@ my @excludes_scumm = (
);
-#arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray])
+#ParseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray])
ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways...
ParseModule("_base", "common", \@section_empty);
ParseModule("_base", "gui", \@section_empty, \@excludes_gui);
ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics);
ParseModule("_base", "audio", \@section_empty, \@excludes_snd);
-ParseModule("_base", "video", \@section_empty);
+ParseModule("_base", "video", \@section_video); #
chdir("engines/");
ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm );
@@ -156,21 +169,30 @@ ParseModule("_drascula","drascula", \@section_empty);
ParseModule("_made", "made", \@section_empty);
ParseModule("_m4", "m4", \@section_empty);
ParseModule("_tinsel", "tinsel", \@section_empty);
-ParseModule("_groovie", "groovie", \@section_empty);
+ParseModule("_groovie", "groovie", \@sections_groovie);
ParseModule("_tucker", "tucker", \@section_empty);
-ParseModule("_sci", "sci", \@section_empty);
+ParseModule("_sci", "sci", \@sections_sci);
ParseModule("_draci", "draci", \@section_empty);
ParseModule("_teenagent","teenagent", \@section_empty);
-ParseModule("_mohawk" ,"mohawk", \@section_empty);
+ParseModule("_mohawk" ,"mohawk", \@sections_mohawk);
ParseModule("_hugo" ,"hugo", \@section_empty);
ParseModule("_toon" ,"toon", \@section_empty);
ParseModule("_lastexpress","lastexpress", \@section_empty);
ParseModule("_tsage","tsage", \@section_empty);
-ParseModule("_tony","tony", \@section_empty);
+ParseModule("_tony", "tony", \@section_empty);
ParseModule("_toltecs","toltecs", \@section_empty);
ParseModule("_hopkins","hopkins", \@section_empty);
ParseModule("_pegasus","pegasus", \@section_empty);
ParseModule("_wintermute","wintermute", \@section_empty);
+##### new engines
+ParseModule("_avalanche" ,"avalanche", \@section_empty);
+ParseModule("_dreamweb" ,"dreamweb", \@section_empty);
+ParseModule("_fullpipe" ,"fullpipe", \@section_empty);
+ParseModule("_mortevielle" ,"mortevielle", \@section_empty);
+ParseModule("_neverhood" ,"neverhood", \@section_empty);
+ParseModule("_sword25" ,"sword25", \@section_empty);
+ParseModule("_testbed" ,"testbed", \@section_empty);
+ParseModule("_zvision" ,"zvision", \@section_empty);
print "
=======================================================================================
Done. Enjoy :P
diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
index 3062068852..560439f4e1 100644
--- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
+++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
@@ -1,6 +1,7 @@
use Cwd;
use Switch;
+#use feature "switch";
system("cls");
require "BuildPackageUpload_LocalSettings.pl";
@@ -59,9 +60,13 @@ $ftp_url = "FTP://$FTP_User\@$FTP_Host/$FTP_Dir/";
# these macros are always defined:
$ExtraMacros = "MACRO NONSTANDARD_PORT\n";
-$ExtraMacros .= "MACRO ENABLE_VKEYBD\n";
+$ExtraMacros .= "MACRO ENABLE_VKEYBD\n";
$ExtraMacros .= "MACRO DISABLE_FANCY_THEMES\n";
$ExtraMacros .= "MACRO USE_TRANSLATION\n";
+$ExtraMacros .= "MACRO USE_BINK\n";
+$ExtraMacros .= "MACRO USE_MPEG2\n";
+# $ExtraMacros .= "MACRO \n";
+# candidates are : , USE_TIMIDITY,
# prep nice list of SDKs
#while( ($SDK, $RootDir) = each(%SDK_RootDirs) )
diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
index ded4ef198f..4ff485b3e3 100644
--- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
+++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
@@ -2,24 +2,33 @@
##################################################################################################################
@WorkingEngines = qw(
- scumm agos sky queen gob groovie saga drascula
- kyra lure agi touche parallaction cine
- cruise made tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon lastexpress tsage cge
- composer toltecs tony wintermute pegasus
+ agos agi cine cge composer cruise draci
+ drascula hugo gob groovie kyra lastexpress
+ lure made mohawk parallaction pegasus queen
+ saga sci scumm sky sword1 sword2 teenagent tinsel
+ toltecs tony toon touche tsage tucker wintermute
+ dreamweb fullpipe hopkins mortevielle
+ neverhood testbed avalanche zvision
);
+#### New engines
+#### sword25
@WorkingEngines_1st = qw(
- scumm queen groovie saga drascula
- touche parallaction cine
-? cruise made tucker lastexpress composer wintermute
+ cine composer cruise drascula groovie
+ lastexpress made parallaction queen
+ saga scumm touche tucker wintermute
+ avalanche zvision
);
@WorkingEngines_2nd = qw(
- agos sky gob kyra lure
- agi tinsel sword1 sword2
- draci sci teenagent hugo toon
- tsage cge toltecs tony pegasus
+ agi agos cge draci gob hopkins
+ hugo kyra lure mohawk pegasus sci
+ sky sword1 sword2 teenagent
+ tinsel tsage toltecs tony toon
+ dreamweb fullpipe mortevielle
+ neverhood testbed
);
+#### sword25
@TestingEngines = qw(
@@ -34,20 +43,32 @@
lol
agos2
eob
+ cstime
+ myst
+ riven
+ saga2
+ sci32
+ groovie2
);
#disabled subengines lol saga2 personal nightmare
+ # see configure.engines
%UseableFeatures = (
'zlib' => 'zlib.lib',
'mad' => 'libmad.lib',
'tremor' => 'libtremor.lib',
- 'flac' => 'libflac.lib'
+ 'flac' => 'libflacdec.lib',
+ 'freetype2' => 'freetype.lib',
+ 'faad' => 'libFAAD2.lib',
+ 'mpeg2' => 'libmpeg2.lib'
);
+ # 'mpeg2' => 'libmpeg2.lib'
# these are normally enabled for each variation
#$DefaultFeatures = qw(zlib,mad);
- $DefaultFeatures = qw(zlib,mad,tremor,flac);
+ #$DefaultFeatures = qw(zlib,mad,tremor,);
+ $DefaultFeatures = qw(mad,tremor,faad,flac,freetype2,mpeg2,zlib,);
##################################################################################################################
##
@@ -64,7 +85,8 @@
$HaltOnError = 0;
$SkipExistingPackages = 0;
$ReallyQuiet = 0;
- $DevBase = "C:\\S";
+ $DevBase = "D:\\Symbian";
+ $Compiler = "D:\\Program/ Files\\CodeSourcery\\Sourcery/ G++ Lite";
# specify an optional FTP server to upload to after each Build+Package (can leave empty)
#$FTP_Host = "host.com";
@@ -77,14 +99,14 @@
# Note1: the \epoc32 directory needs to be in these rootdirs
# Note2: these paths do NOT end in a backslash!
# $SDK_RootDirs{'UIQ2'} = "$DevBase\\UIQ_21";
- $SDK_RootDirs{'UIQ3'} = "$DevBase\\UIQ3";
+ # $SDK_RootDirs{'UIQ3'} = "$DevBase\\UIQ3";
# $SDK_RootDirs{'S60v1'} = "$DevBase\\S60v1";
# $SDK_RootDirs{'S60v2'} = "$DevBase\\S60v2";
$SDK_RootDirs{'S60v3'} = "$DevBase\\S60v3";
# $SDK_RootDirs{'S80'} = "$DevBase\\S80";
# $SDK_RootDirs{'S90'} = "$DevBase\\S90";
- $SDK_ToolchainDirs{'S60v3'} = "$DevBase\\arm-symbianelf\\bin";
+ $SDK_ToolchainDirs{'S60v3'} = "$Compiler\\arm-symbianelf\\bin";
$SDK_ToolchainDirs{'UIQ2'} = "$DevBase\\ECompXL\\bin"; # only needed for UIQ2/UIQ3
$SDK_ToolchainDirs{'UIQ3'} = "$DevBase\\ECompXL\\bin"; # only needed for UIQ2/UIQ3
@@ -94,7 +116,7 @@
{
## Standard libraries
$SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "$DevBase\\zlib-1.2.2\\epoc";
- #$SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "$DevBase\\libmad-0.15.1b\\group";
+ $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "$DevBase\\libmad-0.15.1b\\group";
$SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "$DevBase\\tremor\\epoc";
## SDL 1.2.12 / AnotherGuest / Symbian version
@@ -186,7 +208,7 @@
# now you can add $VariationSets only built on this PC below this line :)
}
- elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-LAPE") #################################################################
+ elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-VAIO2") #################################################################
{
$Producer = "AnotherGuest";
$RedirectSTDERR = 1;
@@ -206,7 +228,7 @@
$SDK_RootDirs{'S60v3'}= "G:\\S60v3";
#$SDK_RootDirs{'S80'}= "D:\\S80";
#$SDK_RootDirs{'S90'}= "D:\\S90";
- $ECompXL_BinDir= "D:\\ECompXL\\";
+ #$ECompXL_BinDir= "D:\\ECompXL\\";
if (0) # so we can turn them on/off easily
{
# $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc";
@@ -223,38 +245,42 @@
# now you can add $VariationSets only built on this PC below this line :)
}
- elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV_VAIO1") #################################################################
+ elsif ($ENV{'COMPUTERNAME'} eq "PC-FOREVER1111") #################################################################
{
- $Producer = "AnotherGuest";
+ $Producer = "Fedor";
$RedirectSTDERR = 1;
$HaltOnError = 0;
- $SkipExistingPackages = 1;
- $ReallyQuiet = 1;
+ $SkipExistingPackages = 0;
+ $ReallyQuiet = 0;
+ $Compiler = "D:\\Program/ Files\\CodeSourcery\\Sourcery/ G++ Lite";
#$FTP_Host = "host.com";
#$FTP_User = "ag@host.com";
#$FTP_Pass = "password";
#$FTP_Dir = "cvsbuilds";
- #$SDK_RootDirs{'UIQ2'}= "D:\\UIQ2";
- $SDK_RootDirs{'UIQ3'}= "G:\\UIQ3";
- #$SDK_RootDirs{'S60v1'}= "D:\\S60v1";
- #$SDK_RootDirs{'S60v2'}= "D:\\S60v2";
- $SDK_RootDirs{'S60v3'}= "G:\\S60v3";
- #$SDK_RootDirs{'S80'}= "D:\\S80";
- #$SDK_RootDirs{'S90'}= "D:\\S90";
- #$ECompXL_BinDir= "D:\\ECompXL\\";
+ #$SDK_RootDirs{'UIQ2'}= "C:\\UIQ2";
+ #$SDK_RootDirs{'UIQ3'}= "C:\\UIQ3";
+ #$SDK_RootDirs{'S60v1'}= "C:\\S60v1";
+ #$SDK_RootDirs{'S60v2'}= "C:\\S60v2";
+ #$SDK_RootDirs{'S80'}= "C:\\S80";
+ #$SDK_RootDirs{'S90'}= "C:\\S90";
+ #$ECompXL_BinDir= "C:\\ECompXL\\";
+
+ $SDK_RootDirs{'S60v3'}= "D:\\Symbian\\S60_5th_Edition_SDK_v1.0";
+ $SDK_ToolchainDirs{'S60v3'} = "$Compiler\\arm-symbianelf\\bin";
+
+ # these supporting libraries get built first, then all the Variations
+ # Note: the string {'xxx.lib'} is used in checking in build success: so needs to be accurate!
if (0) # so we can turn them on/off easily
{
# $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc";
-# $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "C:\\S\\libmad-0.15.1b\\group";
-# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "C:\\tremor\\epoc";
- $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ";
- $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60";
- $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S80";
- $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S90";
- $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60\\S60V3";
- $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ\\UIQ3";
+ $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "D:\\Symbian\\Projects\\SDL\\libs\\libmad-0.15.1b\\epoc";
+# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "D:\\Symbian\\Projects\\SDL\\libs\\Tremor\\epoc";
+# $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\UIQ";
+# $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S60";
+# $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S80";
+# $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S90";
}
# now you can add $VariationSets only built on this PC below this line :)
@@ -298,8 +324,8 @@
# the first one includes all SDKs & release-ready engines
$VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines";
-# $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines";
-# $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines";
+ # $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines";
+ # $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines";
# now one for each ready-for-release engine
if (0)
{
diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README
index 58cbc7814a..3c4fbb9d7d 100644
--- a/backends/platform/symbian/README
+++ b/backends/platform/symbian/README
@@ -2,7 +2,8 @@
ScummVM - ScummVM ported to EPOC/SymbianOS
Copyright (C) 2008-2013 ScummVM Team
- Copyright (C) 2003-2008 Lars 'AnotherGuest' Persson
+ Copyright (C) 2013-2013 Fedor Strizniou aka zanac
+ Copyright (C) 2003-2013 Lars 'AnotherGuest' Persson
Copyright (C) 2002-2008 Jurgen 'SumthinWicked' Braam
Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
@@ -24,6 +25,15 @@ About ScummVM
Jurgen and Lars have successfully transfered all needed changes into CVS/SVN, with additional helpful tools for Symbian OS
Release History:
+Release version: 1.7.0
+ * Nothing significant in the Symbian port, except SDL improvements (new SDL version used)
+
+Release version: 1.6.0
+ * Nothing significant in the Symbian port, except SDL improvements (new SDL version used)
+
+ Release version: 1.5.0
+ * Nothing significant in the Symbian port, except SDL improvements (new SDL version used)
+
Release version: 1.4.0
* Nothing significant in the Symbian port, except SDL improvements (new SDL version used)
* See main readme for general ScummVM improvements, major update
diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
index 4c6b1b05f8..a5920ae823 100644
--- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
+++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
@@ -33,7 +33,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM S60v3"},(0xA0000657),1,60,0
+#{"ScummVM S60v3"},(0xA0000657),1,70,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
@@ -58,18 +58,46 @@
"..\..\..\..\NEWS"-"!:\resource\apps\scummvm\NEWS"
; Common datafiles needed for some games
-"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat"
-"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
+"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
"..\..\..\..\dists\engine-data\hugo.dat"-"c:\data\scummvm\hugo.dat"
+"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat"
"..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat"
-"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
+"..\..\..\..\dists\engine-data\mort.dat"-"c:\data\scummvm\mort.dat"
+"..\..\..\..\dists\engine-data\neverhood.dat"-"c:\data\scummvm\neverhood.dat"
+"..\..\..\..\dists\engine-data\queen.tbl"-"c:\data\scummvm\queen.tbl"
+"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\teenagent.dat"-"c:\data\scummvm\teenagent.dat"
+"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat"
"..\..\..\..\dists\engine-data\toon.dat"-"c:\data\scummvm\toon.dat"
"..\..\..\..\dists\engine-data\wintermute.zip"-"c:\data\scummvm\wintermute.zip"
-"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat"
"..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip"
"..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat"
"..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip"
+"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf"
+"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf"
+"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf"
+"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf"
+"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf"
+"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf"
+"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf"
+"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf"
+"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf"
+;"..\..\..\..\gui\themes\"-"c:\data\scummvm\"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"c:\data\scummvm\scummvm.ini",FILENULL
diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg
index d3fd0450fa..c71805fb9f 100644
--- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg
+++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg
@@ -36,7 +36,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM S60v3"},(0xA0000657),1,60,0
+#{"ScummVM S60v3"},(0xA0000657),1,70,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
@@ -66,18 +66,45 @@
"..\..\..\..\NEWS"-"!:\resource\apps\scummvm\NEWS"
; Common datafiles needed for some games
-"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat"
-"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
+"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
"..\..\..\..\dists\engine-data\hugo.dat"-"c:\data\scummvm\hugo.dat"
+"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat"
"..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat"
-"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
+"..\..\..\..\dists\engine-data\mort.dat"-"c:\data\scummvm\mort.dat"
+"..\..\..\..\dists\engine-data\neverhood.dat"-"c:\data\scummvm\neverhood.dat"
+"..\..\..\..\dists\engine-data\queen.tbl"-"c:\data\scummvm\queen.tbl"
+"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\teenagent.dat"-"c:\data\scummvm\teenagent.dat"
+"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat"
"..\..\..\..\dists\engine-data\toon.dat"-"c:\data\scummvm\toon.dat"
-"..\..\..\..\dists\engine-data\wintermute.zip-"c:\data\scummvm\wintermute.zip"
-"..\..\..\..\dists\engine-data\tony.dat-"c:\data\scummvm\tony.dat"
+"..\..\..\..\dists\engine-data\wintermute.zip"-"c:\data\scummvm\wintermute.zip"
"..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip"
"..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat"
"..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip"
+"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf"
+"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf"
+"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf"
+"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf"
+"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf"
+"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf"
+"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf"
+"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf"
+"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf"
+"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf"
+"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf"
+"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf"
+"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"c:\data\scummvm\scummvm.ini",FILENULL
diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
index c62d25dafa..b4f1cfdd5c 100644
--- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
+++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
@@ -32,7 +32,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM UIQ3"},(0xA0000657),1,60,0
+#{"ScummVM UIQ3"},(0xA0000657),1,70,0
; ProductID for UIQ 3.0
; Product/platform version UID, Major, Minor, Build, Product ID
diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg
index a37e0b0533..722e23a1b8 100644
--- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg
+++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg
@@ -35,7 +35,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM UIQ3"},(0xA0000657),1,60,0
+#{"ScummVM UIQ3"},(0xA0000657),1,70,0
; ProductID for UIQ 3.0
; Product/platform version UID, Major, Minor, Build, Product ID
diff --git a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
new file mode 100644
index 0000000000..12f157f1e7
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_avalanche.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\avalanche
+
+//START_AUTO_OBJECTS_AVALANCHE_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_AVALANCHE_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in
index d6dfafd014..bf12bffb41 100644
--- a/backends/platform/symbian/mmp/scummvm_base.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in
@@ -50,15 +50,15 @@ ALWAYS_BUILD_AS_ARM
USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio
USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl
+USERINCLUDE \epoc32\include\mpeg2dec //\epoc32\include\theora
+SYSTEMINCLUDE \epoc32\include\freetype
+SYSTEMINCLUDE \epoc32\include\mpeg2dec
SYSTEMINCLUDE \epoc32\include\ESDL
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE \epoc32\include\tremor
SYSTEMINCLUDE \epoc32\include
-SYSTEMINCLUDE \epoc32\include\mw
-SYSTEMINCLUDE \epoc32\include\platform
-SYSTEMINCLUDE \epoc32\include\platform\mw
SYSTEMINCLUDE ..\src // for portdefs.h
// *** SOURCE files
@@ -115,6 +115,9 @@ SOURCEPATH ..\..\..\..\video
//STOP_AUTO_OBJECTS_VIDEO_//
// add a few files manually, since they are not parsed from modules.mk files
+SOURCE bink_decoder.cpp
+SOURCE codecs\mpeg.cpp
+
SOURCEPATH ..\..\..\..
SOURCE backends\events\default\default-events.cpp
SOURCE backends\timer\default\default-timer.cpp
diff --git a/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in
new file mode 100644
index 0000000000..b6369b7d2b
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_dreamweb.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\dreamweb
+
+//START_AUTO_OBJECTS_DREAMWEB_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_DREAMWEB_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in
new file mode 100644
index 0000000000..4a8f69f709
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_fullpipe.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\fullpipe
+
+//START_AUTO_OBJECTS_FULLPIPE_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_FULLPIPE_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
index 5772bfaad0..124f7c0dc3 100644
--- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
@@ -59,6 +59,13 @@ SOURCEPATH ..\..\..\..\engines\kyra
//STOP_AUTO_OBJECTS_KYRA_ENABLE_LOL//
+
+//START_AUTO_OBJECTS_KYRA_ENABLE_EOB//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_KYRA_ENABLE_EOB//
+
// *** Include paths
USERINCLUDE ..\..\..\..\engines
diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
index 5f7bd4e144..3fe9af68f6 100644
--- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
@@ -53,6 +53,25 @@ SOURCEPATH ..\..\..\..\engines\mohawk
//STOP_AUTO_OBJECTS_MOHAWK_//
+
+//START_AUTO_OBJECTS_MOHAWK_ENABLE_MYST//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_MYST//
+
+//START_AUTO_OBJECTS_MOHAWK_ENABLE_RIVEN//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_RIVEN//
+
+//START_AUTO_OBJECTS_MOHAWK_ENABLE_CSTIME//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_CSTIME//
+
// *** Include paths
USERINCLUDE ..\..\..\..\engines
diff --git a/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in
new file mode 100644
index 0000000000..3969a3af9c
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_mortevielle.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\mortevielle
+
+//START_AUTO_OBJECTS_MORTEVIELLE_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_MORTEVIELLE_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in
new file mode 100644
index 0000000000..3a49093c43
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_neverhood.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\neverhood
+
+//START_AUTO_OBJECTS_NEVERHOOD_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_NEVERHOOD_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
index 5749c66e10..333a6d43c2 100644
--- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
@@ -53,6 +53,14 @@ SOURCEPATH ..\..\..\..\engines\sci
//STOP_AUTO_OBJECTS_SCI_//
+
+//START_AUTO_OBJECTS_SCI_ENABLE_SCI32//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_SCI_ENABLE_SCI32//
+
+
// *** Include paths
USERINCLUDE ..\..\..\..\engines
diff --git a/backends/platform/symbian/mmp/scummvm_sword25.mmp.in b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in
new file mode 100644
index 0000000000..e14501e42d
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_sword25.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\sword25
+
+//START_AUTO_OBJECTS_SWORD25_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_SWORD25_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+USERINCLUDE ..\..\..\..\engines\sword25\util\lua ..\..\..\..\engines\sword25\util\pluto
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_testbed.mmp.in b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in
new file mode 100644
index 0000000000..ce6a18508d
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_testbed.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\testbed
+
+//START_AUTO_OBJECTS_TESTBED_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_TESTBED_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_zvision.mmp.in b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in
new file mode 100644
index 0000000000..3687b10fec
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2013 The ScummVM project
+ * Copyright (C) 2013 Strizniou Fedor
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_zvision.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\zvision
+
+//START_AUTO_OBJECTS_ZVISION_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_ZVISION_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src
+SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index b1bd976f9e..ead85a933e 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -197,3 +197,8 @@ void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size
return NULL;
}
+
+int remove(const char *path)
+{
+ return unlink(path);
+}
diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h
index 1f9128a54f..f69a90e009 100644
--- a/backends/platform/symbian/src/portdefs.h
+++ b/backends/platform/symbian/src/portdefs.h
@@ -60,6 +60,8 @@ typedef signed long int int32;
#define SMALL_SCREEN_DEVICE
#define DISABLE_COMMAND_LINE
+#define USE_RGB_COLOR
+int remove(const char *path);
#if defined(USE_TREMOR) && !defined(USE_VORBIS)
#define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
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/tizen/application.cpp b/backends/platform/tizen/application.cpp
new file mode 100644
index 0000000000..a73efacf58
--- /dev/null
+++ b/backends/platform/tizen/application.cpp
@@ -0,0 +1,144 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "engines/engine.h"
+
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/application.h"
+
+Application *TizenScummVM::createInstance() {
+ logEntered();
+ return new TizenScummVM();
+}
+
+TizenScummVM::TizenScummVM() : _appForm(NULL) {
+ logEntered();
+}
+
+TizenScummVM::~TizenScummVM() {
+ logEntered();
+ if (g_system) {
+ TizenSystem *system = (TizenSystem *)g_system;
+ system->destroyBackend();
+ delete system;
+ g_system = NULL;
+ }
+}
+
+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 TizenScummVM::OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination) {
+ logEntered();
+ return true;
+}
+
+void TizenScummVM::OnUserEventReceivedN(RequestId requestId, IList *args) {
+ logEntered();
+ MessageBox messageBox;
+ int modalResult;
+ String *message;
+
+ switch (requestId) {
+ case USER_MESSAGE_EXIT:
+ // normal program termination
+ Terminate();
+ break;
+
+ case USER_MESSAGE_EXIT_ERR:
+ // assertion failure termination
+ if (args) {
+ message = (String *)args->GetAt(0);
+ }
+ if (!message) {
+ message = new String("Unknown error");
+ }
+ messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK);
+ messageBox.ShowAndWait(modalResult);
+ Terminate();
+ break;
+
+ case 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();
+ break;
+ }
+}
+
+void TizenScummVM::OnForeground(void) {
+ logEntered();
+ pauseGame(false);
+}
+
+void TizenScummVM::OnBackground(void) {
+ logEntered();
+ pauseGame(true);
+}
+
+void TizenScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
+ logEntered();
+}
+
+void TizenScummVM::OnLowMemory(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOn(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOff(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenBrightnessChanged(int brightness) {
+ logEntered();
+}
+
+void TizenScummVM::pauseGame(bool pause) {
+ if (_appForm) {
+ if (pause && g_engine && !g_engine->isPaused()) {
+ _appForm->pushKey(Common::KEYCODE_SPACE);
+ }
+ if (g_system) {
+ ((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..f9ac80a583 100644
--- a/backends/platform/bada/audio.cpp
+++ b/backends/platform/tizen/audio.cpp
@@ -23,18 +23,12 @@
#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 96
+#define MIN_TIMER_INTERVAL 5
AudioThread::AudioThread() :
_mixer(0),
@@ -45,15 +39,14 @@ AudioThread::AudioThread() :
_ready(0),
_interval(TIMER_INTERVAL),
_playing(-1),
+ _size(0),
_muted(true) {
}
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 +62,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;
}
@@ -84,54 +77,11 @@ void AudioThread::setMute(bool on) {
}
}
-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);
- }
- }
- 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 +94,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;
}
@@ -158,6 +107,7 @@ bool AudioThread::OnStart(void) {
}
}
+ _size = _audioBuffer[0].GetCapacity();
_timer = new Timer();
if (!_timer || IsFailed(_timer->Construct(*this))) {
AppLog("Failed to create audio timer");
@@ -169,21 +119,9 @@ bool AudioThread::OnStart(void) {
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;
}
@@ -202,53 +140,52 @@ void AudioThread::OnStop(void) {
if (_audioOut) {
_audioOut->Reset();
+ _audioOut->Unprepare();
delete _audioOut;
}
}
-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]);
_tail = (_tail + 1) % NUM_AUDIO_BUFFERS;
_ready--;
} else {
- // audio buffer empty: decrease timer inverval
+ // audio buffer empty: decrease timer interval
_playing = -1;
- _interval -= TIMER_INCREMENT;
+ _interval -= 1;
if (_interval < MIN_TIMER_INTERVAL) {
_interval = MIN_TIMER_INTERVAL;
}
}
+
}
void AudioThread::OnTimerExpired(Timer &timer) {
if (_ready < NUM_AUDIO_BUFFERS) {
- uint len = _audioBuffer[_head].GetCapacity();
- int samples = _mixer->mixCallback((byte *)_audioBuffer[_head].GetPointer(), len);
- if (samples) {
- _head = (_head + 1) % NUM_AUDIO_BUFFERS;
- _ready++;
+ if (_playing != _head) {
+ if (_mixer->mixCallback((byte *)_audioBuffer[_head].GetPointer(), _size)) {
+ _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;
- }
+ // audio buffer full: restore timer interval
+ _interval = TIMER_INTERVAL;
}
if (_ready && _playing == -1) {
diff --git a/backends/platform/bada/audio.h b/backends/platform/tizen/audio.h
index 72c537a942..a304231578 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,22 +53,21 @@ public:
Audio::MixerImpl *Construct(OSystem *system);
bool isSilentMode();
void setMute(bool on);
- int setVolume(bool up, bool minMax);
+private:
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];
- int _head, _tail, _ready, _interval, _playing;
+ Tizen::Base::Runtime::Timer *_timer;
+ Tizen::Media::AudioOut *_audioOut;
+ Tizen::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS];
+ int _head, _tail, _ready, _interval, _playing, _size;
bool _muted;
};
diff --git a/backends/platform/tizen/form.cpp b/backends/platform/tizen/form.cpp
new file mode 100644
index 0000000000..10d51cc610
--- /dev/null
+++ b/backends/platform/tizen/form.cpp
@@ -0,0 +1,432 @@
+/* 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(kEscapeKey) {
+}
+
+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);
+ SetFormBackEventListener(this);
+ SetFormMenuEventListener(this);
+
+ // 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);
+ }
+}
+
+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);
+ }
+ }
+}
+
+void TizenAppForm::OnFormBackRequested(Form &source) {
+ logEntered();
+ if (_state == kActiveState) {
+ invokeShortcut();
+ }
+}
+
+void TizenAppForm::OnFormMenuRequested(Form &source) {
+ logEntered();
+ if (_state == kActiveState) {
+ setShortcut();
+ }
+}
diff --git a/backends/platform/tizen/form.h b/backends/platform/tizen/form.h
new file mode 100644
index 0000000000..e419c14d24
--- /dev/null
+++ b/backends/platform/tizen/form.h
@@ -0,0 +1,120 @@
+/* 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 <FUiCtrlIFormBackEventListener.h>
+#include <FUiCtrlIFormMenuEventListener.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;
+using namespace Tizen::Ui::Controls;
+
+//
+// TizenAppForm
+//
+class TizenAppForm :
+ public Controls::Form,
+ public IRunnable,
+ public IOrientationEventListener,
+ public ITouchEventListener,
+ public IFormBackEventListener,
+ public IFormMenuEventListener {
+
+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 OnFormBackRequested(Form &source);
+ void OnFormMenuRequested(Form &source);
+
+ 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..8145cd5638 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,53 @@ 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(kSdCard));
+ myList.push_back(new TizenFilesystemNode(kMedia));
+ myList.push_back(new TizenFilesystemNode(kShared));
}
if (!result) {
@@ -358,7 +363,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 +379,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 +397,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 +417,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..390796dc0e 100644
--- a/backends/platform/bada/graphics.cpp
+++ b/backends/platform/tizen/graphics.cpp
@@ -22,35 +22,62 @@
#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);
+ }
+ }
+}
+
+result TizenGraphicsManager::Construct() {
+ // Initialize our OpenGL ES context.
+ loadEgl();
+
+ // Notify the OpenGL code about our context.
+
+ // We default to RGB565 and RGBA5551 which is closest to the actual output
+ // mode we setup.
+ notifyContextChange(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
+
+ // Tell our size.
+ int x, y, width, height;
+ _appForm->GetBounds(x, y, width, height);
+ AppLog("screen size: %dx%d", width, height);
+ setActualScreenSize(width, height);
+ return E_SUCCESS;
+}
+
+const Graphics::Font *TizenGraphicsManager::getFontOSD() {
return FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
}
-bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) {
- int16 currentX = _cursorState.x;
- int16 currentY = _cursorState.y;
+bool TizenGraphicsManager::moveMouse(int16 &x, int16 &y) {
+ int16 currentX, currentY;
+ getMousePosition(currentX, currentY);
// save the current hardware coordinates
- _cursorState.x = x;
- _cursorState.y = y;
+ setMousePosition(x, y);
// return x/y as game coordinates
adjustMousePosition(x, y);
@@ -62,7 +89,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 +100,42 @@ Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() c
return res;
}
-bool BadaGraphicsManager::hasFeature(OSystem::Feature f) {
- bool result = (f == OSystem::kFeatureFullscreenMode ||
- f == OSystem::kFeatureVirtualKeyboard ||
- OpenGLGraphicsManager::hasFeature(f));
+bool TizenGraphicsManager::hasFeature(OSystem::Feature f) {
+ bool result =
+ (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) {
+ if (enable) {
+ _appForm->showKeypad();
+ }
+ } else {
+ OpenGLGraphicsManager::setFeatureState(f, enable);
+ }
}
-void BadaGraphicsManager::setReady() {
+void TizenGraphicsManager::setReady() {
+ logEntered();
+ _appForm->GetVisualElement()->SetShowState(true);
_initState = false;
}
-void BadaGraphicsManager::updateScreen() {
- if (_transactionMode == kTransactionNone) {
- internUpdateScreen();
+void TizenGraphicsManager::updateScreen() {
+ if (!_initState) {
+ OpenGLGraphicsManager::updateScreen();
+ eglSwapBuffers(_eglDisplay, _eglSurface);
}
}
-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,
@@ -116,10 +152,6 @@ bool BadaGraphicsManager::loadEgl() {
eglBindAPI(EGL_OPENGL_ES_API);
- if (_eglDisplay) {
- unloadGFXMode();
- }
-
_eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);
if (EGL_NO_DISPLAY == _eglDisplay) {
systemError("eglGetDisplay() failed");
@@ -132,8 +164,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 +175,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");
@@ -164,98 +193,12 @@ bool BadaGraphicsManager::loadEgl() {
systemError("eglMakeCurrent() failed");
return false;
}
-
logLeaving();
return true;
}
-bool BadaGraphicsManager::loadGFXMode() {
- logEntered();
-
- if (!loadEgl()) {
- unloadGFXMode();
- return false;
- }
-
- int x, y, width, height;
- _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
-
- AppLog("screen size: %dx%d", _videoMode.hardwareWidth, _videoMode.hardwareHeight);
- return OpenGLGraphicsManager::loadGFXMode();
-}
-
-void BadaGraphicsManager::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() {
- if (!_initState) {
- OpenGLGraphicsManager::internUpdateScreen();
- eglSwapBuffers(_eglDisplay, _eglSurface);
- } else {
- showSplash();
- }
-}
-
-void BadaGraphicsManager::unloadGFXMode() {
- logEntered();
-
- if (EGL_NO_DISPLAY != _eglDisplay) {
- eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
-
- if (_eglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(_eglDisplay, _eglContext);
- _eglContext = EGL_NO_CONTEXT;
- }
-
- if (_eglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(_eglDisplay, _eglSurface);
- _eglSurface = EGL_NO_SURFACE;
- }
-
- eglTerminate(_eglDisplay);
- _eglDisplay = EGL_NO_DISPLAY;
- }
-
- _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();
-
+bool TizenGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
+ // We get this whenever a new resolution is requested. Since Tizen is
+ // using a fixed output size we do nothing like that here.
+ return true;
}
diff --git a/backends/platform/bada/graphics.h b/backends/platform/tizen/graphics.h
index b2aaca43bc..29ba86a3c4 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,35 +33,39 @@
#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 OpenGL::OpenGLGraphicsManager {
public:
- BadaGraphicsManager(BadaAppForm *appForm);
+ TizenGraphicsManager(TizenAppForm *appForm);
+ virtual ~TizenGraphicsManager();
+
+ result Construct();
Common::List<Graphics::PixelFormat> getSupportedFormats() const;
bool hasFeature(OSystem::Feature f);
- void updateScreen();
void setFeatureState(OSystem::Feature f, bool enable);
+ void updateScreen();
+
void setReady();
bool isReady() { return !_initState; }
- const Graphics::Font *getFontOSD();
+
bool moveMouse(int16 &x, int16 &y);
-private:
- void internUpdateScreen();
- bool loadGFXMode();
- void loadTextures();
- void unloadGFXMode();
+protected:
void setInternalMousePosition(int x, int y) {}
- void showSplash();
+ bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format);
+
+ const Graphics::Font *getFontOSD();
+
+private:
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..75f009cc61 100644
--- a/backends/platform/bada/sscanf.cpp
+++ b/backends/platform/tizen/sscanf.cpp
@@ -93,7 +93,7 @@ bool scanStringUntil(const char **in, va_list *ap, char c_end) {
char *arg = va_arg(*ap, char*);
while (**in && **in != c_end) {
*arg = **in;
- *arg++;
+ arg++;
(*in)++;
}
*arg = 0;
diff --git a/backends/platform/bada/system.cpp b/backends/platform/tizen/system.cpp
index 3f862c2571..f7ebc46719 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);
- if (!_graphicsManager) {
+ _graphicsManager = (GraphicsManager *)new TizenGraphicsManager(_appForm);
+ if (!_graphicsManager || graphicsManager->Construct() != E_SUCCESS) {
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,72 @@ 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);
+ appForm->GetVisualElement()->SetShowState(false);
+
+ logLeaving();
return appForm;
}
@@ -502,13 +532,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(App::GetInstance()->GetAppDataPath() + 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/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
index a9bcdbb8d1..92c890b0a9 100644
--- a/backends/platform/wii/osystem_gfx.cpp
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -528,16 +528,13 @@ void OSystem_Wii::updateScreen() {
}
Graphics::Surface *OSystem_Wii::lockScreen() {
- _surface.pixels = _gamePixels;
- _surface.w = _gameWidth;
- _surface.h = _gameHeight;
+ _surface.init(_gameWidth, _gameHeight,
#ifdef USE_RGB_COLOR
- _surface.pitch = _gameWidth * _pfGame.bytesPerPixel;
- _surface.format = _pfGame;
+ _gameWidth * _pfGame.bytesPerPixel, _gamePixels, _pfGame
#else
- _surface.pitch = _gameWidth;
- _surface.format = Graphics::PixelFormat::createFormatCLUT8();
+ _gameWidth, _gamePixels, Graphics::PixelFormat::createFormatCLUT8()
#endif
+ );
return &_surface;
}
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index 3897731db4..1c5cd5565b 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -563,7 +563,7 @@ void OSystem_WINCE3::setGraphicsModeIntern() {
void OSystem_WINCE3::initSDL() {
// Check if SDL has not been initialized
if (!_initedSDL) {
- uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO;
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
@@ -576,9 +576,6 @@ void OSystem_WINCE3::initSDL() {
if (SDL_Init(sdlFlags) == -1)
error("Could not initialize SDL: %s", SDL_GetError());
- // Enable unicode support if possible
- SDL_EnableUNICODE(1);
-
_initedSDL = true;
}
}
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/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp
index 75de86472f..ec4cbf1de2 100644
--- a/backends/vkeybd/virtual-keyboard-gui.cpp
+++ b/backends/vkeybd/virtual-keyboard-gui.cpp
@@ -32,11 +32,9 @@
namespace Common {
-static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, OverlayColor transparent) {
- if (surf_dst->format.bytesPerPixel != sizeof(OverlayColor) || surf_src->format.bytesPerPixel != sizeof(OverlayColor))
- return;
-
- const OverlayColor *src = (const OverlayColor *)surf_src->pixels;
+template<typename ColorType>
+static void blitImplementation(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, ColorType transparent) {
+ const ColorType *src = (const ColorType *)surf_src->getPixels();
int blitW = surf_src->w;
int blitH = surf_src->h;
@@ -58,13 +56,13 @@ static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16
if (blitW <= 0 || blitH <= 0)
return;
- OverlayColor *dst = (OverlayColor *)surf_dst->getBasePtr(x, y);
+ ColorType *dst = (ColorType *)surf_dst->getBasePtr(x, y);
int dstAdd = surf_dst->w - blitW;
int srcAdd = surf_src->w - blitW;
for (int i = 0; i < blitH; ++i) {
for (int j = 0; j < blitW; ++j, ++dst, ++src) {
- OverlayColor col = *src;
+ ColorType col = *src;
if (col != transparent)
*dst = col;
}
@@ -73,6 +71,16 @@ static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16
}
}
+static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, uint32 transparent) {
+ if (surf_dst->format.bytesPerPixel != surf_src->format.bytesPerPixel)
+ return;
+
+ if (surf_dst->format.bytesPerPixel == 2)
+ blitImplementation<uint16>(surf_dst, surf_src, x, y, transparent);
+ else if (surf_dst->format.bytesPerPixel == 4)
+ blitImplementation<uint32>(surf_dst, surf_src, x, y, transparent);
+}
+
VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd)
: _kbd(kbd), _displaying(false), _drag(false),
_drawCaret(false), _displayEnabled(false), _firstRun(true),
@@ -111,7 +119,7 @@ void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) {
}
}
-void VirtualKeyboardGUI::setupDisplayArea(Rect &r, OverlayColor forecolor) {
+void VirtualKeyboardGUI::setupDisplayArea(Rect &r, uint32 forecolor) {
_dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
if (!fontIsSuitable(_dispFont, r)) {
@@ -161,7 +169,7 @@ void VirtualKeyboardGUI::run() {
_system->clearOverlay();
}
_overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat());
- _system->grabOverlay(_overlayBackup.pixels, _overlayBackup.pitch);
+ _system->grabOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch);
setupCursor();
@@ -171,7 +179,7 @@ void VirtualKeyboardGUI::run() {
removeCursor();
- _system->copyRectToOverlay(_overlayBackup.pixels, _overlayBackup.pitch, 0, 0, _overlayBackup.w, _overlayBackup.h);
+ _system->copyRectToOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch, 0, 0, _overlayBackup.w, _overlayBackup.h);
if (!g_gui.isActive()) _system->hideOverlay();
_overlayBackup.free();
@@ -262,7 +270,7 @@ void VirtualKeyboardGUI::screenChanged() {
_screenH = newScreenH;
_overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat());
- _system->grabOverlay(_overlayBackup.pixels, _overlayBackup.pitch);
+ _system->grabOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch);
if (!_kbd->checkModeResolutions()) {
_displaying = false;
@@ -356,13 +364,13 @@ void VirtualKeyboardGUI::redraw() {
Graphics::Surface surf;
surf.create(w, h, _system->getOverlayFormat());
- OverlayColor *dst = (OverlayColor *)surf.pixels;
- const OverlayColor *src = (OverlayColor *) _overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top);
+ byte *dst = (byte *)surf.getPixels();
+ const byte *src = (const byte *)_overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top);
while (h--) {
- memcpy(dst, src, surf.w * sizeof(OverlayColor));
- dst += surf.w;
- src += _overlayBackup.w;
+ memcpy(dst, src, surf.pitch);
+ dst += surf.pitch;
+ src += _overlayBackup.pitch;
}
blit(&surf, _kbdSurface, _kbdBound.left - _dirtyRect.left,
@@ -371,7 +379,7 @@ void VirtualKeyboardGUI::redraw() {
blit(&surf, &_dispSurface, _dispX - _dirtyRect.left,
_dispY - _dirtyRect.top, _dispBackColor);
}
- _system->copyRectToOverlay(surf.pixels, surf.pitch,
+ _system->copyRectToOverlay(surf.getPixels(), surf.pitch,
_dirtyRect.left, _dirtyRect.top, surf.w, surf.h);
surf.free();
diff --git a/backends/vkeybd/virtual-keyboard-gui.h b/backends/vkeybd/virtual-keyboard-gui.h
index d0f9c884ed..a2000adea0 100644
--- a/backends/vkeybd/virtual-keyboard-gui.h
+++ b/backends/vkeybd/virtual-keyboard-gui.h
@@ -99,7 +99,7 @@ private:
VirtualKeyboard *_kbd;
Rect _kbdBound;
Graphics::Surface *_kbdSurface;
- OverlayColor _kbdTransparentColor;
+ uint32 _kbdTransparentColor;
Point _dragPoint;
bool _drag;
@@ -113,7 +113,7 @@ private:
const Graphics::Font *_dispFont;
int16 _dispX, _dispY;
uint _dispI;
- OverlayColor _dispForeColor, _dispBackColor;
+ uint32 _dispForeColor, _dispBackColor;
int _lastScreenChanged;
int16 _screenW, _screenH;
@@ -121,7 +121,7 @@ private:
bool _displaying;
bool _firstRun;
- void setupDisplayArea(Rect &r, OverlayColor forecolor);
+ void setupDisplayArea(Rect &r, uint32 forecolor);
void move(int16 x, int16 y);
void moveToDefaultPosition();
void screenChanged();
diff --git a/backends/vkeybd/virtual-keyboard.h b/backends/vkeybd/virtual-keyboard.h
index 4ab5ad446d..3b2b2196bd 100644
--- a/backends/vkeybd/virtual-keyboard.h
+++ b/backends/vkeybd/virtual-keyboard.h
@@ -112,11 +112,11 @@ protected:
String resolution;
String bitmapName;
Graphics::Surface *image;
- OverlayColor transparentColor;
+ uint32 transparentColor;
ImageMap imageMap;
VKEventMap events;
Rect displayArea;
- OverlayColor displayFontColor;
+ uint32 displayFontColor;
Mode() : image(0) {}
~Mode() {
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 42a3a64d34..a032f37a25 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)
@@ -822,9 +827,8 @@ void upgradeTargets() {
printf("Upgrading all your existing targets\n");
- Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
- Common::ConfigManager::DomainMap::iterator iter = domains.begin();
- for (iter = domains.begin(); iter != domains.end(); ++iter) {
+ Common::ConfigManager::DomainMap::iterator iter = ConfMan.beginGameDomains();
+ for (; iter != ConfMan.endGameDomains(); ++iter) {
Common::ConfigManager::Domain &dom = iter->_value;
Common::String name(iter->_key);
Common::String gameid(dom.getVal("gameid"));
diff --git a/base/main.cpp b/base/main.cpp
index 355a65f883..c993dfa57a 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"
@@ -131,6 +134,19 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
Common::Error err = Common::kNoError;
Engine *engine = 0;
+#if defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR)
+ // HACK: We set up the requested graphics mode setting here to allow the
+ // backend to switch from Surface SDL to OpenGL if necessary. This is
+ // needed because otherwise the g_system->getSupportedFormats might return
+ // bad values.
+ g_system->beginGFXTransaction();
+ g_system->setGraphicsMode(ConfMan.get("gfx_mode").c_str());
+ if (g_system->endGFXTransaction() != OSystem::kTransactionSuccess) {
+ warning("Switching graphics mode to '%s' failed", ConfMan.get("gfx_mode").c_str());
+ return Common::kUnknownError;
+ }
+#endif
+
// Verify that the game path refers to an actual directory
if (!(dir.exists() && dir.isDirectory()))
err = Common::kPathNotDirectory;
@@ -409,7 +425,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 +440,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 +468,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 +515,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 +543,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/base/plugins.h b/base/plugins.h
index 4409c9eaea..e0673ce636 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -169,7 +169,7 @@ protected:
PluginType _type;
public:
- Plugin() : _pluginObject(0) {}
+ Plugin() : _pluginObject(0), _type(PLUGIN_TYPE_MAX) {}
virtual ~Plugin() {
//if (isLoaded())
//unloadPlugin();
diff --git a/base/version.cpp b/base/version.cpp
index 89fae90c2e..c55bd63323 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -129,4 +129,12 @@ const char *gScummVMFeatures = ""
#ifdef USE_FREETYPE2
"FreeType2 "
#endif
+
+#ifdef USE_JPEG
+ "JPEG "
+#endif
+
+#ifdef USE_PNG
+ "PNG "
+#endif
;
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/archive.cpp b/common/archive.cpp
index 1323f14805..57ebeb2ca6 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -118,7 +118,7 @@ void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority
add(name, new FSDirectory(dir, depth, flat), priority);
}
-void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) {
+void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority, int depth, bool flat) {
FSList subDirs;
if (!directory.getChildren(subDirs))
return;
@@ -161,9 +161,9 @@ void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPa
}
if (nextPattern.empty())
- addDirectory(name, *i, priority);
+ addDirectory(name, *i, priority, depth, flat);
else
- addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority);
+ addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority, depth, flat);
}
}
}
diff --git a/common/archive.h b/common/archive.h
index ffd86d786d..2f9736f032 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -184,8 +184,8 @@ public:
* to assume that this method is using anything other than a simple case insensitive compare.
* Thus do not use any tokens like '*' or '?' in the "caselessName" parameter of this function!
*/
- void addSubDirectoryMatching(const FSNode &directory, const String &caselessName, int priority = 0) {
- addSubDirectoriesMatching(directory, caselessName, true, priority);
+ void addSubDirectoryMatching(const FSNode &directory, const String &caselessName, int priority = 0, int depth = 1, bool flat = false) {
+ addSubDirectoriesMatching(directory, caselessName, true, priority, depth, flat);
}
/**
@@ -208,7 +208,7 @@ public:
*
* @see Common::matchString
*/
- void addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority = 0);
+ void addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority = 0, int depth = 1, bool flat = false);
/**
* Remove an archive from the searchable set.
diff --git a/common/c++11-compat.h b/common/c++11-compat.h
index 50d79bd79e..f963ba9ac8 100644
--- a/common/c++11-compat.h
+++ b/common/c++11-compat.h
@@ -31,7 +31,9 @@
// Custom nullptr replacement. This is not type safe as the real C++11 nullptr
// though.
//
+#if !defined(nullptr) // XCode 5.0.1 has __cplusplus=199711 but defines this
#define nullptr 0
+#endif
//
// Replacement for the override keyword. This allows compilation of code
diff --git a/common/config-manager.h b/common/config-manager.h
index d43a7bec51..6bf56749c5 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -24,7 +24,6 @@
#define COMMON_CONFIG_MANAGER_H
#include "common/array.h"
-//#include "common/config-file.h"
#include "common/hashmap.h"
#include "common/singleton.h"
#include "common/str.h"
@@ -47,12 +46,33 @@ class ConfigManager : public Singleton<ConfigManager> {
public:
- class Domain : public StringMap {
+ class Domain {
private:
+ StringMap _entries;
StringMap _keyValueComments;
String _domainComment;
public:
+ typedef StringMap::const_iterator const_iterator;
+ const_iterator begin() const { return _entries.begin(); }
+ const_iterator end() const { return _entries.end(); }
+
+ bool empty() const { return _entries.empty(); }
+
+ bool contains(const String &key) const { return _entries.contains(key); }
+
+ String &operator[](const String &key) { return _entries[key]; }
+ const String &operator[](const String &key) const { return _entries[key]; }
+
+ void setVal(const String &key, const String &value) { _entries.setVal(key, value); }
+
+ String &getVal(const String &key) { return _entries.getVal(key); }
+ const String &getVal(const String &key) const { return _entries.getVal(key); }
+
+ void clear() { _entries.clear(); }
+
+ void erase(const String &key) { _entries.erase(key); }
+
void setDomainComment(const String &comment);
const String &getDomainComment() const;
@@ -143,7 +163,8 @@ public:
bool hasMiscDomain(const String &domName) const;
const DomainMap & getGameDomains() const { return _gameDomains; }
- DomainMap & getGameDomains() { return _gameDomains; }
+ DomainMap::iterator beginGameDomains() { return _gameDomains.begin(); }
+ DomainMap::iterator endGameDomains() { return _gameDomains.end(); }
static void defragment(); // move in memory to reduce fragmentation
void copyFrom(ConfigManager &source);
diff --git a/common/coroutines.h b/common/coroutines.h
index 834c67f6e4..30b9bb6a99 100644
--- a/common/coroutines.h
+++ b/common/coroutines.h
@@ -128,7 +128,7 @@ public:
*/
#define CORO_BEGIN_CONTEXT \
struct CoroContextTag : Common::CoroBaseContext { \
- CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) {} \
+ CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) { DUMMY = 0; } \
int DUMMY
/**
@@ -146,6 +146,7 @@ public:
#define CORO_BEGIN_CODE(x) \
if (&coroParam == &Common::nullContext) assert(!Common::nullContext); \
if (!x) { coroParam = x = new CoroContextTag(); } \
+ x->DUMMY = 0; \
Common::CoroContextHolder tmpHolder(coroParam); \
switch (coroParam->_line) { case 0:;
diff --git a/common/cosinetables.cpp b/common/cosinetables.cpp
index fe8f454e14..3b245750fa 100644
--- a/common/cosinetables.cpp
+++ b/common/cosinetables.cpp
@@ -34,10 +34,10 @@ CosineTable::CosineTable(int bitPrecision) {
int m = 1 << _bitPrecision;
double freq = 2 * M_PI / m;
- _table = new float[m];
+ _table = new float[m / 2];
- // Table contains cos(2*pi*x/n) for 0<=x<=n/4,
- // followed by its reverse
+ // Table contains cos(2*pi*i/m) for 0<=i<m/4,
+ // followed by 3m/4<=i<m
for (int i = 0; i <= m / 4; i++)
_table[i] = cos(i * freq);
diff --git a/common/cosinetables.h b/common/cosinetables.h
index f9fb6fd59a..f5c95ec003 100644
--- a/common/cosinetables.h
+++ b/common/cosinetables.h
@@ -36,7 +36,14 @@ public:
~CosineTable();
/**
- * Get pointer to table
+ * Get pointer to table.
+ *
+ * This table contains 2^bitPrecision/2 entries.
+ * The layout of this table is as follows:
+ * - Entries 0 up to (excluding) 2^bitPrecision/4:
+ * cos(0) till (excluding) cos(1/2*pi)
+ * - Entries 2^bitPrecision/4 up to (excluding) 2^bitPrecision/2:
+ * cos(3/2*pi) till (excluding) cos(2*pi)
*/
const float *getTable() { return _table; }
diff --git a/common/dcl.cpp b/common/dcl.cpp
index 1879be992d..87ec0ad915 100644
--- a/common/dcl.cpp
+++ b/common/dcl.cpp
@@ -371,12 +371,14 @@ bool DecompressorDCL::unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32
debug(8, "\nCOPY(%d from %d)\n", val_length, val_distance);
if (val_length + _dwWrote > _szUnpacked) {
- warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes", val_length);
+ warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes (declared unpacked size is %d bytes, current is %d + %d bytes)",
+ val_length, _szUnpacked, _dwWrote, val_length);
return false;
}
if (_dwWrote < val_distance) {
- warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream");
+ warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream (declared unpacked size is %d bytes, current is %d bytes)",
+ _szUnpacked, _dwWrote);
return false;
}
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/config-file.cpp b/common/ini-file.cpp
index 0ce6dcf0c8..be5247dcfb 100644
--- a/common/config-file.cpp
+++ b/common/ini-file.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -28,24 +28,24 @@
namespace Common {
-bool ConfigFile::isValidName(const String &name) {
+bool INIFile::isValidName(const String &name) {
const char *p = name.c_str();
while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.'))
p++;
return *p == 0;
}
-ConfigFile::ConfigFile() {
+INIFile::INIFile() {
}
-ConfigFile::~ConfigFile() {
+INIFile::~INIFile() {
}
-void ConfigFile::clear() {
+void INIFile::clear() {
_sections.clear();
}
-bool ConfigFile::loadFromFile(const String &filename) {
+bool INIFile::loadFromFile(const String &filename) {
File file;
if (file.open(filename))
return loadFromStream(file);
@@ -53,7 +53,7 @@ bool ConfigFile::loadFromFile(const String &filename) {
return false;
}
-bool ConfigFile::loadFromSaveFile(const char *filename) {
+bool INIFile::loadFromSaveFile(const char *filename) {
assert(g_system);
SaveFileManager *saveFileMan = g_system->getSavefileManager();
SeekableReadStream *loadFile;
@@ -67,7 +67,7 @@ bool ConfigFile::loadFromSaveFile(const char *filename) {
return status;
}
-bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
+bool INIFile::loadFromStream(SeekableReadStream &stream) {
Section section;
KeyValue kv;
String comment;
@@ -112,9 +112,9 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
p++;
if (*p == '\0')
- error("ConfigFile::loadFromStream: missing ] in line %d", lineno);
+ error("INIFile::loadFromStream: missing ] in line %d", lineno);
else if (*p != ']')
- error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno);
+ error("INIFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno);
// Previous section is finished now, store it.
if (!section.name.empty())
@@ -140,7 +140,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
// If no section has been set, this config file is invalid!
if (section.name.empty()) {
- error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
+ error("INIFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
}
// Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
@@ -173,7 +173,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
return (!stream.err() || stream.eos());
}
-bool ConfigFile::saveToFile(const String &filename) {
+bool INIFile::saveToFile(const String &filename) {
DumpFile file;
if (file.open(filename))
return saveToStream(file);
@@ -181,7 +181,7 @@ bool ConfigFile::saveToFile(const String &filename) {
return false;
}
-bool ConfigFile::saveToSaveFile(const char *filename) {
+bool INIFile::saveToSaveFile(const char *filename) {
assert(g_system);
SaveFileManager *saveFileMan = g_system->getSavefileManager();
WriteStream *saveFile;
@@ -195,7 +195,7 @@ bool ConfigFile::saveToSaveFile(const char *filename) {
return status;
}
-bool ConfigFile::saveToStream(WriteStream &stream) {
+bool INIFile::saveToStream(WriteStream &stream) {
for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
// Write out the section comment, if any
if (! i->comment.empty()) {
@@ -226,7 +226,7 @@ bool ConfigFile::saveToStream(WriteStream &stream) {
return !stream.err();
}
-void ConfigFile::addSection(const String &section) {
+void INIFile::addSection(const String &section) {
Section *s = getSection(section);
if (s)
return;
@@ -236,7 +236,7 @@ void ConfigFile::addSection(const String &section) {
_sections.push_back(newSection);
}
-void ConfigFile::removeSection(const String &section) {
+void INIFile::removeSection(const String &section) {
assert(isValidName(section));
for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
if (section.equalsIgnoreCase(i->name)) {
@@ -246,13 +246,13 @@ void ConfigFile::removeSection(const String &section) {
}
}
-bool ConfigFile::hasSection(const String &section) const {
+bool INIFile::hasSection(const String &section) const {
assert(isValidName(section));
const Section *s = getSection(section);
return s != 0;
}
-void ConfigFile::renameSection(const String &oldName, const String &newName) {
+void INIFile::renameSection(const String &oldName, const String &newName) {
assert(isValidName(oldName));
assert(isValidName(newName));
@@ -262,7 +262,7 @@ void ConfigFile::renameSection(const String &oldName, const String &newName) {
// HACK: For now we just print a warning, for more info see the TODO
// below.
if (ns)
- warning("ConfigFile::renameSection: Section name \"%s\" already used", newName.c_str());
+ warning("INIFile::renameSection: Section name \"%s\" already used", newName.c_str());
else
os->name = newName;
}
@@ -274,7 +274,7 @@ void ConfigFile::renameSection(const String &oldName, const String &newName) {
}
-bool ConfigFile::hasKey(const String &key, const String &section) const {
+bool INIFile::hasKey(const String &key, const String &section) const {
assert(isValidName(key));
assert(isValidName(section));
@@ -284,7 +284,7 @@ bool ConfigFile::hasKey(const String &key, const String &section) const {
return s->hasKey(key);
}
-void ConfigFile::removeKey(const String &key, const String &section) {
+void INIFile::removeKey(const String &key, const String &section) {
assert(isValidName(key));
assert(isValidName(section));
@@ -293,7 +293,7 @@ void ConfigFile::removeKey(const String &key, const String &section) {
s->removeKey(key);
}
-bool ConfigFile::getKey(const String &key, const String &section, String &value) const {
+bool INIFile::getKey(const String &key, const String &section, String &value) const {
assert(isValidName(key));
assert(isValidName(section));
@@ -307,7 +307,7 @@ bool ConfigFile::getKey(const String &key, const String &section, String &value)
return true;
}
-void ConfigFile::setKey(const String &key, const String &section, const String &value) {
+void INIFile::setKey(const String &key, const String &section, const String &value) {
assert(isValidName(key));
assert(isValidName(section));
// TODO: Verify that value is valid, too. In particular, it shouldn't
@@ -329,13 +329,13 @@ void ConfigFile::setKey(const String &key, const String &section, const String &
}
}
-const ConfigFile::SectionKeyList ConfigFile::getKeys(const String &section) const {
+const INIFile::SectionKeyList INIFile::getKeys(const String &section) const {
const Section *s = getSection(section);
return s->getKeys();
}
-ConfigFile::Section *ConfigFile::getSection(const String &section) {
+INIFile::Section *INIFile::getSection(const String &section) {
for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
if (section.equalsIgnoreCase(i->name)) {
return &(*i);
@@ -344,7 +344,7 @@ ConfigFile::Section *ConfigFile::getSection(const String &section) {
return 0;
}
-const ConfigFile::Section *ConfigFile::getSection(const String &section) const {
+const INIFile::Section *INIFile::getSection(const String &section) const {
for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) {
if (section.equalsIgnoreCase(i->name)) {
return &(*i);
@@ -353,11 +353,11 @@ const ConfigFile::Section *ConfigFile::getSection(const String &section) const {
return 0;
}
-bool ConfigFile::Section::hasKey(const String &key) const {
+bool INIFile::Section::hasKey(const String &key) const {
return getKey(key) != 0;
}
-const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const {
+const INIFile::KeyValue* INIFile::Section::getKey(const String &key) const {
for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
if (key.equalsIgnoreCase(i->key)) {
return &(*i);
@@ -366,7 +366,7 @@ const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const
return 0;
}
-void ConfigFile::Section::setKey(const String &key, const String &value) {
+void INIFile::Section::setKey(const String &key, const String &value) {
for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
if (key.equalsIgnoreCase(i->key)) {
i->value = value;
@@ -380,7 +380,7 @@ void ConfigFile::Section::setKey(const String &key, const String &value) {
keys.push_back(newKV);
}
-void ConfigFile::Section::removeKey(const String &key) {
+void INIFile::Section::removeKey(const String &key) {
for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
if (key.equalsIgnoreCase(i->key)) {
keys.erase(i);
diff --git a/common/config-file.h b/common/ini-file.h
index 8bba851110..1d94ce7bdc 100644
--- a/common/config-file.h
+++ b/common/ini-file.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef COMMON_CONFIG_FILE_H
-#define COMMON_CONFIG_FILE_H
+#ifndef COMMON_INI_FILE_H
+#define COMMON_INI_FILE_H
#include "common/hash-str.h"
#include "common/list.h"
@@ -34,9 +34,6 @@ class WriteStream;
/**
* This class allows reading/writing INI style config files.
- * It is used by the ConfigManager for storage, but can also
- * be used by other code if it needs to read/write custom INI
- * files.
*
* Lines starting with a '#' are ignored (i.e. treated as comments).
* Some effort is made to preserve comments, though.
@@ -47,10 +44,8 @@ class WriteStream;
* from/to files, but of course is not appropriate for fast access.
* The main reason is that this class is indeed geared toward doing precisely
* that!
- * If you need fast access to the game config, use higher level APIs, like the
- * one provided by ConfigManager.
*/
-class ConfigFile {
+class INIFile {
public:
struct KeyValue {
String key;
@@ -60,12 +55,12 @@ public:
typedef List<KeyValue> SectionKeyList;
- /** A section in a config file. I.e. corresponds to something like this:
+ /** A section in a ini file. I.e. corresponds to something like this:
* [mySection]
* key=value
*
* Comments are also stored, to keep users happy who like editing their
- * config files manually.
+ * ini files manually.
*/
struct Section {
String name;
@@ -82,8 +77,8 @@ public:
typedef List<Section> SectionList;
public:
- ConfigFile();
- ~ConfigFile();
+ INIFile();
+ ~INIFile();
// TODO: Maybe add a copy constructor etc.?
@@ -95,7 +90,7 @@ public:
*/
static bool isValidName(const String &name);
- /** Reset everything stored in this config file. */
+ /** Reset everything stored in this ini file. */
void clear();
bool loadFromFile(const String &filename);
@@ -127,14 +122,6 @@ private:
const Section *getSection(const String &section) const;
};
-/*
-- ConfigMan owns a config file
-- allow direct access to that config file (for the launcher)
-- simplify and unify the regular ConfigMan API in exchange
-
-
-*/
-
} // End of namespace Common
#endif
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/math.h b/common/math.h
index b85ec0d22a..ba137101e4 100644
--- a/common/math.h
+++ b/common/math.h
@@ -52,14 +52,6 @@
#endif
#endif
-#ifndef M_SQRT1_2
- #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
-#endif
-
-#ifndef M_PI
- #define M_PI 3.14159265358979323846
-#endif
-
#ifndef FLT_MIN
#define FLT_MIN 1E-37
#endif
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..67c498df00 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -2,7 +2,6 @@ MODULE := common
MODULE_OBJS := \
archive.o \
- config-file.o \
config-manager.o \
coroutines.o \
dcl.o \
@@ -10,12 +9,12 @@ MODULE_OBJS := \
error.o \
EventDispatcher.o \
EventMapper.o \
- EventRecorder.o \
file.o \
fs.o \
gui_options.o \
hashmap.o \
iff_container.o \
+ ini-file.o \
installshield_cab.o \
language.o \
localization.o \
@@ -36,6 +35,7 @@ MODULE_OBJS := \
translation.o \
unarj.o \
unzip.o \
+ ustr.o \
util.o \
winexe.o \
winexe_ne.o \
@@ -51,5 +51,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/rdft.h b/common/rdft.h
index 3386940404..76e95c363a 100644
--- a/common/rdft.h
+++ b/common/rdft.h
@@ -20,7 +20,7 @@
*
*/
-// Based on eos' (I)RDFT code which is in turn
+// Based on xoreos' (I)RDFT code which is in turn
// Based upon the (I)RDFT code in FFmpeg
// Copyright (c) 2009 Alex Converse <alex dot converse at gmail dot com>
@@ -44,6 +44,40 @@ namespace Common {
*
* Used in engines:
* - scumm
+ *
+ *
+ * It has four modes:
+ *
+ * Below, n = 1 << bits
+ *
+ * (I)DFT_R2C:
+ * input:
+ * n real floats
+ * output:
+ * n/2 complex floats (stored as real part followed by imag part).
+ *
+ * The output represents the first half of the (I)DFT of the input.
+ * If F is the complex (I)DFT of the input, then
+ * output[0] = F[0] + i * F[n/2] and
+ * output[k] = F[k] for k = 1 .. n/2-1.
+ * Note that F[0] and F[k] are real since the input is real, and
+ * the remaining values of F can be reconstructed from symmetry if desired.
+ *
+ * (I)DFT_C2R:
+ * input:
+ * n/2 complex floats
+ * output:
+ * n real floats
+ *
+ * The input encodes a complex vector x of length n that has the
+ * required symmetry to have a real (I)DFT:
+ * x[0] = Re(input[0])
+ * x[k] = input[k] for k = 1 .. n/2-1
+ * x[n/2] = Im(input[0])
+ * x[k] = conj(input[n-k]) for k = n/2+1 .. n-1
+ * The output is then the real (I)DFT of x, divided by 2.
+ *
+ * TODO: Is this division by 2 intentional?
*/
class RDFT {
diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp
new file mode 100644
index 0000000000..7c438cbf69
--- /dev/null
+++ b/common/recorderfile.cpp
@@ -0,0 +1,716 @@
+/* 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);
+
+ _playbackParseState = kFileStateCheckFormat;
+}
+
+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/scummsys.h b/common/scummsys.h
index 291de87dc9..48dffc53a6 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -23,6 +23,10 @@
#ifndef COMMON_SCUMMSYS_H
#define COMMON_SCUMMSYS_H
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
// This is a convenience macro to test whether the compiler used is a GCC
// version, which is at least major.minor.
#define GCC_ATLEAST(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
@@ -144,6 +148,63 @@
#endif
#endif
+// The following math constants are usually defined by the system math.h header, but
+// they are not part of the ANSI C++ standards and so can NOT be relied upon to be
+// present i.e. when -std=c++11 is passed to GCC, enabling strict ANSI compliance.
+// As we rely on these being present, we define them if they are not set.
+
+#ifndef M_E
+ #define M_E 2.7182818284590452354 /* e */
+#endif
+
+#ifndef M_LOG2E
+ #define M_LOG2E 1.4426950408889634074 /* log_2 e */
+#endif
+
+#ifndef M_LOG10E
+ #define M_LOG10E 0.43429448190325182765 /* log_10 e */
+#endif
+
+#ifndef M_LN2
+ #define M_LN2 0.69314718055994530942 /* log_e 2 */
+#endif
+
+#ifndef M_LN10
+ #define M_LN10 2.30258509299404568402 /* log_e 10 */
+#endif
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846 /* pi */
+#endif
+
+#ifndef M_PI_2
+ #define M_PI_2 1.57079632679489661923 /* pi/2 */
+#endif
+
+#ifndef M_PI_4
+ #define M_PI_4 0.78539816339744830962 /* pi/4 */
+#endif
+
+#ifndef M_1_PI
+ #define M_1_PI 0.31830988618379067154 /* 1/pi */
+#endif
+
+#ifndef M_2_PI
+ #define M_2_PI 0.63661977236758134308 /* 2/pi */
+#endif
+
+#ifndef M_2_SQRTPI
+ #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
+#endif
+
+#ifndef M_SQRT2
+ #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#endif
+
+#ifndef M_SQRT1_2
+ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
+#endif
+
// Include our C++11 compatability header for pre-C++11 compilers.
#if __cplusplus < 201103L
#include "common/c++11-compat.h"
@@ -344,6 +405,8 @@
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned int uint;
+ typedef signed long long int64;
+ typedef unsigned long long uint64;
#endif
diff --git a/common/sinetables.cpp b/common/sinetables.cpp
index a6ec99469d..7338166d39 100644
--- a/common/sinetables.cpp
+++ b/common/sinetables.cpp
@@ -34,15 +34,15 @@ SineTable::SineTable(int bitPrecision) {
int m = 1 << _bitPrecision;
double freq = 2 * M_PI / m;
- _table = new float[m];
+ _table = new float[m / 2];
- // Table contains sin(2*pi*x/n) for 0<=x<=n/4,
- // followed by its reverse
- for (int i = 0; i <= m / 4; i++)
+ // Table contains sin(2*pi*i/m) for 0<=i<m/4,
+ // followed by m/2<=i<3m/4
+ for (int i = 0; i < m / 4; i++)
_table[i] = sin(i * freq);
- for (int i = 1; i < m / 4; i++)
- _table[m / 2 - i] = _table[i];
+ for (int i = 0; i < m / 4; i++)
+ _table[m / 4 + i] = -_table[i];
}
SineTable::~SineTable() {
diff --git a/common/sinetables.h b/common/sinetables.h
index 16e203f26d..3489663661 100644
--- a/common/sinetables.h
+++ b/common/sinetables.h
@@ -37,6 +37,13 @@ public:
/**
* Get pointer to table
+ *
+ * This table contains 2^bitPrecision/2 entries.
+ * The layout of this table is as follows:
+ * - Entries 0 up to (excluding) 2^bitPrecision/4:
+ * sin(0) till (excluding) sin(1/2*pi)
+ * - Entries 2^bitPrecision/4 up to (excluding) 2^bitPrecision/2:
+ * sin(pi) till (excluding) sin(3/2*pi)
*/
const float *getTable() { return _table; }
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..ea2db1d1d6 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);
@@ -229,6 +234,13 @@ public:
static String vformat(const char *fmt, va_list args);
public:
+ typedef char value_type;
+ /**
+ * Unsigned version of the underlying type. This can be used to cast
+ * individual string characters to bigger integer types without sign
+ * extension happening.
+ */
+ typedef unsigned char unsigned_type;
typedef char * iterator;
typedef const char * const_iterator;
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/unarj.cpp b/common/unarj.cpp
index fe3c17a2ac..e8aed7cbd1 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -95,6 +95,12 @@ class ArjDecoder {
public:
ArjDecoder(const ArjHeader *hdr) {
_compsize = hdr->compSize;
+ _compressed = 0;
+ _outstream = 0;
+ _bitbuf = 0;
+ _bytebuf = 0;
+ _bitcount = 0;
+ _blocksize = 0;
}
~ArjDecoder() {
@@ -112,7 +118,6 @@ public:
uint16 _bitbuf;
uint16 _bytebuf;
int32 _compsize;
- byte _subbitbuf;
int _bitcount;
void init_getbits();
@@ -132,9 +137,6 @@ public:
private:
byte _ntext[ARJ_FDICSIZ];
- int16 _getlen;
- int16 _getbuf;
-
uint16 _left[2 * ARJ_NC - 1];
uint16 _right[2 * ARJ_NC - 1];
byte _c_len[ARJ_NC];
@@ -656,7 +658,6 @@ void ArjDecoder::decode_f(int32 origsize) {
init_getbits();
ncount = 0;
- _getlen = _getbuf = 0;
r = 0;
while (ncount < (uint32)origsize) {
diff --git a/common/ustr.cpp b/common/ustr.cpp
new file mode 100644
index 0000000000..fbc831cb56
--- /dev/null
+++ b/common/ustr.cpp
@@ -0,0 +1,329 @@
+/* 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/ustr.h"
+#include "common/memorypool.h"
+#include "common/util.h"
+
+namespace Common {
+
+extern MemoryPool *g_refCountPool;
+
+static uint32 computeCapacity(uint32 len) {
+ // By default, for the capacity we use the next multiple of 32
+ return ((len + 32 - 1) & ~0x1F);
+}
+
+U32String::U32String(const value_type *str) : _size(0), _str(_storage) {
+ if (str == 0) {
+ _storage[0] = 0;
+ _size = 0;
+ } else {
+ uint32 len = 0;
+ const value_type *s = str;
+ while (*s++) {
+ ++len;
+ }
+ initWithCStr(str, len);
+ }
+}
+
+U32String::U32String(const value_type *str, uint32 len) : _size(0), _str(_storage) {
+ initWithCStr(str, len);
+}
+
+U32String::U32String(const value_type *beginP, const value_type *endP) : _size(0), _str(_storage) {
+ assert(endP >= beginP);
+ initWithCStr(beginP, endP - beginP);
+}
+
+U32String::U32String(const U32String &str)
+ : _size(str._size) {
+ if (str.isStorageIntern()) {
+ // String in internal storage: just copy it
+ memcpy(_storage, str._storage, _builtinCapacity * sizeof(value_type));
+ _str = _storage;
+ } else {
+ // String in external storage: use refcount mechanism
+ str.incRefCount();
+ _extern._refCount = str._extern._refCount;
+ _extern._capacity = str._extern._capacity;
+ _str = str._str;
+ }
+ assert(_str != 0);
+}
+
+U32String::~U32String() {
+ decRefCount(_extern._refCount);
+}
+
+U32String &U32String::operator=(const U32String &str) {
+ if (&str == this)
+ return *this;
+
+ if (str.isStorageIntern()) {
+ decRefCount(_extern._refCount);
+ _size = str._size;
+ _str = _storage;
+ memcpy(_str, str._str, (_size + 1) * sizeof(value_type));
+ } else {
+ str.incRefCount();
+ decRefCount(_extern._refCount);
+
+ _extern._refCount = str._extern._refCount;
+ _extern._capacity = str._extern._capacity;
+ _size = str._size;
+ _str = str._str;
+ }
+
+ return *this;
+}
+
+U32String &U32String::operator+=(const U32String &str) {
+ if (&str == this) {
+ return operator+=(U32String(str));
+ }
+
+ int len = str._size;
+ if (len > 0) {
+ ensureCapacity(_size + len, true);
+
+ memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type));
+ _size += len;
+ }
+ return *this;
+}
+
+U32String &U32String::operator+=(value_type c) {
+ ensureCapacity(_size + 1, true);
+
+ _str[_size++] = c;
+ _str[_size] = 0;
+
+ return *this;
+}
+
+bool U32String::equals(const U32String &x) const {
+ if (this == &x || _str == x._str) {
+ return true;
+ }
+
+ if (x.size() != _size) {
+ return false;
+ }
+
+ return !memcmp(_str, x._str, _size * sizeof(value_type));
+}
+
+bool U32String::contains(value_type x) const {
+ for (uint32 i = 0; i < _size; ++i) {
+ if (_str[i] == x) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void U32String::deleteChar(uint32 p) {
+ assert(p < _size);
+
+ makeUnique();
+ while (p++ < _size)
+ _str[p - 1] = _str[p];
+ _size--;
+}
+
+void U32String::clear() {
+ decRefCount(_extern._refCount);
+
+ _size = 0;
+ _str = _storage;
+ _storage[0] = 0;
+}
+
+void U32String::toLowercase() {
+ makeUnique();
+ for (uint32 i = 0; i < _size; ++i) {
+ if (_str[i] < 128) {
+ _str[i] = tolower(_str[i]);
+ }
+ }
+}
+
+void U32String::toUppercase() {
+ makeUnique();
+ for (uint32 i = 0; i < _size; ++i) {
+ if (_str[i] < 128) {
+ _str[i] = toupper(_str[i]);
+ }
+ }
+}
+
+uint32 U32String::find(const U32String &str, uint32 pos) const {
+ if (pos >= _size) {
+ return npos;
+ }
+
+ const value_type *strP = str.c_str();
+
+ for (const_iterator cur = begin() + pos; *cur; ++cur) {
+ uint i = 0;
+ while (true) {
+ if (!strP[i]) {
+ return cur - begin();
+ }
+
+ if (cur[i] != strP[i]) {
+ break;
+ }
+
+ ++i;
+ }
+ }
+
+ return npos;
+}
+
+void U32String::makeUnique() {
+ ensureCapacity(_size, true);
+}
+
+void U32String::ensureCapacity(uint32 new_size, bool keep_old) {
+ bool isShared;
+ uint32 curCapacity, newCapacity;
+ value_type *newStorage;
+ int *oldRefCount = _extern._refCount;
+
+ if (isStorageIntern()) {
+ isShared = false;
+ curCapacity = _builtinCapacity;
+ } else {
+ isShared = (oldRefCount && *oldRefCount > 1);
+ curCapacity = _extern._capacity;
+ }
+
+ // Special case: If there is enough space, and we do not share
+ // the storage, then there is nothing to do.
+ if (!isShared && new_size < curCapacity)
+ return;
+
+ if (isShared && new_size < _builtinCapacity) {
+ // We share the storage, but there is enough internal storage: Use that.
+ newStorage = _storage;
+ newCapacity = _builtinCapacity;
+ } else {
+ // We need to allocate storage on the heap!
+
+ // Compute a suitable new capacity limit
+ // If the current capacity is sufficient we use the same capacity
+ if (new_size < curCapacity)
+ newCapacity = curCapacity;
+ else
+ newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
+
+ // Allocate new storage
+ newStorage = new value_type[newCapacity];
+ assert(newStorage);
+ }
+
+ // Copy old data if needed, elsewise reset the new storage.
+ if (keep_old) {
+ assert(_size < newCapacity);
+ memcpy(newStorage, _str, (_size + 1) * sizeof(value_type));
+ } else {
+ _size = 0;
+ newStorage[0] = 0;
+ }
+
+ // Release hold on the old storage ...
+ decRefCount(oldRefCount);
+
+ // ... in favor of the new storage
+ _str = newStorage;
+
+ if (!isStorageIntern()) {
+ // Set the ref count & capacity if we use an external storage.
+ // It is important to do this *after* copying any old content,
+ // else we would override data that has not yet been copied!
+ _extern._refCount = 0;
+ _extern._capacity = newCapacity;
+ }
+}
+
+void U32String::incRefCount() const {
+ assert(!isStorageIntern());
+ if (_extern._refCount == 0) {
+ if (g_refCountPool == 0) {
+ g_refCountPool = new MemoryPool(sizeof(int));
+ assert(g_refCountPool);
+ }
+
+ _extern._refCount = (int *)g_refCountPool->allocChunk();
+ *_extern._refCount = 2;
+ } else {
+ ++(*_extern._refCount);
+ }
+}
+
+void U32String::decRefCount(int *oldRefCount) {
+ if (isStorageIntern())
+ return;
+
+ if (oldRefCount) {
+ --(*oldRefCount);
+ }
+ if (!oldRefCount || *oldRefCount <= 0) {
+ // The ref count reached zero, so we free the string storage
+ // and the ref count storage.
+ if (oldRefCount) {
+ assert(g_refCountPool);
+ g_refCountPool->freeChunk(oldRefCount);
+ }
+ delete[] _str;
+
+ // Even though _str points to a freed memory block now,
+ // we do not change its value, because any code that calls
+ // decRefCount will have to do this afterwards anyway.
+ }
+}
+
+void U32String::initWithCStr(const value_type *str, uint32 len) {
+ assert(str);
+
+ _storage[0] = 0;
+
+ _size = len;
+
+ if (len >= _builtinCapacity) {
+ // Not enough internal storage, so allocate more
+ _extern._capacity = computeCapacity(len+1);
+ _extern._refCount = 0;
+ _str = new value_type[_extern._capacity];
+ assert(_str != 0);
+ }
+
+ // Copy the string into the storage area
+ memmove(_str, str, len * sizeof(value_type));
+ _str[len] = 0;
+}
+
+} // End of namespace Common
diff --git a/common/ustr.h b/common/ustr.h
new file mode 100644
index 0000000000..ab9dac70de
--- /dev/null
+++ b/common/ustr.h
@@ -0,0 +1,194 @@
+/* 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_USTR_H
+#define COMMON_USTR_H
+
+#include "common/scummsys.h"
+
+namespace Common {
+
+/**
+ * Very simple string class for UTF-32 strings in ScummVM. The main intention
+ * behind this class is to feature a simple way of displaying UTF-32 strings
+ * through the Graphics::Font API.
+ *
+ * Please note that operations like equals, deleteCharacter, toUppercase, etc.
+ * are only very simplified convenience operations. They might not fully work
+ * as you would expect for a proper UTF-32 string class.
+ *
+ * The presence of \0 characters in the string will cause undefined
+ * behavior in some operations.
+ */
+class U32String {
+public:
+ static const uint32 npos = 0xFFFFFFFF;
+
+ typedef uint32 value_type;
+ typedef uint32 unsigned_type;
+private:
+ /**
+ * The size of the internal storage. Increasing this means less heap
+ * allocations are needed, at the cost of more stack memory usage,
+ * and of course lots of wasted memory.
+ */
+ static const uint32 _builtinCapacity = 32;
+
+ /**
+ * Length of the string.
+ */
+ uint32 _size;
+
+ /**
+ * Pointer to the actual string storage. Either points to _storage,
+ * or to a block allocated on the heap via malloc.
+ */
+ value_type *_str;
+
+
+ union {
+ /**
+ * Internal string storage.
+ */
+ value_type _storage[_builtinCapacity];
+ /**
+ * External string storage data -- the refcounter, and the
+ * capacity of the string _str points to.
+ */
+ struct {
+ mutable int *_refCount;
+ uint32 _capacity;
+ } _extern;
+ };
+
+ inline bool isStorageIntern() const {
+ return _str == _storage;
+ }
+
+public:
+ /** Construct a new empty string. */
+ U32String() : _size(0), _str(_storage) { _storage[0] = 0; }
+
+ /** Construct a new string from the given NULL-terminated C string. */
+ explicit U32String(const value_type *str);
+
+ /** Construct a new string containing exactly len characters read from address str. */
+ U32String(const value_type *str, uint32 len);
+
+ /** Construct a new string containing the characters between beginP (including) and endP (excluding). */
+ U32String(const value_type *beginP, const value_type *endP);
+
+ /** Construct a copy of the given string. */
+ U32String(const U32String &str);
+
+ ~U32String();
+
+ U32String &operator=(const U32String &str);
+ U32String &operator+=(const U32String &str);
+ U32String &operator+=(value_type c);
+
+ /**
+ * Equivalence comparison operator.
+ * @see equals
+ */
+ bool operator==(const U32String &x) const { return equals(x); }
+
+ /**
+ * Compares whether two U32String are the same based on memory comparison.
+ * This does *not* do comparison based on canonical equivalence.
+ */
+ bool equals(const U32String &x) const;
+
+ bool contains(value_type x) const;
+
+ inline const value_type *c_str() const { return _str; }
+ inline uint32 size() const { return _size; }
+
+ inline bool empty() const { return (_size == 0); }
+
+ value_type operator[](int idx) const {
+ assert(_str && idx >= 0 && idx < (int)_size);
+ return _str[idx];
+ }
+
+ /**
+ * Removes the value at position p from the string.
+ * Using this on decomposed characters will not remove the whole
+ * character!
+ */
+ void deleteChar(uint32 p);
+
+ /** Clears the string, making it empty. */
+ void clear();
+
+ /**
+ * Convert all characters in the string to lowercase.
+ *
+ * Be aware that this only affects the case of ASCII characters. All
+ * other characters will not be touched at all.
+ */
+ void toLowercase();
+
+ /**
+ * Convert all characters in the string to uppercase.
+ *
+ * Be aware that this only affects the case of ASCII characters. All
+ * other characters will not be touched at all.
+ */
+ void toUppercase();
+
+ uint32 find(const U32String &str, uint32 pos = 0) const;
+
+ typedef value_type * iterator;
+ typedef const value_type * const_iterator;
+
+ iterator begin() {
+ // Since the user could potentially
+ // change the string via the returned
+ // iterator we have to assure we are
+ // pointing to a unique storage.
+ makeUnique();
+
+ return _str;
+ }
+
+ iterator end() {
+ return begin() + size();
+ }
+
+ const_iterator begin() const {
+ return _str;
+ }
+
+ const_iterator end() const {
+ return begin() + size();
+ }
+private:
+ void makeUnique();
+ void ensureCapacity(uint32 new_size, bool keep_old);
+ void incRefCount() const;
+ void decRefCount(int *oldRefCount);
+ void initWithCStr(const value_type *str, uint32 len);
+};
+
+} // End of namespace Common
+
+#endif
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.cpp b/common/winexe.cpp
index 7cfc140452..877ab6baa1 100644
--- a/common/winexe.cpp
+++ b/common/winexe.cpp
@@ -73,7 +73,7 @@ String WinResourceID::toString() const {
if (_idType == kIDTypeString)
return _name;
else if (_idType == kIDTypeNumerical)
- return String::format("%08x", _id);
+ return String::format("0x%08x", _id);
return "";
}
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp
index 8690f6795b..8ab7e707bb 100644
--- a/common/winexe_ne.cpp
+++ b/common/winexe_ne.cpp
@@ -187,8 +187,8 @@ uint32 NEResources::getResourceTableOffset() {
static const char *s_resTypeNames[] = {
"", "cursor", "bitmap", "icon", "menu", "dialog", "string",
"font_dir", "font", "accelerator", "rc_data", "msg_table",
- "group_cursor", "group_icon", "version", "dlg_include",
- "plug_play", "vxd", "ani_cursor", "ani_icon", "html",
+ "group_cursor", "", "group_icon", "", "version", "dlg_include",
+ "", "plug_play", "vxd", "ani_cursor", "ani_icon", "html",
"manifest"
};
@@ -200,9 +200,16 @@ bool NEResources::readResourceTable(uint32 offset) {
return false;
uint32 align = 1 << _exe->readUint16LE();
-
uint16 typeID = _exe->readUint16LE();
+
while (typeID != 0) {
+ // High bit of the type means integer type
+ WinResourceID type;
+ if (typeID & 0x8000)
+ type = typeID & 0x7FFF;
+ else
+ type = getResourceString(*_exe, offset + typeID);
+
uint16 resCount = _exe->readUint16LE();
_exe->skip(4); // reserved
@@ -218,17 +225,18 @@ bool NEResources::readResourceTable(uint32 offset) {
res.handle = _exe->readUint16LE();
res.usage = _exe->readUint16LE();
- res.type = typeID;
+ res.type = type;
- if ((id & 0x8000) == 0)
- res.id = getResourceString(*_exe, offset + id);
- else
+ // High bit means integer type
+ if (id & 0x8000)
res.id = id & 0x7FFF;
+ else
+ res.id = getResourceString(*_exe, offset + id);
- if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames)))
+ 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());
else
- debug(2, "Found resource %04x %s", typeID, res.id.toString().c_str());
+ debug(2, "Found resource %s %s", type.toString().c_str(), res.id.toString().c_str());
_resources.push_back(res);
}
@@ -257,7 +265,7 @@ String NEResources::getResourceString(SeekableReadStream &exe, uint32 offset) {
return string;
}
-const NEResources::Resource *NEResources::findResource(uint16 type, WinResourceID id) const {
+const NEResources::Resource *NEResources::findResource(const WinResourceID &type, const WinResourceID &id) const {
for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
if (it->type == type && it->id == id)
return &*it;
@@ -265,7 +273,7 @@ const NEResources::Resource *NEResources::findResource(uint16 type, WinResourceI
return 0;
}
-SeekableReadStream *NEResources::getResource(uint16 type, WinResourceID id) {
+SeekableReadStream *NEResources::getResource(const WinResourceID &type, const WinResourceID &id) {
const Resource *res = findResource(type, id);
if (!res)
@@ -275,7 +283,7 @@ SeekableReadStream *NEResources::getResource(uint16 type, WinResourceID id) {
return _exe->readStream(res->size);
}
-const Array<WinResourceID> NEResources::getIDList(uint16 type) const {
+const Array<WinResourceID> NEResources::getIDList(const WinResourceID &type) const {
Array<WinResourceID> idArray;
for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
diff --git a/common/winexe_ne.h b/common/winexe_ne.h
index 4a1b2343df..3f50b5cc54 100644
--- a/common/winexe_ne.h
+++ b/common/winexe_ne.h
@@ -34,27 +34,27 @@ class SeekableReadStream;
/** The default Windows resources. */
enum NEResourceType {
- kNECursor = 0x8001,
- kNEBitmap = 0x8002,
- kNEIcon = 0x8003,
- kNEMenu = 0x8004,
- kNEDialog = 0x8005,
- kNEString = 0x8006,
- kNEFontDir = 0x8007,
- kNEFont = 0x8008,
- kNEAccelerator = 0x8009,
- kNERCData = 0x800A,
- kNEMessageTable = 0x800B,
- kNEGroupCursor = 0x800C,
- kNEGroupIcon = 0x800D,
- kNEVersion = 0x8010,
- kNEDlgInclude = 0x8011,
- kNEPlugPlay = 0x8013,
- kNEVXD = 0x8014,
- kNEAniCursor = 0x8015,
- kNEAniIcon = 0x8016,
- kNEHTML = 0x8017,
- kNEManifest = 0x8018
+ kNECursor = 0x01,
+ kNEBitmap = 0x02,
+ kNEIcon = 0x03,
+ kNEMenu = 0x04,
+ kNEDialog = 0x05,
+ kNEString = 0x06,
+ kNEFontDir = 0x07,
+ kNEFont = 0x08,
+ kNEAccelerator = 0x09,
+ kNERCData = 0x0A,
+ kNEMessageTable = 0x0B,
+ kNEGroupCursor = 0x0C,
+ kNEGroupIcon = 0x0E,
+ kNEVersion = 0x10,
+ kNEDlgInclude = 0x11,
+ kNEPlugPlay = 0x13,
+ kNEVXD = 0x14,
+ kNEAniCursor = 0x15,
+ kNEAniIcon = 0x16,
+ kNEHTML = 0x17,
+ kNEManifest = 0x18
};
/**
@@ -81,17 +81,17 @@ public:
bool loadFromEXE(SeekableReadStream *stream);
/** Return a list of resources for a given type. */
- const Array<WinResourceID> getIDList(uint16 type) const;
+ const Array<WinResourceID> getIDList(const WinResourceID &type) const;
/** Return a stream to the specified resource (or 0 if non-existent). */
- SeekableReadStream *getResource(uint16 type, WinResourceID id);
+ SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &id);
private:
/** A resource. */
struct Resource {
WinResourceID id;
- uint16 type; ///< Type of the resource.
+ WinResourceID type; ///< Type of the resource.
uint32 offset; ///< Offset within the EXE.
uint32 size; ///< Size of the data.
@@ -112,7 +112,7 @@ private:
bool readResourceTable(uint32 offset);
/** Find a specific resource. */
- const Resource *findResource(uint16 type, WinResourceID id) const;
+ const Resource *findResource(const WinResourceID &type, const WinResourceID &id) const;
/** Read a resource string. */
static String getResourceString(SeekableReadStream &exe, uint32 offset);
diff --git a/common/zlib.cpp b/common/zlib.cpp
index 920338e57e..f1a298a9f1 100644
--- a/common/zlib.cpp
+++ b/common/zlib.cpp
@@ -27,6 +27,7 @@
#include "common/ptr.h"
#include "common/util.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#if defined(USE_ZLIB)
#ifdef __SYMBIAN32__
@@ -158,10 +159,11 @@ protected:
uint32 _pos;
uint32 _origSize;
bool _eos;
+ bool _shownBackwardSeekingWarning;
public:
- GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() {
+ GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream(), _shownBackwardSeekingWarning(false) {
assert(w != 0);
// Verify file header is correct
@@ -241,13 +243,17 @@ public:
}
bool seek(int32 offset, int whence = SEEK_SET) {
int32 newPos = 0;
- assert(whence != SEEK_END); // SEEK_END not supported
switch (whence) {
case SEEK_SET:
newPos = offset;
break;
case SEEK_CUR:
newPos = _pos + offset;
+ break;
+ case SEEK_END:
+ // NOTE: This can be an expensive operation (see below).
+ newPos = size() + offset;
+ break;
}
assert(newPos >= 0);
@@ -256,9 +262,15 @@ public:
// To search backward, we have to restart the whole decompression
// from the start of the file. A rather wasteful operation, best
// to avoid it. :/
-#if DEBUG
- warning("Backward seeking in GZipReadStream detected");
-#endif
+
+ if (!_shownBackwardSeekingWarning) {
+ // We only throw this warning once per stream, to avoid
+ // getting the console swarmed with warnings when consecutive
+ // seeks are made.
+ warning("Backward seeking in GZipReadStream detected");
+ _shownBackwardSeekingWarning = true;
+ }
+
_pos = 0;
_wrapped->seek(0, SEEK_SET);
_zlibErr = inflateReset(&_stream);
diff --git a/configure b/configure
index 5016a86239..d454591f08 100755
--- a/configure
+++ b/configure
@@ -97,7 +97,9 @@ add_feature() {
_srcdir=`dirname $0`
# Read list of engines
-. $_srcdir/engines/configure.engines
+for i in $_srcdir/engines/*/configure.engine; do
+ . "$i"
+done
#
# Default settings
@@ -113,7 +115,9 @@ _seq_midi=auto
_sndio=auto
_timidity=auto
_zlib=auto
+_mpeg2=auto
_sparkle=auto
+_jpeg=auto
_png=auto
_theoradec=auto
_faad=auto
@@ -138,9 +142,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
@@ -164,7 +169,7 @@ _windres=windres
_stagingpath="staging"
_win32path="c:/scummvm"
_aos4path="Games:ScummVM"
-_staticlibpath=/sw
+_staticlibpath=
_sdlconfig=sdl-config
_freetypeconfig=freetype-config
_sdlpath="$PATH"
@@ -186,6 +191,7 @@ add_feature faad "libfaad" "_faad"
add_feature flac "FLAC" "_flac"
add_feature freetype2 "FreeType2" "_freetype2"
add_feature mad "MAD" "_mad"
+add_feature jpeg "JPEG" "_jpeg"
add_feature png "PNG" "_png"
add_feature theoradec "libtheoradec" "_theoradec"
add_feature vorbis "Vorbis file support" "_vorbis _tremor"
@@ -816,7 +822,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 +851,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
@@ -860,6 +866,7 @@ Special configuration feature:
motomagx for MotoMAGX
n64 for Nintendo 64
openpandora for OpenPandora
+ ouya for OUYA
ps2 for PlayStation 2
ps3 for PlayStation 3
psp for PlayStation Portable
@@ -898,6 +905,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,9 +935,15 @@ 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]
+ --with-jpeg-prefix=DIR Prefix where libjpeg is installed (optional)
+ --disable-jpeg disable JPEG decoder [autodetect]
+
--with-png-prefix=DIR Prefix where libpng is installed (optional)
--disable-png disable PNG decoder [autodetect]
@@ -1004,6 +1021,10 @@ 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-jpeg) _jpeg=no ;;
+ --enable-jpeg) _jpeg=yes ;;
--disable-png) _png=no ;;
--enable-png) _png=yes ;;
--disable-theoradec) _theoradec=no ;;
@@ -1036,6 +1057,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 +1066,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"
@@ -1078,6 +1106,11 @@ for ac_option in $@; do
MAD_CFLAGS="-I$arg/include"
MAD_LIBS="-L$arg/lib"
;;
+ --with-jpeg-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ JPEG_CFLAGS="-I$arg/include"
+ JPEG_LIBS="-L$arg/lib"
+ ;;
--with-png-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
PNG_CFLAGS="-I$arg/include"
@@ -1238,7 +1271,7 @@ get_system_exe_extension $guessed_host
NATIVEEXEEXT=$_exeext
case $_host in
-android | android-v7a)
+android | android-v7a | ouya)
_host_os=android
_host_cpu=arm
_host_alias=arm-linux-androideabi
@@ -1247,16 +1280,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 +1405,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 +1519,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 +1560,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 +1759,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 +1795,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 +1859,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() {
@@ -2024,6 +2053,12 @@ case $_host_os in
CXXFLAGS="$CXXFLAGS -mfpu=vfp"
LDFLAGS="$LDFLAGS -Wl,--fix-cortex-a8"
;;
+ ouya)
+ CXXFLAGS="$CXXFLAGS -march=armv7-a"
+ CXXFLAGS="$CXXFLAGS -mtune=cortex-a9"
+ CXXFLAGS="$CXXFLAGS -mfloat-abi=softfp"
+ CXXFLAGS="$CXXFLAGS -mfpu=neon"
+ ;;
esac
CXXFLAGS="$CXXFLAGS --sysroot=$ANDROID_NDK/platforms/android-4/arch-arm"
CXXFLAGS="$CXXFLAGS -fpic"
@@ -2051,16 +2086,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
@@ -2099,6 +2124,24 @@ case $_host_os in
LDFLAGS="-L${macport_prefix}/lib $LDFLAGS"
CXXFLAGS="-I${macport_prefix}/include $CXXFLAGS"
+
+ if test -z "$_staticlibpath"; then
+ _staticlibpath=${macport_prefix}
+ echo "Set staticlib-prefix to ${_staticlibpath}"
+ fi
+ fi
+ # If _staticlibpath is not set yet try first /sw (fink) then /usr/local
+ # (the macports case is handled above).
+ if test -z "$_staticlibpath"; then
+ if test -d "/sw"; then
+ _staticlibpath=/sw
+ echo "Set staticlib-prefix to ${_staticlibpath}"
+ elif test -d "/usr/local"; then
+ _staticlibpath=/usr/local
+ echo "Set staticlib-prefix to ${_staticlibpath}"
+ else
+ echo "Could not determine prefix for static libraries"
+ fi
fi
;;
dreamcast)
@@ -2176,7 +2219,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 +2281,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"
@@ -2298,7 +2347,7 @@ if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
echo "Cross-compiling to $_host"
case "$_host" in
- android | android-v7a)
+ android | android-v7a | ouya)
# we link a .so as default
LDFLAGS="$LDFLAGS -shared"
LDFLAGS="$LDFLAGS -Wl,-Bsymbolic,--no-undefined"
@@ -2316,22 +2365,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 +2414,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 +2678,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 +2740,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 +2747,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 +2823,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 +2907,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 +2920,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
@@ -2915,7 +2967,7 @@ case $_host_os in
amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp | wii | wince)
_posix=no
;;
- android | beos* | bsd* | darwin* | freebsd* | gph-linux | haiku* | hpux* | iphone | irix* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
+ android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
_posix=yes
;;
os2-emx*)
@@ -3071,7 +3123,7 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive
'
;;
- linux*)
+ linux* | gnu* | k*bsd*-gnu*)
_plugin_prefix="lib"
_plugin_suffix=".so"
CXXFLAGS="$CXXFLAGS -fPIC"
@@ -3326,6 +3378,32 @@ define_in_config_h_if_yes "$_alsa" 'USE_ALSA'
echo "$_alsa"
#
+# Check for libjpeg
+#
+echocheck "libjpeg >= v6b"
+if test "$_jpeg" = auto ; then
+ _jpeg=no
+ cat > $TMPC << EOF
+#include <stdio.h>
+#include <jpeglib.h>
+int main(void) {
+#if JPEG_LIB_VERSION >= 62
+#else
+ syntax error
+#endif
+ return 0;
+}
+EOF
+ cc_check $JPEG_CFLAGS $JPEG_LIBS -ljpeg && _jpeg=yes
+fi
+if test "$_jpeg" = yes ; then
+ LIBS="$LIBS $JPEG_LIBS -ljpeg"
+ INCLUDES="$INCLUDES $JPEG_CFLAGS"
+fi
+define_in_config_if_yes "$_jpeg" 'USE_JPEG'
+echo "$_jpeg"
+
+#
# Check for PNG
#
echocheck "PNG >= 1.2.8"
@@ -3341,10 +3419,10 @@ int main(void) {
return 0;
}
EOF
- cc_check $PNG_CFLAGS $PNG_LIBS -lpng && _png=yes
+ cc_check $PNG_CFLAGS $PNG_LIBS -lpng -lz && _png=yes
fi
if test "$_png" = yes ; then
- LIBS="$LIBS $PNG_LIBS -lpng"
+ LIBS="$LIBS $PNG_LIBS -lpng -lz"
INCLUDES="$INCLUDES $PNG_CFLAGS"
fi
define_in_config_if_yes "$_png" 'USE_PNG'
@@ -3461,6 +3539,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 +3687,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 +3845,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 +3921,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 +4014,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 +4088,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
@@ -4053,8 +4199,18 @@ for engine in $_engines; do
fi
done
-# Prepare the information to be shown
+# Sort engines to place our headline engine at start...
+# No technical reason, just historical convention
+headline_engine=scumm
+_sorted_engines="${headline_engine}"
for engine in $_engines; do
+ if test "${engine}" != "${headline_engine}" ; then
+ _sorted_engines="${_sorted_engines} ${engine}"
+ fi
+done
+
+# Prepare the information to be shown
+for engine in $_sorted_engines; do
if test "`get_engine_sub $engine`" = "no" ; then
# It's a main engine
prepare_engine_build_strings $engine
@@ -4236,3 +4392,59 @@ include \$(srcdir)/Makefile
EOF
fi
+
+# Ensure engines folder exists prior to trying to generate
+# files into it (used for out-of-tree-builds)
+mkdir -p engines
+
+echo "Creating engines/engines.mk"
+cat > engines/engines.mk << EOF
+# This file is automatically generated by configure
+# DO NOT EDIT MANUALLY
+# This file is being included by "Makefile.common"
+EOF
+
+for engine in $_sorted_engines; do
+ j=`echo $engine | tr '[:lower:]' '[:upper:]'`
+ if test "`get_engine_sub $engine`" = "no" ; then
+ # main engine
+ cat >> engines/engines.mk << EOF
+
+ifdef ENABLE_$j
+DEFINES += -DENABLE_$j=\$(ENABLE_$j)
+MODULES += engines/$engine
+EOF
+
+ for subeng in `get_engine_subengines $engine` ; do
+ k=`echo $subeng | tr '[:lower:]' '[:upper:]'`
+ cat >> engines/engines.mk << EOF
+
+ifdef ENABLE_$k
+DEFINES += -DENABLE_$k
+endif
+EOF
+ done
+
+ cat >> engines/engines.mk << EOF
+endif
+EOF
+ fi
+done
+
+echo "Creating engines/plugins_table.h"
+cat > engines/plugins_table.h << EOF
+/* This file is automatically generated by configure */
+/* DO NOT EDIT MANUALLY */
+// This file is being included by "base/plugins.cpp"
+EOF
+
+for engine in $_sorted_engines; do
+ if test "`get_engine_sub $engine`" = "no" ; then
+ j=`echo $engine | tr '[:lower:]' '[:upper:]'`
+ cat >> engines/plugins_table.h << EOF
+#if PLUGIN_ENABLED_STATIC($j)
+LINK_PLUGIN($j)
+#endif
+EOF
+ fi
+done
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/convbdf.cpp b/devtools/convbdf.cpp
index c8b1fb7d6d..69728eb9fd 100644
--- a/devtools/convbdf.cpp
+++ b/devtools/convbdf.cpp
@@ -20,6 +20,10 @@
*
*/
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
#include <fstream>
#include <string>
#include <stdio.h>
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..693e277b91
--- /dev/null
+++ b/devtools/create_mortdat/create_mortdat.cpp
@@ -0,0 +1,275 @@
+/* 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 "common/endian.h"
+#include "create_mortdat.h"
+#include "enginetext.h"
+#include "gametext.h"
+#include "menudata.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);
+}
+
+/**
+ * Write out the data for the English menu
+ */
+void writeMenuData(const char *menuData, int languageId) {
+ // Write out a section header to the output file and the menu data
+ const char menuHeader[4] = { 'M', 'E', 'N', 'U' };
+ outputFile.write(menuHeader, 4); // Section Id
+ int size = strlen(menuData) / 8 + 1; // Language code + Menu data size
+ outputFile.writeWord(size);
+
+ outputFile.writeByte(languageId);
+ // Write each 8-characters block as a byte (one bit per character)
+ // ' ' -> 0, anything else -> 1
+ byte value = 0;
+ int valueCpt = 0;
+ const char* str = menuData;
+ while (*str != 0) {
+ if (*(str++) != ' ')
+ value |= (1 << (7 - valueCpt));
+ ++valueCpt;
+ if (valueCpt == 8) {
+ outputFile.writeByte(value);
+ value = 0;
+ valueCpt = 0;
+ }
+ }
+}
+
+void writeMenuBlock() {
+ writeMenuData(menuDataEn, 1);
+ writeMenuData(menuDataDe, 2);
+}
+
+void writeVerbNums(const int *verbs, int languageId) {
+ // Write out a section header to the output file
+ const char menuHeader[4] = { 'V', 'E', 'R', 'B' };
+ outputFile.write(menuHeader, 4); // Section Id
+ int size = 52 + 1; // Language code + 26 words
+ outputFile.writeWord(size);
+
+ outputFile.writeByte(languageId);
+ for (int i = 0; i < 26; i++)
+ outputFile.writeWord(verbs[i]);
+}
+
+void writeMenuVerbs() {
+ writeVerbNums(verbsEn, 1);
+ writeVerbNums(verbsFr, 0);
+ writeVerbNums(verbsDe, 2);
+}
+
+void process() {
+ writeFontBlock();
+ writeGameStrings();
+ writeEngineStrings();
+ writeMenuVerbs();
+ writeMenuBlock();
+}
+
+/**
+ * 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..e5007ae653
--- /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 2
+
+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..4f7b1f9776
--- /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 optician!). 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 precautions 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$",
+ "It is not my 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 occupations? He should take 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?$",
+ "Oh for that I trust her! She knows how to keep herself busy$",
+ "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 have no issue with this person$",
+ "He is a resourceful businessman. He sometimes tries to swim upstream but... he will always find a way to make it work$",
+ "They are all boring .. No! Not even that .. Even if .. some of them ..$",
+ "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$",
+ "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$",
+ "Nice feathers, but a bird's brain... Ask her husband$",
+ "Is it for an appointment?$",
+ "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!$",
+ "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!$",
+ "You can either see through walls 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$",
+ "I've always wondered why some people fancied her!$",
+ "If the room is closed, ask Leo$",
+ "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$",
+ "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$",
+ " close$",
+ " eat$",
+ " enter$",
+ " force$",
+ " knock$",
+ " leave$",
+ " lift$",
+ " listen$",
+ " look$",
+ " open$",
+ " place$",
+ " read$",
+ " scratch$",
+ " search$",
+ " sleep$",
+ " smell$",
+ " sound$",
+ " take$",
+ " turn$",
+ " wait$",
+ " hide yourself$",
+ " look$",
+ " put$",
+ " read$",
+ " search$",
+ " 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/menudata.h b/devtools/create_mortdat/menudata.h
new file mode 100644
index 0000000000..ec8724135c
--- /dev/null
+++ b/devtools/create_mortdat/menudata.h
@@ -0,0 +1,143 @@
+/* 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 MENUDATA_H
+#define MENUDATA_H
+
+const char *menuDataEn =
+ " @@@ "
+ " @ "
+ " @ @ @@ @@@ @@@ "
+ " @ @ @ @ @ "
+ " @ @ @ @ @ "
+ " @ @ @ @ @ "
+ "@@@ @@@ @@ @@ "
+ " "
+ " @@ @@ "
+ " @@ @ @ "
+ " @ @ @ @ @@@ @@@ @@@"
+ " @ @ @ @ @ @ @ "
+ " @ @ @ @ @ @ "
+ " @ @ @ @ @ @ "
+ "@@@ @@@ @@@@ @@ "
+ " "
+ " @ @ "
+ " @@ @ "
+ " @ @ @@@@ @@@@ "
+ " @ @ @ @ @ "
+ " @@@@@ @ @ "
+ " @ @ @ @ @ "
+ "@@@ @@@ @@@ @@ "
+ " "
+ " @@@@@ @@@ @@@"
+ " @ @ @ @ @"
+ " @ @@@ @ @ "
+ " @@@@ @ @ @ @@@ "
+ " @ @@@@@ @ @ "
+ " @ @ @ @ @ "
+ "@@@@@@ @@@ @@@ @@@ "
+ " "
+ "@@@@@@@ @@@ @@@ "
+ "@ @ @ @ @ "
+ " @ @@@@ @ @ @@"
+ " @ @ @ @ @@ @ "
+ " @ @ @ @ @ @@ "
+ " @ @ @ @ @ @ "
+ "@@@ @@@@ @@@ @@@ @@@"
+ " "
+ " @@@@@@@ @ @@@ "
+ " @ @ @ "
+ " @ @ @@ @ @@@ "
+ " @@@@ @ @ @ @"
+ " @ @ @ @ @@@@@ "
+ " @ @ @ @ "
+ "@@@ @@@ @@@ @@@ "
+ " ";
+
+const char *menuDataDe =
+ " @@@ @@ "
+ " @ @ "
+ " @ @ @@ @ @@@@"
+ " @ @ @ @@@ @ @"
+ " @ @ @ @ @ @ @ "
+ " @ @ @ @ @ @ @ "
+ "@@@ @@@ @@ @@ @@ @@@@ "
+ " "
+ " @@@@@@ @ @@ "
+ " @ @ @ "
+ " @ @ @@ @@@@ @ "
+ " @@@@ @ @ @ @@@ "
+ " @ @ @ @ @ @ "
+ " @ @ @ @ @ @ @ "
+ "@@ @@ @@@ @@@ @@ @@"
+ " "
+ " @ @@ @ "
+ " @@@ @ @ "
+ " @ @ @ @@ @@@@ "
+ " @ @ @ @ @ "
+ " @@@@@ @@@ @ "
+ " @ @ @ @ @ "
+ "@@@ @@@ @@@ @@ @@ "
+ " "
+ " @@@ @@ "
+ " @ @ "
+ " @ @@@@ @ "
+ " @ @ @ @@@ "
+ " @ @ @ @ "
+ " @ @ @ @ @ "
+ " @@@ @@@ @@ @@ "
+ " "
+ " @@@@@@ "
+ " @ @ @@ "
+ " @ @ @@@ @ @@@ "
+ " @@@@ @ @ @@@@ @ @"
+ " @ @ @@@@@ @ @ @@@@ "
+ " @ @ @ @ @ @ "
+ "@@ @@ @@@ @@@ @@@ "
+ " "
+ " @@@@@ @ "
+ " @ @ @ "
+ " @ @ @@@@ @@@@ "
+ " @ @ @ @ @ "
+ " @ @ @ @ @ "
+ " @ @ @ @ @ "
+ "@@@@@ @@@@ @@ "
+ " ";
+
+const int verbsFr[26] = { 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x307, 0x308,
+ 0x309, 0x30a, 0x30b, 0x30c, 0x30d, 0x30e, 0x30f, 0x310,
+ 0x311, 0x312, 0x313, 0x314, 0x315, 0x401, 0x402, 0x403,
+ 0x404, 0x405 };
+
+const int verbsEn[26] = { 0x301, 0x315, 0x305, 0x310, 0x309, 0x304, 0x302, 0x30f,
+ 0x306, 0x30d, 0x30e, 0x303, 0x30c, 0x30b, 0x313, 0x30a,
+ 0x311, 0x312, 0x307, 0x308, 0x314, 0x401, 0x405, 0x404,
+ 0x403, 0x402 };
+
+const int verbsDe[26] = { 0x304, 0x314, 0x307, 0x310, 0x315, 0x308, 0x311, 0x306,
+ 0x30c, 0x301, 0x30d, 0x309, 0x312, 0x30f, 0x30e, 0x302,
+ 0x30a, 0x313, 0x303, 0x30b, 0x305, 0x405, 0x402, 0x404,
+ 0x403, 0x401 };
+#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 323066d8b1..a37ff99ca9 100644
--- a/devtools/create_neverhood/create_neverhood.cpp
+++ b/devtools/create_neverhood/create_neverhood.cpp
@@ -30,12 +30,18 @@
#undef main
#endif // main
-#include <vector>
#include "create_neverhood.h"
+#include <vector>
+#include "md5.h"
#include "tables.h"
const int DAT_VERSION = 0;
+// The MD5 hash of the nhc.exe used to extract the tables from
+const uint8 kNhcExeMd5[16] = {
+ 0x37, 0xD6, 0x54, 0xA2, 0xA7, 0xBB, 0xB0, 0x1F,
+ 0x8C, 0x41, 0x9A, 0xB8, 0x49, 0xFF, 0x29, 0xD4};
+
uint32 dataSize;
byte *data;
uint32 dataStart = 0x004AE000;
@@ -48,12 +54,33 @@ class NavigationList;
void addMessageList(uint32 messageListCount, uint32 messageListOffset);
-void loadExe(const char *filename) {
+bool loadExe(const char *filename) {
FILE *exe = fopen(filename, "rb");
+ if (!exe) {
+ printf("Could not open nhc.exe for reading! Quitting...\n");
+ return false;
+ }
dataSize = fileSize(exe);
data = new byte[dataSize];
fread(data, dataSize, 1, exe);
fclose(exe);
+ return true;
+}
+
+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[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;
+ }
+ return true;
}
byte *getData(uint32 offset) {
@@ -85,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);
@@ -93,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);
@@ -102,11 +129,11 @@ struct HitRect {
writeUint16LE(fd, y2);
writeUint16LE(fd, messageNum);
}
-
+
int getItemSize() const {
return 10;
}
-
+
};
struct MessageItem {
@@ -114,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 {
@@ -148,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);
@@ -156,11 +183,11 @@ struct SubRectItem {
writeUint16LE(fd, y2);
writeUint32LE(fd, messageListOffset);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct RectItem {
@@ -185,7 +212,7 @@ struct RectItem {
subItemOffset += 16;
subRectItems.push_back(subRectItem);
}
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, x1);
@@ -196,11 +223,11 @@ struct RectItem {
for (uint32 j = 0; j < subRectItems.size(); j++)
subRectItems[j].save(fd);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct NavigationItem {
@@ -211,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);
@@ -236,7 +263,7 @@ struct NavigationItem {
int getItemSize() const {
return 24;
}
-
+
};
struct SceneInfo140Item {
@@ -320,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;
}
@@ -371,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)
@@ -428,7 +455,7 @@ public:
}
return false;
}
-
+
};
class NavigationList : public StaticDataList<NavigationItem> {
@@ -438,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();
@@ -459,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++) {
@@ -473,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;
@@ -481,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++) {
@@ -495,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();
@@ -506,9 +533,11 @@ void addMessageList(uint32 messageListCount, uint32 messageListOffset) {
int main(int argc, char *argv[]) {
- FILE *datFile;
+ if (!loadExe("nhc.exe") ||
+ !validateMd5())
+ return 1;
- loadExe("nhc.exe");
+ FILE *datFile;
hitRectLists.loadListVector(hitRectListOffsets);
rectLists.loadListVector(rectListOffsets);
@@ -516,12 +545,12 @@ int main(int argc, char *argv[]) {
navigationLists.loadListVector(navigationListOffsets);
sceneInfo140Items.loadVector(sceneInfo140Offsets);
sceneInfo2700Items.loadVector(sceneInfo2700Offsets);
-
+
datFile = fopen("neverhood.dat", "wb");
writeUint32LE(datFile, 0x11223344); // Some magic
writeUint32LE(datFile, DAT_VERSION);
-
+
messageLists.saveListVector(datFile);
rectLists.saveListVector(datFile);
hitRectLists.saveListVector(datFile);
diff --git a/devtools/create_neverhood/md5.cpp b/devtools/create_neverhood/md5.cpp
new file mode 100644
index 0000000000..50f7406a47
--- /dev/null
+++ b/devtools/create_neverhood/md5.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.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "md5.h"
+
+#define GET_UINT32(n, b, i) (n) = READ_LE_UINT32(b + i)
+#define PUT_UINT32(n, b, i) WRITE_LE_UINT32(b + i, n)
+
+void md5_starts(md5_context *ctx) {
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+static void md5_process(md5_context *ctx, const uint8 data[64]) {
+ uint32 X[16], A, B, C, D;
+
+ GET_UINT32(X[0], data, 0);
+ GET_UINT32(X[1], data, 4);
+ GET_UINT32(X[2], data, 8);
+ GET_UINT32(X[3], data, 12);
+ GET_UINT32(X[4], data, 16);
+ GET_UINT32(X[5], data, 20);
+ GET_UINT32(X[6], data, 24);
+ GET_UINT32(X[7], data, 28);
+ GET_UINT32(X[8], data, 32);
+ GET_UINT32(X[9], data, 36);
+ GET_UINT32(X[10], data, 40);
+ GET_UINT32(X[11], data, 44);
+ GET_UINT32(X[12], data, 48);
+ GET_UINT32(X[13], data, 52);
+ GET_UINT32(X[14], data, 56);
+ GET_UINT32(X[15], data, 60);
+
+#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a, b, c, d, k, s, t) \
+{ \
+ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x, y, z) (z ^ (x & (y ^ z)))
+
+ P(A, B, C, D, 0, 7, 0xD76AA478);
+ P(D, A, B, C, 1, 12, 0xE8C7B756);
+ P(C, D, A, B, 2, 17, 0x242070DB);
+ P(B, C, D, A, 3, 22, 0xC1BDCEEE);
+ P(A, B, C, D, 4, 7, 0xF57C0FAF);
+ P(D, A, B, C, 5, 12, 0x4787C62A);
+ P(C, D, A, B, 6, 17, 0xA8304613);
+ P(B, C, D, A, 7, 22, 0xFD469501);
+ P(A, B, C, D, 8, 7, 0x698098D8);
+ P(D, A, B, C, 9, 12, 0x8B44F7AF);
+ P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+ P(B, C, D, A, 11, 22, 0x895CD7BE);
+ P(A, B, C, D, 12, 7, 0x6B901122);
+ P(D, A, B, C, 13, 12, 0xFD987193);
+ P(C, D, A, B, 14, 17, 0xA679438E);
+ P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x, y, z) (y ^ (z & (x ^ y)))
+
+ P(A, B, C, D, 1, 5, 0xF61E2562);
+ P(D, A, B, C, 6, 9, 0xC040B340);
+ P(C, D, A, B, 11, 14, 0x265E5A51);
+ P(B, C, D, A, 0, 20, 0xE9B6C7AA);
+ P(A, B, C, D, 5, 5, 0xD62F105D);
+ P(D, A, B, C, 10, 9, 0x02441453);
+ P(C, D, A, B, 15, 14, 0xD8A1E681);
+ P(B, C, D, A, 4, 20, 0xE7D3FBC8);
+ P(A, B, C, D, 9, 5, 0x21E1CDE6);
+ P(D, A, B, C, 14, 9, 0xC33707D6);
+ P(C, D, A, B, 3, 14, 0xF4D50D87);
+ P(B, C, D, A, 8, 20, 0x455A14ED);
+ P(A, B, C, D, 13, 5, 0xA9E3E905);
+ P(D, A, B, C, 2, 9, 0xFCEFA3F8);
+ P(C, D, A, B, 7, 14, 0x676F02D9);
+ P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x, y, z) (x ^ y ^ z)
+
+ P(A, B, C, D, 5, 4, 0xFFFA3942);
+ P(D, A, B, C, 8, 11, 0x8771F681);
+ P(C, D, A, B, 11, 16, 0x6D9D6122);
+ P(B, C, D, A, 14, 23, 0xFDE5380C);
+ P(A, B, C, D, 1, 4, 0xA4BEEA44);
+ P(D, A, B, C, 4, 11, 0x4BDECFA9);
+ P(C, D, A, B, 7, 16, 0xF6BB4B60);
+ P(B, C, D, A, 10, 23, 0xBEBFBC70);
+ P(A, B, C, D, 13, 4, 0x289B7EC6);
+ P(D, A, B, C, 0, 11, 0xEAA127FA);
+ P(C, D, A, B, 3, 16, 0xD4EF3085);
+ P(B, C, D, A, 6, 23, 0x04881D05);
+ P(A, B, C, D, 9, 4, 0xD9D4D039);
+ P(D, A, B, C, 12, 11, 0xE6DB99E5);
+ P(C, D, A, B, 15, 16, 0x1FA27CF8);
+ P(B, C, D, A, 2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x, y, z) (y ^ (x | ~z))
+
+ P(A, B, C, D, 0, 6, 0xF4292244);
+ P(D, A, B, C, 7, 10, 0x432AFF97);
+ P(C, D, A, B, 14, 15, 0xAB9423A7);
+ P(B, C, D, A, 5, 21, 0xFC93A039);
+ P(A, B, C, D, 12, 6, 0x655B59C3);
+ P(D, A, B, C, 3, 10, 0x8F0CCC92);
+ P(C, D, A, B, 10, 15, 0xFFEFF47D);
+ P(B, C, D, A, 1, 21, 0x85845DD1);
+ P(A, B, C, D, 8, 6, 0x6FA87E4F);
+ P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+ P(C, D, A, B, 6, 15, 0xA3014314);
+ P(B, C, D, A, 13, 21, 0x4E0811A1);
+ P(A, B, C, D, 4, 6, 0xF7537E82);
+ P(D, A, B, C, 11, 10, 0xBD3AF235);
+ P(C, D, A, B, 2, 15, 0x2AD7D2BB);
+ P(B, C, D, A, 9, 21, 0xEB86D391);
+
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+void md5_update(md5_context *ctx, const uint8 *input, uint32 length) {
+ uint32 left, fill;
+
+ if (!length)
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < length)
+ ctx->total[1]++;
+
+ if (left && length >= fill) {
+ memcpy((void *)(ctx->buffer + left), (const void *)input, fill);
+ md5_process(ctx, ctx->buffer);
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while (length >= 64) {
+ md5_process(ctx, input);
+ length -= 64;
+ input += 64;
+ }
+
+ if (length) {
+ memcpy((void *)(ctx->buffer + left), (const void *)input, length);
+ }
+}
+
+static const uint8 md5_padding[64] = {
+ 0x80, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void md5_finish(md5_context *ctx, uint8 digest[16]) {
+ uint32 last, padn;
+ uint32 high, low;
+ uint8 msglen[8];
+
+ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32(low, msglen, 0);
+ PUT_UINT32(high, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ md5_update(ctx, md5_padding, padn);
+ md5_update(ctx, msglen, 8);
+
+ PUT_UINT32(ctx->state[0], digest, 0);
+ PUT_UINT32(ctx->state[1], digest, 4);
+ PUT_UINT32(ctx->state[2], digest, 8);
+ PUT_UINT32(ctx->state[3], digest, 12);
+}
+
+bool md5_file(const char *name, uint8 digest[16], uint32 length) {
+ FILE *f;
+
+ f = fopen(name, "rb");
+ if (f == NULL) {
+ printf("md5_file couldn't open '%s'\n", name);
+ return false;
+ }
+
+ md5_context ctx;
+ uint32 i;
+ unsigned char buf[1000];
+ bool restricted = (length != 0);
+ int readlen;
+
+ if (!restricted || sizeof(buf) <= length)
+ readlen = sizeof(buf);
+ else
+ readlen = length;
+
+ md5_starts(&ctx);
+
+
+ while ((i = (uint32)fread(buf, 1, readlen, f)) > 0) {
+ md5_update(&ctx, buf, i);
+
+ length -= i;
+ if (restricted && length == 0)
+ break;
+
+ if (restricted && sizeof(buf) > length)
+ readlen = length;
+ }
+
+ md5_finish(&ctx, digest);
+ fclose(f);
+ return true;
+}
+
+void md5_buffer(byte *buf, uint32 len, uint8 digest[16]) {
+ md5_context ctx;
+
+ md5_starts(&ctx);
+ md5_update(&ctx, buf, len);
+ md5_finish(&ctx, digest);
+}
+
diff --git a/devtools/create_neverhood/md5.h b/devtools/create_neverhood/md5.h
new file mode 100644
index 0000000000..81bc03ff83
--- /dev/null
+++ b/devtools/create_neverhood/md5.h
@@ -0,0 +1,41 @@
+/* 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_MD5_H
+#define COMMON_MD5_H
+
+#include "util.h"
+
+typedef struct {
+ uint32 total[2];
+ uint32 state[4];
+ uint8 buffer[64];
+} md5_context;
+
+void md5_starts(md5_context *ctx);
+void md5_update(md5_context *ctx, const uint8 *input, uint32 length);
+void md5_finish(md5_context *ctx, uint8 digest[16]);
+
+bool md5_file(const char *name, uint8 digest[16], uint32 length = 0);
+void md5_buffer(byte *buf, uint32 len, uint8 digest[16]);
+
+#endif
diff --git a/devtools/create_neverhood/module.mk b/devtools/create_neverhood/module.mk
index 284e19105d..8e263559b5 100644
--- a/devtools/create_neverhood/module.mk
+++ b/devtools/create_neverhood/module.mk
@@ -3,6 +3,7 @@ MODULE := devtools/create_neverhood
MODULE_OBJS := \
create_neverhood.o \
+ md5.o \
util.o
# Set the name of the executable
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/codeblocks.cpp b/devtools/create_project/codeblocks.cpp
index 3458ca5a19..442a2b0025 100644
--- a/devtools/create_project/codeblocks.cpp
+++ b/devtools/create_project/codeblocks.cpp
@@ -64,6 +64,11 @@ std::string processLibraryName(std::string name) {
if (pos != std::string::npos)
return name.replace(pos, 7, "");
+ // Remove "-static" in lib name
+ pos = name.find("-static");
+ if (pos != std::string::npos)
+ return name.replace(pos, 7, "");
+
// Replace "zlib" by "libz"
if (name == "zlib")
return "libz";
@@ -115,6 +120,7 @@ void CodeBlocksProvider::createProjectFile(const std::string &name, const std::s
"\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
"\t\t\t\t\t<Add directory=\"..\\..\\common\" />\n"
"\t\t\t\t\t<Add directory=\"..\\..\" />\n"
+ "\t\t\t\t\t<Add directory=\".\\\" />\n"
"\t\t\t\t</Compiler>\n";
//////////////////////////////////////////////////////////////////////////
diff --git a/devtools/create_project/config.h b/devtools/create_project/config.h
index 1a66edff93..9d4b101360 100644
--- a/devtools/create_project/config.h
+++ b/devtools/create_project/config.h
@@ -27,6 +27,7 @@
#define PROJECT_NAME "scummvm" // Used for folders, icons, resources and project/solution name
#define LIBS_DEFINE "SCUMMVM_LIBS" // Name of the include environment variable
#define REVISION_DEFINE "SCUMMVM_INTERNAL_REVISION"
+#define FIRST_ENGINE "scumm" // Name of the engine which should be sorted as first element
#define ENABLE_LANGUAGE_EXTENSIONS "" // Comma separated list of projects that need language extensions
#define DISABLE_EDIT_AND_CONTINUE "tinsel,tony,scummvm" // Comma separated list of projects that need Edit&Continue to be disabled for co-routine support (the main project is automatically added)
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index a8e09ff5eb..9d7ed532cb 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -39,10 +39,11 @@
#include <fstream>
#include <iostream>
-
+#include <sstream>
#include <stack>
#include <algorithm>
#include <iomanip>
+#include <iterator>
#include <cstring>
#include <cstdlib>
@@ -59,6 +60,7 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <errno.h>
#endif
namespace {
@@ -81,22 +83,6 @@ std::string unifyPath(const std::string &path);
* @param exe Name of the executable.
*/
void displayHelp(const char *exe);
-
-/**
- * Structure for describing an FSNode. This is a very minimalistic
- * description, which includes everything we need.
- * It only contains the name of the node and whether it is a directory
- * or not.
- */
-struct FSNode {
- FSNode() : name(), isDirectory(false) {}
- FSNode(const std::string &n, bool iD) : name(n), isDirectory(iD) {}
-
- std::string name; ///< Name of the file system node
- bool isDirectory; ///< Whether it is a directory or not
-};
-
-typedef std::list<FSNode> FileList;
} // End of anonymous namespace
enum ProjectType {
@@ -109,7 +95,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) {
@@ -128,7 +114,7 @@ int main(int argc, char *argv[]) {
setup.filePrefix = setup.srcDir;
setup.outputDir = '.';
- setup.engines = parseConfigure(setup.srcDir);
+ setup.engines = parseEngines(setup.srcDir);
if (setup.engines.empty()) {
std::cout << "WARNING: No engines found in configure file or configure file missing in \"" << setup.srcDir << "\"\n";
@@ -189,7 +175,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 +250,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 +265,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 +307,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 +361,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 +534,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 +576,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 +607,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 +628,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"
@@ -636,47 +658,70 @@ void displayHelp(const char *exe) {
}
/**
- * Try to parse a given line and create an engine definition
- * out of the result.
+ * Parse the configure.engine file of a given engine directory and return a
+ * list of all defined engines.
*
- * This may take *any* input line, when the line is not used
- * to define an engine the result of the function will be "false".
+ * @param engineDir The directory of the engine.
+ * @return The list of all defined engines.
+ */
+EngineDescList parseEngineConfigure(const std::string &engineDir);
+
+/**
+ * Compares two FSNode entries in a strict-weak fashion based on the name.
*
- * Note that the contents of "engine" are undefined, when this
- * function returns "false".
+ * @param left The first operand.
+ * @param right The second operand.
+ * @return "true" when the name of the left operand is strictly smaller than
+ * the name of the second operand. "false" otherwise.
+ */
+bool compareFSNode(const CreateProjectTool::FSNode &left, const CreateProjectTool::FSNode &right);
+
+#ifdef FIRST_ENGINE
+/**
+ * Compares two FSNode entries in a strict-weak fashion based on engine name
+ * order.
*
- * @param line Text input line.
- * @param engine Reference to an object, where the engine information
- * is to be stored in.
- * @return "true", when parsing succeeded, "false" otherwise.
+ * @param left The first operand.
+ * @param right The second operand.
+ * @return "true" when the name of the left operand is strictly smaller than
+ * the name of the second operand. "false" otherwise.
*/
-bool parseEngine(const std::string &line, EngineDesc &engine);
+bool compareEngineNames(const CreateProjectTool::FSNode &left, const CreateProjectTool::FSNode &right);
+#endif
} // End of anonymous namespace
-EngineDescList parseConfigure(const std::string &srcDir) {
- std::string configureFile = srcDir + "/engines/configure.engines";
+EngineDescList parseEngines(const std::string &srcDir) {
+ using CreateProjectTool::FileList;
+ using CreateProjectTool::listDirectory;
- std::ifstream configure(configureFile.c_str());
- if (!configure)
- return EngineDescList();
+ EngineDescList engineList;
- std::string line;
- EngineDescList engines;
+ FileList engineFiles = listDirectory(srcDir + "/engines/");
- for (;;) {
- std::getline(configure, line);
- if (configure.eof())
- break;
+#ifdef FIRST_ENGINE
+ // In case we want to sort an engine to the front of the list we will
+ // use some manual sorting predicate which assures that.
+ engineFiles.sort(&compareEngineNames);
+#else
+ // Otherwise, we simply sort the file list alphabetically this allows
+ // for a nicer order in --list-engines output, for example.
+ engineFiles.sort(&compareFSNode);
+#endif
- if (configure.fail())
- error("Failed while reading from " + configureFile);
+ for (FileList::const_iterator i = engineFiles.begin(), end = engineFiles.end(); i != end; ++i) {
+ // Each engine requires its own sub directory thus we will skip all
+ // non directory file nodes here.
+ if (!i->isDirectory) {
+ continue;
+ }
- EngineDesc desc;
- if (parseEngine(line, desc))
- engines.push_back(desc);
+ // Retrieve all engines defined in this sub directory and add them to
+ // the list of all engines.
+ EngineDescList list = parseEngineConfigure(srcDir + "/engines/" + i->name);
+ engineList.splice(engineList.end(), list);
}
- return engines;
+ return engineList;
}
bool isSubEngine(const std::string &name, const EngineDescList &engines) {
@@ -741,6 +786,21 @@ StringList getEngineDefines(const EngineDescList &engines) {
}
namespace {
+/**
+ * Try to parse a given line and create an engine definition
+ * out of the result.
+ *
+ * This may take *any* input line, when the line is not used
+ * to define an engine the result of the function will be "false".
+ *
+ * Note that the contents of "engine" are undefined, when this
+ * function returns "false".
+ *
+ * @param line Text input line.
+ * @param engine Reference to an object, where the engine information
+ * is to be stored in.
+ * @return "true", when parsing succeeded, "false" otherwise.
+ */
bool parseEngine(const std::string &line, EngineDesc &engine) {
// Format:
// add_engine engine_name "Readable Description" enable_default ["SubEngineList"]
@@ -763,6 +823,48 @@ bool parseEngine(const std::string &line, EngineDesc &engine) {
return true;
}
+
+EngineDescList parseEngineConfigure(const std::string &engineDir) {
+ std::string configureFile = engineDir + "/configure.engine";
+
+ std::ifstream configure(configureFile.c_str());
+ if (!configure)
+ return EngineDescList();
+
+ std::string line;
+ EngineDescList engines;
+
+ for (;;) {
+ std::getline(configure, line);
+ if (configure.eof())
+ break;
+
+ if (configure.fail())
+ error("Failed while reading from " + configureFile);
+
+ EngineDesc desc;
+ if (parseEngine(line, desc))
+ engines.push_back(desc);
+ }
+
+ return engines;
+}
+
+bool compareFSNode(const CreateProjectTool::FSNode &left, const CreateProjectTool::FSNode &right) {
+ return left.name < right.name;
+}
+
+#ifdef FIRST_ENGINE
+bool compareEngineNames(const CreateProjectTool::FSNode &left, const CreateProjectTool::FSNode &right) {
+ if (left.name == FIRST_ENGINE) {
+ return right.name != FIRST_ENGINE;
+ } else if (right.name == FIRST_ENGINE) {
+ return false;
+ } else {
+ return compareFSNode(left, right);
+ }
+}
+#endif
} // End of anonymous namespace
TokenList tokenize(const std::string &input, char separator) {
@@ -805,23 +907,27 @@ 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" },
+ { "jpeg", "USE_JPEG", "jpeg-static", true, "libjpeg 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 +935,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}
@@ -925,6 +1033,10 @@ bool producesObjectFile(const std::string &fileName) {
return false;
}
+std::string toString(int num) {
+ return static_cast<std::ostringstream*>(&(std::ostringstream() << num))->str();
+}
+
/**
* Checks whether the give file in the specified directory is present in the given
* file list.
@@ -1002,13 +1114,6 @@ bool compareNodes(const FileNode *l, const FileNode *r) {
}
}
-/**
- * Returns a list of all files and directories in the specified
- * path.
- *
- * @param dir Directory which should be listed.
- * @return List of all children.
- */
FileList listDirectory(const std::string &dir) {
FileList result;
#ifdef USE_WIN32_API
@@ -1049,6 +1154,32 @@ FileList listDirectory(const std::string &dir) {
return result;
}
+void createDirectory(const std::string &dir) {
+#if defined(_WIN32) || defined(WIN32)
+ if (!CreateDirectory(dir.c_str(), NULL)) {
+ if (GetLastError() != ERROR_ALREADY_EXISTS) {
+ error("Could not create folder \"" + dir + "\"");
+ }
+ }
+#else
+ if (mkdir(dir.c_str(), 0777) == -1) {
+ if (errno == EEXIST) {
+ // Try to open as a folder (might be a file / symbolic link)
+ DIR *dirp = opendir(dir.c_str());
+ if (dirp == NULL) {
+ error("Could not create folder \"" + dir + "\"");
+ } else {
+ // The folder exists, just close the stream and return
+ closedir(dirp);
+ }
+ } else {
+ error("Could not create folder \"" + dir + "\"");
+ }
+ }
+#endif
+
+}
+
/**
* Scans the specified directory against files, which should be included
* in the project files. It will not include files present in the exclude list.
@@ -1114,69 +1245,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;
-
- createModuleList(moduleDir, setup.defines, in, ex);
- createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
- }
+ // We also need to add the UUID of the main project file.
+ const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
- // Create other misc. build files
- createOtherBuildFiles(setup);
+ createWorkspace(setup);
- } else {
- _uuidMap = createUUIDMap(setup);
+ StringList in, ex;
- // 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,9 +1323,15 @@ 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);
+ // In case we create the main ScummVM project files we will need to
+ // generate engines/plugins_table.h too.
+ if (!setup.tests && !setup.devTools) {
+ createEnginePluginsTable(setup);
}
}
@@ -1306,7 +1440,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 +1571,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);
@@ -1473,6 +1660,37 @@ void ProjectProvider::createModuleList(const std::string &moduleDir, const Strin
error("Malformed file " + moduleMkFile);
}
+void ProjectProvider::createEnginePluginsTable(const BuildSetup &setup) {
+ // First we need to create the "engines" directory.
+ createDirectory(setup.outputDir + "/engines");
+
+ // Then, we can generate the actual "plugins_table.h" file.
+ const std::string enginePluginsTableFile = setup.outputDir + "/engines/plugins_table.h";
+ std::ofstream enginePluginsTable(enginePluginsTableFile.c_str());
+ if (!enginePluginsTable) {
+ error("Could not open \"" + enginePluginsTableFile + "\" for writing");
+ }
+
+ enginePluginsTable << "/* This file is automatically generated by create_project */\n"
+ << "/* DO NOT EDIT MANUALLY */\n"
+ << "// This file is being included by \"base/plugins.cpp\"\n";
+
+ for (EngineDescList::const_iterator i = setup.engines.begin(), end = setup.engines.end(); i != end; ++i) {
+ // We ignore all sub engines here because they require no special
+ // handling.
+ if (isSubEngine(i->name, setup.engines)) {
+ continue;
+ }
+
+ // Make the engine name all uppercase.
+ std::string engineName;
+ std::transform(i->name.begin(), i->name.end(), std::back_inserter(engineName), toupper);
+
+ enginePluginsTable << "#if PLUGIN_ENABLED_STATIC(" << engineName << ")\n"
+ << "LINK_PLUGIN(" << engineName << ")\n"
+ << "#endif\n";
+ }
+}
} // End of anonymous namespace
void error(const std::string &message) {
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index de77793ee7..459342a67d 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -23,6 +23,10 @@
#ifndef TOOLS_CREATE_PROJECT_H
#define TOOLS_CREATE_PROJECT_H
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
#include <map>
#include <list>
#include <string>
@@ -98,16 +102,17 @@ struct EngineDesc {
typedef std::list<EngineDesc> EngineDescList;
/**
- * This function parses the project configure file and creates a list
- * of available engines.
+ * This function parses the project directory and creates a list of
+ * available engines.
*
* It will also automatically setup the default build state (enabled
- * or disabled) to the state specified in the "configure" file.
+ * or disabled) to the state specified in the individual configure.engine
+ * files.
*
* @param srcDir Path to the root of the project source.
* @return List of available engines.
*/
-EngineDescList parseConfigure(const std::string &srcDir);
+EngineDescList parseEngines(const std::string &srcDir);
/**
* Checks whether the specified engine is a sub engine. To determine this
@@ -221,13 +226,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;
}
@@ -256,6 +264,22 @@ void NORETURN_PRE error(const std::string &message) NORETURN_POST;
namespace CreateProjectTool {
/**
+ * Structure for describing an FSNode. This is a very minimalistic
+ * description, which includes everything we need.
+ * It only contains the name of the node and whether it is a directory
+ * or not.
+ */
+struct FSNode {
+ FSNode() : name(), isDirectory(false) {}
+ FSNode(const std::string &n, bool iD) : name(n), isDirectory(iD) {}
+
+ std::string name; ///< Name of the file system node
+ bool isDirectory; ///< Whether it is a directory or not
+};
+
+typedef std::list<FSNode> FileList;
+
+/**
* Gets a proper sequence of \t characters for the given
* indentation level.
*
@@ -300,6 +324,30 @@ void splitFilename(const std::string &fileName, std::string &name, std::string &
bool producesObjectFile(const std::string &fileName);
/**
+* Convert an integer to string
+*
+* @param num the integer to convert
+* @return string representation of the number
+*/
+std::string toString(int num);
+
+/**
+ * Returns a list of all files and directories in the specified
+ * path.
+ *
+ * @param dir Directory which should be listed.
+ * @return List of all children.
+ */
+FileList listDirectory(const std::string &dir);
+
+/**
+ * Create a directory at the given path.
+ *
+ * @param dir The path to create.
+ */
+void createDirectory(const std::string &dir);
+
+/**
* Structure representing a file tree. This contains two
* members: name and children. "name" holds the name of
* the node. "children" does contain all the node's children.
@@ -339,7 +387,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 +478,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 +497,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;
@@ -458,6 +507,15 @@ protected:
* @return A new UUID as string.
*/
std::string createUUID() const;
+
+private:
+ /**
+ * This creates the engines/plugins_table.h file required for building
+ * ScummVM.
+ *
+ * @param setup Description of the desired build.
+ */
+ void createEnginePluginsTable(const BuildSetup &setup);
};
} // End of CreateProjectTool namespace
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index 0f77d91852..07ae20e7dc 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");
}
@@ -64,10 +67,10 @@ inline void outputConfiguration(std::ostream &project, const std::string &config
"\t\t</ProjectConfiguration>\n";
}
-inline void outputConfigurationType(const BuildSetup &setup, std::ostream &project, const std::string &name, const std::string &config, int version) {
+inline void outputConfigurationType(const BuildSetup &setup, std::ostream &project, const std::string &name, const std::string &config, std::string toolset) {
project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"Configuration\">\n"
- "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n"
- "\t\t<PlatformToolset>v" << version << "0</PlatformToolset>\n"
+ "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools || setup.tests) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n"
+ "\t\t<PlatformToolset>" << toolset << "</PlatformToolset>\n"
"\t</PropertyGroup>\n";
}
@@ -88,13 +91,15 @@ 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");
outputConfiguration(project, "Debug", "x64");
outputConfiguration(project, "Analysis", "Win32");
outputConfiguration(project, "Analysis", "x64");
+ outputConfiguration(project, "LLVM", "Win32");
+ outputConfiguration(project, "LLVM", "x64");
outputConfiguration(project, "Release", "Win32");
outputConfiguration(project, "Release", "x64");
@@ -105,18 +110,23 @@ 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
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n";
- outputConfigurationType(setup, project, name, "Release|Win32", _version);
- outputConfigurationType(setup, project, name, "Analysis|Win32", _version);
- outputConfigurationType(setup, project, name, "Debug|Win32", _version);
- outputConfigurationType(setup, project, name, "Release|x64", _version);
- outputConfigurationType(setup, project, name, "Analysis|x64", _version);
- outputConfigurationType(setup, project, name, "Debug|x64", _version);
+ std::string version = "v" + toString(_version) + "0";
+ std::string llvm = "LLVM-vs" + toString(getVisualStudioVersion());
+
+ outputConfigurationType(setup, project, name, "Release|Win32", version);
+ outputConfigurationType(setup, project, name, "Analysis|Win32", version);
+ outputConfigurationType(setup, project, name, "LLVM|Win32", llvm);
+ outputConfigurationType(setup, project, name, "Debug|Win32", version);
+ outputConfigurationType(setup, project, name, "Release|x64", version);
+ outputConfigurationType(setup, project, name, "LLVM|x64", llvm);
+ outputConfigurationType(setup, project, name, "Analysis|x64", version);
+ outputConfigurationType(setup, project, name, "Debug|x64", version);
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n"
"\t<ImportGroup Label=\"ExtensionSettings\">\n"
@@ -124,20 +134,24 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
outputProperties(project, "Release|Win32", setup.projectDescription + "_Release.props");
outputProperties(project, "Analysis|Win32", setup.projectDescription + "_Analysis.props");
+ outputProperties(project, "LLVM|Win32", setup.projectDescription + "_LLVM.props");
outputProperties(project, "Debug|Win32", setup.projectDescription + "_Debug.props");
outputProperties(project, "Release|x64", setup.projectDescription + "_Release64.props");
outputProperties(project, "Analysis|x64", setup.projectDescription + "_Analysis64.props");
+ outputProperties(project, "LLVM|x64", setup.projectDescription + "_LLVM64.props");
outputProperties(project, "Debug|x64", setup.projectDescription + "_Debug64.props");
project << "\t<PropertyGroup Label=\"UserMacros\" />\n";
// Project-specific settings (analysis uses debug properties)
- outputProjectSettings(project, name, setup, false, true, false);
- outputProjectSettings(project, name, setup, false, true, true);
- outputProjectSettings(project, name, setup, true, true, false);
- outputProjectSettings(project, name, setup, false, false, false);
- outputProjectSettings(project, name, setup, false, false, true);
- outputProjectSettings(project, name, setup, true, false, false);
+ outputProjectSettings(project, name, setup, false, true, "Debug");
+ outputProjectSettings(project, name, setup, false, true, "Analysis");
+ outputProjectSettings(project, name, setup, false, true, "LLVM");
+ outputProjectSettings(project, name, setup, true, true, "Release");
+ outputProjectSettings(project, name, setup, false, false, "Debug");
+ outputProjectSettings(project, name, setup, false, false, "Analysis");
+ outputProjectSettings(project, name, setup, false, false, "LLVM");
+ outputProjectSettings(project, name, setup, true, false, "Release");
// Files
std::string modulePath;
@@ -156,10 +170,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 +214,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";
@@ -236,16 +266,14 @@ void MSBuildProvider::writeReferences(const BuildSetup &setup, std::ofstream &ou
output << "\t</ItemGroup>\n";
}
-void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) {
- const std::string configuration = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug"));
-
+void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration) {
// Check for project-specific warnings:
std::map<std::string, StringList>::iterator warningsIterator = _projectWarnings.find(name);
bool enableLanguageExtensions = find(_enableLanguageExtensions.begin(), _enableLanguageExtensions.end(), name) != _enableLanguageExtensions.end();
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 +285,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 +299,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 +321,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 +347,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 +360,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 +378,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"
@@ -359,22 +391,20 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
properties.flush();
}
-void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) {
- const std::string outputType = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug"));
+void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration) {
const std::string outputBitness = (isWin32 ? "32" : "64");
- std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
+ std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_" + configuration + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
if (!properties)
- error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
+ error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + configuration + (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<_PropertySheetDisplayName>" << setup.projectDescription << "_" << configuration << outputBitness << "</_PropertySheetDisplayName>\n"
"\t\t<LinkIncremental>" << (isRelease ? "false" : "true") << "</LinkIncremental>\n"
"\t</PropertyGroup>\n"
"\t<ItemDefinitionGroup>\n"
@@ -388,22 +418,26 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
"\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
"\t\t\t<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n"
- "\t\t\t<EnablePREfast>" << (enableAnalysis ? "true" : "false") << "</EnablePREfast>\n"
+ "\t\t\t<EnablePREfast>" << (configuration == "Analysis" ? "true" : "false") << "</EnablePREfast>\n"
"\t\t</ClCompile>\n"
"\t\t<Link>\n"
"\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
"\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;" << (configuration == "LLVM" ? "_CRT_SECURE_NO_WARNINGS;" : "") << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<MinimalRebuild>true</MinimalRebuild>\n"
"\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n"
"\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n"
"\t\t\t<FunctionLevelLinking>true</FunctionLevelLinking>\n"
"\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
"\t\t\t<DebugInformationFormat>" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "</DebugInformationFormat>\n" // For x64 format Edit and continue is not supported, thus we default to Program Database
- "\t\t\t<EnablePREfast>" << (enableAnalysis ? "true" : "false") << "</EnablePREfast>\n"
- "\t\t</ClCompile>\n"
+ "\t\t\t<EnablePREfast>" << (configuration == "Analysis" ? "true" : "false") << "</EnablePREfast>\n";
+
+ if (configuration == "LLVM")
+ properties << "\t\t\t<AdditionalOptions>-Wno-microsoft -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder -Wpointer-arith -Wcast-qual -Wshadow -Wnon-virtual-dtor -Wwrite-strings -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants -Wno-nested-anon-types %(AdditionalOptions)</AdditionalOptions>\n";
+
+ properties << "\t\t</ClCompile>\n"
"\t\t<Link>\n"
"\t\t\t<GenerateDebugInformation>true</GenerateDebugInformation>\n"
"\t\t\t<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n"
@@ -459,7 +493,7 @@ void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ofstream
// Deal with duplicated file names
if (isDuplicate) {
projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\">\n"
- "\t\t\t<ObjectFileName>$(IntDir)" << (*entry).prefix << "%(Filename).obj</ObjectFileName>\n";
+ "\t\t\t<ObjectFileName>$(IntDir)" << (*entry).prefix << "%(Filename).obj</ObjectFileName>\n";
projectFile << "\t\t</ClCompile>\n";
} else {
diff --git a/devtools/create_project/msbuild.h b/devtools/create_project/msbuild.h
index fa6667741a..829657beff 100644
--- a/devtools/create_project/msbuild.h
+++ b/devtools/create_project/msbuild.h
@@ -35,7 +35,7 @@ protected:
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
const StringList &includeList, const StringList &excludeList);
- void outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis);
+ void outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration);
void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
@@ -44,7 +44,7 @@ protected:
void outputGlobalPropFile(const BuildSetup &setup, std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix, bool runBuildEvents);
- void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis);
+ void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration);
const char *getProjectExtension();
const char *getPropertiesExtension();
diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index b8d2401af9..cdd2d8a7c1 100644
--- a/devtools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -79,9 +79,11 @@ void MSVCProvider::createWorkspace(const BuildSetup &setup) {
"\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"
"\t\tDebug|Win32 = Debug|Win32\n"
"\t\tAnalysis|Win32 = Analysis|Win32\n"
+ "\t\tLLVM|Win32 = LLVM|Win32\n"
"\t\tRelease|Win32 = Release|Win32\n"
"\t\tDebug|x64 = Debug|x64\n"
"\t\tAnalysis|x64 = Analysis|x64\n"
+ "\t\tLLVM|x64 = LLVM|x64\n"
"\t\tRelease|x64 = Release|x64\n"
"\tEndGlobalSection\n"
"\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
@@ -91,12 +93,16 @@ void MSVCProvider::createWorkspace(const BuildSetup &setup) {
"\t\t{" << i->second << "}.Debug|Win32.Build.0 = Debug|Win32\n"
"\t\t{" << i->second << "}.Analysis|Win32.ActiveCfg = Analysis|Win32\n"
"\t\t{" << i->second << "}.Analysis|Win32.Build.0 = Analysis|Win32\n"
+ "\t\t{" << i->second << "}.LLVM|Win32.ActiveCfg = LLVM|Win32\n"
+ "\t\t{" << i->second << "}.LLVM|Win32.Build.0 = LLVM|Win32\n"
"\t\t{" << i->second << "}.Release|Win32.ActiveCfg = Release|Win32\n"
"\t\t{" << i->second << "}.Release|Win32.Build.0 = Release|Win32\n"
"\t\t{" << i->second << "}.Debug|x64.ActiveCfg = Debug|x64\n"
"\t\t{" << i->second << "}.Debug|x64.Build.0 = Debug|x64\n"
"\t\t{" << i->second << "}.Analysis|x64.ActiveCfg = Analysis|x64\n"
"\t\t{" << i->second << "}.Analysis|x64.Build.0 = Analysis|x64\n"
+ "\t\t{" << i->second << "}.LLVM|x64.ActiveCfg = LLVM|x64\n"
+ "\t\t{" << i->second << "}.LLVM|x64.Build.0 = LLVM|x64\n"
"\t\t{" << i->second << "}.Release|x64.ActiveCfg = Release|x64\n"
"\t\t{" << i->second << "}.Release|x64.Build.0 = Release|x64\n";
}
@@ -114,12 +120,14 @@ void MSVCProvider::createOtherBuildFiles(const BuildSetup &setup) {
// Create the configuration property files (for Debug and Release with 32 and 64bits versions)
// Note: we use the debug properties for the analysis configuration
- createBuildProp(setup, true, false, false);
- createBuildProp(setup, true, true, false);
- createBuildProp(setup, false, false, false);
- createBuildProp(setup, false, false, true);
- createBuildProp(setup, false, true, false);
- createBuildProp(setup, false, true, true);
+ createBuildProp(setup, true, false, "Release");
+ createBuildProp(setup, true, true, "Release");
+ createBuildProp(setup, false, false, "Debug");
+ createBuildProp(setup, false, true, "Debug");
+ createBuildProp(setup, false, false, "Analysis");
+ createBuildProp(setup, false, true, "Analysis");
+ createBuildProp(setup, false, false, "LLVM");
+ createBuildProp(setup, false, true, "LLVM");
}
void MSVCProvider::createGlobalProp(const BuildSetup &setup) {
@@ -161,6 +169,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..3a3eb98034 100644
--- a/devtools/create_project/msvc.h
+++ b/devtools/create_project/msvc.h
@@ -70,7 +70,7 @@ protected:
* @param isWin32 Bitness of property file
* @param enableAnalysis PREfast support
*/
- virtual void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) = 0;
+ virtual void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration) = 0;
/**
* Get the file extension for property files
@@ -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..84bc674f9a 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)
@@ -92,6 +92,7 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
// Win32
outputConfiguration(project, setup, libraries, "Debug", "Win32", "", true);
outputConfiguration(project, setup, libraries, "Analysis", "Win32", "", true);
+ outputConfiguration(project, setup, libraries, "LLVM", "Win32", "", true);
outputConfiguration(project, setup, libraries, "Release", "Win32", "", true);
// x64
@@ -100,6 +101,7 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
// libraries list created for IA-32. If that changes in the future, we need to adjust this part!
outputConfiguration(project, setup, libraries, "Debug", "x64", "64", false);
outputConfiguration(project, setup, libraries, "Analysis", "x64", "64", false);
+ outputConfiguration(project, setup, libraries, "LLVM", "Win32", "64", false);
outputConfiguration(project, setup, libraries, "Release", "x64", "64", false);
} else {
@@ -119,9 +121,11 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
// Win32
outputConfiguration(setup, project, toolConfig, "Debug", "Win32", "");
outputConfiguration(setup, project, toolConfig, "Analysis", "Win32", "");
+ outputConfiguration(setup, project, toolConfig, "LLVM", "Win32", "");
outputConfiguration(setup, project, toolConfig, "Release", "Win32", "");
outputConfiguration(setup, project, toolConfig, "Debug", "x64", "64");
outputConfiguration(setup, project, toolConfig, "Analysis", "x64", "64");
+ outputConfiguration(setup, project, toolConfig, "LLVM", "x64", "64");
outputConfiguration(setup, project, toolConfig, "Release", "x64", "64");
}
@@ -140,6 +144,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 +170,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 +178,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 +232,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 +255,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"
@@ -249,19 +269,18 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of
properties.flush();
}
-void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) {
- const std::string outputType = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug"));
+void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration) {
const std::string outputBitness = (isWin32 ? "32" : "64");
- std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
+ std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_" + configuration + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
if (!properties)
- error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
+ error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + configuration + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
properties << "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n"
"<VisualStudioPropertySheet\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"8.00\"\n"
- "\tName=\"" << setup.projectDescription << "_" << outputType << outputBitness << "\"\n"
+ "\tName=\"" << setup.projectDescription << "_" << configuration << outputBitness << "\"\n"
"\tInheritedPropertySheets=\".\\" << setup.projectDescription << "_Global" << (isWin32 ? "" : "64") << ".vsprops\"\n"
"\t>\n"
"\t<Tool\n"
@@ -275,7 +294,7 @@ void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelea
"\t\tBufferSecurityCheck=\"false\"\n"
"\t\tDebugInformationFormat=\"0\"\n"
"\t\tRuntimeLibrary=\"0\"\n"
- "\t\tAdditionalOption=\"" << (enableAnalysis ? "/analyze" : "") << "\"\n"
+ "\t\tAdditionalOption=\"" << (configuration == "Analysis" ? "/analyze" : "") << "\"\n"
"\t/>\n"
"\t<Tool\n"
"\t\tName=\"VCLinkerTool\"\n"
@@ -291,7 +310,7 @@ void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelea
"\t\tEnableFunctionLevelLinking=\"true\"\n"
"\t\tWarnAsError=\"false\"\n"
"\t\tDebugInformationFormat=\"" << (isWin32 ? "4" : "3") << "\"\n" // For x64 format "4" (Edit and continue) is not supported, thus we default to "3"
- "\t\tAdditionalOption=\"" << (enableAnalysis ? "/analyze" : "") << "\"\n"
+ "\t\tAdditionalOption=\"" << (configuration == "Analysis" ? "/analyze" : "") << "\"\n"
"\t/>\n"
"\t<Tool\n"
"\t\tName=\"VCLinkerTool\"\n"
@@ -338,9 +357,9 @@ void VisualStudioProvider::writeFileListToProject(const FileNode &dir, std::ofst
<< indentString << "\t<FileConfiguration Name=\"Debug|Win32\">\n"
<< toolLine
<< indentString << "\t</FileConfiguration>\n"
- << indentString << "\t<FileConfiguration Name=\"Analysis|Win32\">\n"
- << toolLine
- << indentString << "\t</FileConfiguration>\n"
+ << indentString << "\t<FileConfiguration Name=\"Analysis|Win32\">\n"
+ << toolLine
+ << indentString << "\t</FileConfiguration>\n"
<< indentString << "\t<FileConfiguration Name=\"Release|Win32\">\n"
<< toolLine
<< indentString << "\t</FileConfiguration>\n"
@@ -353,18 +372,18 @@ void VisualStudioProvider::writeFileListToProject(const FileNode &dir, std::ofst
<< indentString << "\t<FileConfiguration Name=\"Debug|Win32\">\n"
<< toolLine
<< indentString << "\t</FileConfiguration>\n"
- << indentString << "\t<FileConfiguration Name=\"Analysis|Win32\">\n"
- << toolLine
- << indentString << "\t</FileConfiguration>\n"
+ << indentString << "\t<FileConfiguration Name=\"Analysis|Win32\">\n"
+ << toolLine
+ << indentString << "\t</FileConfiguration>\n"
<< indentString << "\t<FileConfiguration Name=\"Release|Win32\">\n"
<< toolLine
<< indentString << "\t</FileConfiguration>\n"
- << indentString << "\t<FileConfiguration Name=\"Debug|x64\">\n"
- << toolLine
- << indentString << "\t</FileConfiguration>\n"
- << indentString << "\t<FileConfiguration Name=\"Analysis|x64\">\n"
- << toolLine
- << indentString << "\t</FileConfiguration>\n"
+ << indentString << "\t<FileConfiguration Name=\"Debug|x64\">\n"
+ << toolLine
+ << indentString << "\t</FileConfiguration>\n"
+ << indentString << "\t<FileConfiguration Name=\"Analysis|x64\">\n"
+ << toolLine
+ << indentString << "\t</FileConfiguration>\n"
<< indentString << "\t<FileConfiguration Name=\"Release|x64\">\n"
<< toolLine
<< indentString << "\t</FileConfiguration>\n"
diff --git a/devtools/create_project/visualstudio.h b/devtools/create_project/visualstudio.h
index 845550139c..7eb66c4f2d 100644
--- a/devtools/create_project/visualstudio.h
+++ b/devtools/create_project/visualstudio.h
@@ -42,7 +42,7 @@ protected:
void outputGlobalPropFile(const BuildSetup &setup, std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix, bool runBuildEvents);
- void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis);
+ void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, std::string configuration);
const char *getProjectExtension();
const char *getPropertiesExtension();
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index a9b8e7a752..d95bf3e9ee 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -26,15 +26,6 @@
#include <fstream>
#include <algorithm>
-#if defined(_WIN32) || defined(WIN32)
-#include <windows.h>
-#else
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <errno.h>
-#endif
-
namespace CreateProjectTool {
#define DEBUG_XCODE_HASH 0
@@ -88,27 +79,7 @@ XCodeProvider::XCodeProvider(StringList &global_warnings, std::map<std::string,
void XCodeProvider::createWorkspace(const BuildSetup &setup) {
// Create project folder
std::string workspace = setup.outputDir + '/' + PROJECT_NAME ".xcodeproj";
-
-#if defined(_WIN32) || defined(WIN32)
- if (!CreateDirectory(workspace.c_str(), NULL))
- if (GetLastError() != ERROR_ALREADY_EXISTS)
- error("Could not create folder \"" + setup.outputDir + '/' + PROJECT_NAME ".xcodeproj\"");
-#else
- if (mkdir(workspace.c_str(), 0777) == -1) {
- if (errno == EEXIST) {
- // Try to open as a folder (might be a file / symbolic link)
- DIR *dirp = opendir(workspace.c_str());
- if (dirp == NULL) {
- error("Could not create folder \"" + setup.outputDir + '/' + PROJECT_NAME ".xcodeproj\"");
- } else {
- // The folder exists, just close the stream and return
- closedir(dirp);
- }
- } else {
- error("Could not create folder \"" + setup.outputDir + '/' + PROJECT_NAME ".xcodeproj\"");
- }
- }
-#endif
+ createDirectory(workspace);
// Setup global objects
setupDefines(setup);
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/create_translations/create_translations.cpp b/devtools/create_translations/create_translations.cpp
index a153632c47..a8b04a7a52 100644
--- a/devtools/create_translations/create_translations.cpp
+++ b/devtools/create_translations/create_translations.cpp
@@ -22,6 +22,8 @@
* The generated files is used by ScummVM to propose translation of its GUI.
*/
+#include "create_translations.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -34,7 +36,6 @@
#undef main
#endif // main
-#include "create_translations.h"
#include "po_parser.h"
#include "cp_parser.h"
diff --git a/devtools/create_translations/create_translations.h b/devtools/create_translations/create_translations.h
index 9ccbd39b2b..1df01e6333 100644
--- a/devtools/create_translations/create_translations.h
+++ b/devtools/create_translations/create_translations.h
@@ -28,4 +28,8 @@ typedef unsigned short uint16;
typedef unsigned int uint32;
typedef signed short int16;
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
#endif /* CREATE_TRANSLATIONS_H */
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 06df7fa50e..03e086ce99 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -48,7 +48,7 @@ if ($mode eq "") {
$Text::Wrap::unexpand = 0;
if ($mode eq "TEXT") {
$Text::Wrap::columns = 78;
- $max_name_width = 23; # The maximal width of a name.
+ $max_name_width = 28; # The maximal width of a name.
} elsif ($mode eq "CPP") {
$Text::Wrap::columns = 48; # Approx.
}
@@ -60,6 +60,7 @@ sub html_entities_to_ascii {
# For now we hardcode these mappings
# &aacute; -> a
# &eacute; -> e
+ # &iacute; -> i
# &igrave; -> i
# &oacute; -> o
# &oslash; -> o
@@ -72,8 +73,10 @@ sub html_entities_to_ascii {
# &#322; -> l
# &#347; -> s
# &Scaron; -> S
+ # &ntilde; -> n
$text =~ s/&aacute;/a/g;
$text =~ s/&eacute;/e/g;
+ $text =~ s/&iacute;/i/g;
$text =~ s/&igrave;/i/g;
$text =~ s/&oacute;/o/g;
$text =~ s/&oslash;/o/g;
@@ -81,6 +84,7 @@ sub html_entities_to_ascii {
$text =~ s/&#347;/s/g;
$text =~ s/&Scaron;/S/g;
$text =~ s/&aring;/aa/g;
+ $text =~ s/&ntilde;/n/g;
$text =~ s/&auml;/a/g;
$text =~ s/&euml;/e/g;
@@ -101,6 +105,7 @@ sub html_entities_to_cpp {
# The numerical values are octal!
$text =~ s/&aacute;/\\341/g;
$text =~ s/&eacute;/\\351/g;
+ $text =~ s/&iacute;/\\355/g;
$text =~ s/&igrave;/\\354/g;
$text =~ s/&oacute;/\\363/g;
$text =~ s/&oslash;/\\370/g;
@@ -108,6 +113,7 @@ sub html_entities_to_cpp {
$text =~ s/&#347;/s/g;
$text =~ s/&Scaron;/S/g;
$text =~ s/&aring;/\\345/g;
+ $text =~ s/&ntilde;/\\361/g;
$text =~ s/&auml;/\\344/g;
$text =~ s/&euml;/\\353/g;
@@ -126,6 +132,7 @@ sub html_entities_to_rtf {
$text =~ s/&aacute;/\\'87/g;
$text =~ s/&eacute;/\\'8e/g;
+ $text =~ s/&iacute;/\\'92/g;
$text =~ s/&igrave;/\\'93/g;
$text =~ s/&oacute;/\\'97/g;
$text =~ s/&oslash;/\\'bf/g;
@@ -135,6 +142,8 @@ sub html_entities_to_rtf {
$text =~ s/&Scaron;/\\uc0\\u540 /g;
# Back to hex numbers
+ $text =~ s/&ntilde;/\\'96/g;
+
$text =~ s/&auml;/\\'8a/g;
$text =~ s/&euml;/\\'eb/g;
$text =~ s/&ouml;/\\'9a/g;
@@ -151,12 +160,14 @@ sub html_entities_to_tex {
$text =~ s/&aacute;/\\'a/g;
$text =~ s/&eacute;/\\'e/g;
+ $text =~ s/&iacute;/\\'i/g;
$text =~ s/&igrave;/\\`\\i/g;
$text =~ s/&oacute;/\\'o/g;
$text =~ s/&oslash;/{\\o}/g;
$text =~ s/&aring;/\\aa /g;
$text =~ s/&#322;/{\\l}/g;
$text =~ s/&Scaron;/{\\v S}/g;
+ $text =~ s/&ntilde;/\\Ëœn/g;
$text =~ s/&auml;/\\"a/g;
$text =~ s/&ouml;/\\"o/g;
@@ -541,6 +552,11 @@ begin_credits("Credits");
add_person("Oliver Kiehl", "olki", "(retired)");
add_person("Ludvig Strigeus", "ludde", "(retired)");
end_section();
+
+ begin_section("AVALANCHE");
+ add_person("Peter Bozs&oacute;", "uruk", "");
+ add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
+ end_section();
begin_section("CGE");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
@@ -638,6 +654,16 @@ begin_credits("Credits");
add_person("David Turner", "digitall", "");
end_section();
+ begin_section("Mortevielle");
+ add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
+ add_person("Paul Gilbert", "dreammaster", "");
+ end_section();
+
+ begin_section("Neverhood");
+ add_person("Benjamin Haisch", "john_doe", "");
+ add_person("Filippos Karapetis", "[md5]", "");
+ end_section();
+
begin_section("Parallaction");
add_person("", "peres", "");
end_section();
@@ -744,6 +770,10 @@ begin_credits("Credits");
begin_section("Wintermute");
add_person("Einar Johan T. S&oslash;m&aring;en", "somaen", "");
end_section();
+
+ begin_section("ZVision");
+ add_person("Adrian Astley", "RichieSams", "");
+ end_section();
end_section();
@@ -754,10 +784,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 +844,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();
@@ -965,7 +995,7 @@ begin_credits("Credits");
end_section();
end_section();
- begin_section("Translations");
+ begin_section("GUI Translations");
begin_persons();
add_person("Thierry Crozat", "criezy", "Translation Lead");
end_persons();
@@ -1030,6 +1060,20 @@ begin_credits("Credits");
add_person("Lubomyr Lisen", "", "");
end_section();
end_section();
+ begin_section("Game Translations");
+ begin_section("CGE");
+ add_person("Dan Serban", "nutron", "Soltys English translation");
+ add_person("V&iacute;ctor Gonz&aacute;lez", "IlDucci", "Soltys Spanish translation");
+ add_person("Alejandro G&oacute;mez de la Mu&ntilde;oza", "TheFireRed", "Soltys Spanish translation");
+ end_section();
+ begin_section("Drascula");
+ add_person("Thierry Crozat", "criezy", "Improve French translation");
+ end_section();
+ begin_section("Mortevielle");
+ add_person("Hugo Labrande", "", "Improve English translation");
+ add_person("Thierry Crozat", "criezy", "Improve English translation");
+ end_section();
+ end_section();
begin_section("Websites (design)");
begin_persons();
@@ -1053,6 +1097,7 @@ begin_credits("Credits");
add_person("Janne Huttunen", "", "V3 actor mask support, Dig/FT SMUSH audio");
add_person("Kov&aacute;cs Endre J&aacute;nos", "", "Several fixes for Simon1");
add_person("Jeroen Janssen", "japj", "Numerous readability and bugfix patches");
+ add_person("Keith Kaisershot", "blitter", "Several Pegasus Prime patches");
add_person("Andreas Karlsson", "Sprawl", "Initial port for SymbianOS");
add_person("Claudio Matsuoka", "", "Daily Linux builds");
add_person("Thomas Mayer", "", "PSP port contributions");
@@ -1144,6 +1189,7 @@ begin_credits("Credits");
add_person("Jimmi Th&oslash;gersen", "", "For ScummRev, and much obscure code/documentation");
add_person("", "Tristan", "For additional work on the original MT-32 emulator");
add_person("James Woodcock", "", "Soundtrack enhancements");
+ add_person("Anton Yartsev", "Zidane", "For the original re-implementation of the ZVision engine");
end_persons();
add_paragraph(
diff --git a/devtools/extract_mort/extract_mort.cpp b/devtools/extract_mort/extract_mort.cpp
new file mode 100644
index 0000000000..a52458f9b2
--- /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() {
+ uint32 position = ftell(f);
+ fseek (f, 0, SEEK_END);
+ uint32 end = ftell(f);
+ fseek (f, position, 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 414a25e906..a52bbaecf8 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -346,7 +346,8 @@ ft Full Throttle
4bedb49943df95a9c900a5a82ccbe9de -1 fr All? - - - cyx
8bdb0bf87b5e303dd35693afb9351215 -1 de All? - - - dhewg
55518cd73cf9c6d23ea29c51ee06bdfe -1 it All? - - - delfino
- 55e4cc866ff9046824e1c638ba2b8c7f -1 ru All? - - - sev
+ 55e4cc866ff9046824e1c638ba2b8c7f -1 ru All? - Akella - sev
+ 291fb06071e65897f755846611f5ad40 19697 ru All? - 7-Wolf - sev
e72bb4c2b613db2cf50f89ff6350e70a -1 es All? - - -
fe381e45117878b1e942cb876b050fd6 513243679 en Mac - - Mac bundle Fingolfin
04401d747f1a2c1c4b388daff71ed378 535405461 de Mac - - Mac bundle Fingolfin
@@ -597,6 +598,7 @@ catalog Humongous Interactive Catalog
a56e8d9d4281c53c3f63c9bd22a59e21 10978342 en All HE CUP Preview George Kormendi
74da3494fbe1a7d20213b0afe0954755 10841544 fr All HE CUP Preview - George Kormendi
4c4820518e16e1a0e3616a3b021a04f3 10927456 de All HE CUP Preview - Kirben
+ 288fb75b24389733c29fa107fe8d44e8 10795148 us All HE CUP Preview - Kirben
airport Let's Explore the Airport with Buzzy
d6334a5a9b61afe18c368540fdf522ca -1 en Mac - - - Joachim Eberhard
@@ -625,7 +627,8 @@ jungle Let's Explore the Jungle with Buzzy
8801fb4a1200b347f7a38523339526dd -1 en Windows - - - Kirben
moonbase Moonbase Commander
- cf400d20769fb70eb21766582f4924f7 -1 en Windows - - - Kirben
+ cf400d20769fb70eb21766582f4924f7 -1 en Windows 1.0 1.0 - Kirben
+ e1c9998826ce7fa8bde5cc3a5023edec -1 en Windows 1.1 1.1 - fuzzie
ef71a322b6530ac45b1a070f7c0795f7 -1 en Windows Demo Demo - Kirben
pajama Pajama Sam 1: No Need to Hide When It's Dark Outside
@@ -653,6 +656,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
@@ -772,6 +776,7 @@ puttzoo Putt-Putt Saves the Zoo
3a3e592b074f595489f7f11e150c398d -1 us Windows HE 99 Updated - Adrian
c5cc7cba02a2fbd539c4439e775b0536 43470 de Windows HE 99 Updated - Lightkey
5c9cecbd2952ccec14c9ecebf5822a34 -1 en iOS HE 100 - - clone2727
+ 7b4ee071eecadc2d8cd0c3509110825c -1 en Windows HE 100 Remastered - Kirben
3486ede0f904789267d4bcc5537a46d4 14337 en Mac - Demo - khalek
d220d154aafbfa12bd6f3ab1b2dae420 -1 de Mac - Demo - Joachim Eberhard
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/android/AndroidManifest.xml b/dists/android/AndroidManifest.xml
index 320ed16a6e..16d1ee578b 100644
--- a/dists/android/AndroidManifest.xml
+++ b/dists/android/AndroidManifest.xml
@@ -36,6 +36,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="tv.ouya.intent.category.GAME"/>
</intent-filter>
</activity>
</application>
diff --git a/dists/android/AndroidManifest.xml.in b/dists/android/AndroidManifest.xml.in
index 8f7887eaf5..bf45ffcc0e 100644
--- a/dists/android/AndroidManifest.xml.in
+++ b/dists/android/AndroidManifest.xml.in
@@ -36,6 +36,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="tv.ouya.intent.category.GAME"/>
</intent-filter>
</activity>
</application>
diff --git a/dists/android/res-ouya/values-television/margins.xml b/dists/android/res-ouya/values-television/margins.xml
new file mode 100644
index 0000000000..df586eea34
--- /dev/null
+++ b/dists/android/res-ouya/values-television/margins.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="verticalMargin">45px</dimen>
+ <dimen name="horizontalMargin">80px</dimen>
+</resources>
diff --git a/dists/android/res/drawable-xhdpi/ouya_icon.png b/dists/android/res/drawable-xhdpi/ouya_icon.png
new file mode 100644
index 0000000000..42f9a2a8ce
--- /dev/null
+++ b/dists/android/res/drawable-xhdpi/ouya_icon.png
Binary files differ
diff --git a/dists/android/res/layout/main.xml b/dists/android/res/layout/main.xml
index 8b0d515d62..31aa345cc7 100644
--- a/dists/android/res/layout/main.xml
+++ b/dists/android/res/layout/main.xml
@@ -9,4 +9,8 @@
android:keepScreenOn="true"
android:focusable="true"
android:focusableInTouchMode="true"
+ android:layout_marginTop="@dimen/verticalMargin"
+ android:layout_marginLeft="@dimen/horizontalMargin"
+ android:layout_marginBottom="@dimen/verticalMargin"
+ android:layout_marginRight="@dimen/horizontalMargin"
/>
diff --git a/dists/android/res/values/margins.xml b/dists/android/res/values/margins.xml
new file mode 100644
index 0000000000..a865687b3a
--- /dev/null
+++ b/dists/android/res/values/margins.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="verticalMargin">0px</dimen>
+ <dimen name="horizontalMargin">0px</dimen>
+</resources>
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..0d6a44206d
--- /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/redhat/scummvm.spec b/dists/redhat/scummvm.spec
index 823b74df5e..33622ffb9b 100644
--- a/dists/redhat/scummvm.spec
+++ b/dists/redhat/scummvm.spec
@@ -72,6 +72,7 @@ install -m644 -D dists/engine-data/sky.cpt %{buildroot}%{_datadir}/scummvm/sky.c
install -m644 -D dists/engine-data/drascula.dat %{buildroot}%{_datadir}/scummvm/drascula.dat
install -m644 -D dists/engine-data/teenagent.dat %{buildroot}%{_datadir}/scummvm/teenagent.dat
install -m644 -D dists/engine-data/hugo.dat %{buildroot}%{_datadir}/scummvm/hugo.dat
+install -m644 -D dists/engine-data/tony.dat %{buildroot}%{_datadir}/scummvm/tony.dat
install -m644 -D dists/engine-data/toon.dat %{buildroot}%{_datadir}/scummvm/toon.dat
desktop-file-install --vendor scummvm --dir=%{buildroot}/%{_datadir}/applications dists/scummvm.desktop
@@ -111,6 +112,7 @@ fi
%{_datadir}/scummvm/drascula.dat
%{_datadir}/scummvm/teenagent.dat
%{_datadir}/scummvm/hugo.dat
+%{_datadir}/scummvm/tony.dat
%{_datadir}/scummvm/toon.dat
%{_mandir}/man6/scummvm.6*
diff --git a/dists/redhat/scummvm.spec.in b/dists/redhat/scummvm.spec.in
index 9dbd8add5b..5db2807d0e 100644
--- a/dists/redhat/scummvm.spec.in
+++ b/dists/redhat/scummvm.spec.in
@@ -72,6 +72,7 @@ install -m644 -D dists/engine-data/sky.cpt %{buildroot}%{_datadir}/scummvm/sky.c
install -m644 -D dists/engine-data/drascula.dat %{buildroot}%{_datadir}/scummvm/drascula.dat
install -m644 -D dists/engine-data/teenagent.dat %{buildroot}%{_datadir}/scummvm/teenagent.dat
install -m644 -D dists/engine-data/hugo.dat %{buildroot}%{_datadir}/scummvm/hugo.dat
+install -m644 -D dists/engine-data/tony.dat %{buildroot}%{_datadir}/scummvm/tony.dat
install -m644 -D dists/engine-data/toon.dat %{buildroot}%{_datadir}/scummvm/toon.dat
desktop-file-install --vendor scummvm --dir=%{buildroot}/%{_datadir}/applications dists/scummvm.desktop
@@ -111,6 +112,7 @@ fi
%{_datadir}/scummvm/drascula.dat
%{_datadir}/scummvm/teenagent.dat
%{_datadir}/scummvm/hugo.dat
+%{_datadir}/scummvm/tony.dat
%{_datadir}/scummvm/toon.dat
%{_mandir}/man6/scummvm.6*
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index c457e23b16..037db3ef62 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -32,6 +32,12 @@ 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
#if ENABLE_QUEEN == STATIC_PLUGIN
queen.tbl FILE "dists/engine-data/queen.tbl"
#endif
@@ -41,6 +47,9 @@ sky.cpt FILE "dists/engine-data/sky.cpt"
#if ENABLE_TEENAGENT == STATIC_PLUGIN
teenagent.dat FILE "dists/engine-data/teenagent.dat"
#endif
+#if ENABLE_TONY == STATIC_PLUGIN
+tony.dat FILE "dists/engine-data/tony.dat"
+#endif
#if ENABLE_TOON == STATIC_PLUGIN
toon.dat FILE "dists/engine-data/toon.dat"
#endif
diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in
index f986cc52e8..c18c18ef63 100644
--- a/dists/scummvm.rc.in
+++ b/dists/scummvm.rc.in
@@ -32,6 +32,12 @@ 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
#if ENABLE_QUEEN == STATIC_PLUGIN
queen.tbl FILE "dists/engine-data/queen.tbl"
#endif
@@ -41,6 +47,9 @@ sky.cpt FILE "dists/engine-data/sky.cpt"
#if ENABLE_TEENAGENT == STATIC_PLUGIN
teenagent.dat FILE "dists/engine-data/teenagent.dat"
#endif
+#if ENABLE_TONY == STATIC_PLUGIN
+tony.dat FILE "dists/engine-data/tony.dat"
+#endif
#if ENABLE_TOON == STATIC_PLUGIN
toon.dat FILE "dists/engine-data/toon.dat"
#endif
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b1d1008b60..40783a2407 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"
@@ -78,7 +78,7 @@ static Common::String generatePreferredTarget(const Common::String &id, const AD
res = res + "-cd";
}
- if (desc->platform != Common::kPlatformDOS && desc->platform != Common::kPlatformUnknown) {
+ if (desc->platform != Common::kPlatformDOS && desc->platform != Common::kPlatformUnknown && !(desc->flags & ADGF_DROPPLATFORM)) {
res = res + "-" + getPlatformAbbrev(desc->platform);
}
@@ -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..376a59e471 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -87,7 +87,8 @@ enum ADGameFlags {
ADGF_ADDENGLISH = (1 << 24), ///< always add English as language option
ADGF_MACRESFORK = (1 << 25), ///< the md5 for this entry will be calculated from the resource fork
ADGF_USEEXTRAASTITLE = (1 << 26), ///< Extra field value will be used as main game title, not gameid
- ADGF_DROPLANGUAGE = (1 << 28), ///< don't add language to gameid
+ ADGF_DROPLANGUAGE = (1 << 27), ///< don't add language to gameid
+ ADGF_DROPPLATFORM = (1 << 28), ///< don't add platform to gameid
ADGF_CD = (1 << 29), ///< add "-cd" to gameid
ADGF_DEMO = (1 << 30) ///< add "-demo" to gameid
};
@@ -280,6 +281,9 @@ protected:
return 0;
}
+private:
+ void initSubSystems(const ADGameDescription *gameDesc) const;
+
protected:
/**
* Detect games in specified directory.
diff --git a/engines/agi/POTFILES b/engines/agi/POTFILES
new file mode 100644
index 0000000000..414bf2250d
--- /dev/null
+++ b/engines/agi/POTFILES
@@ -0,0 +1,2 @@
+engines/agi/detection.cpp
+engines/agi/saveload.cpp
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/configure.engine b/engines/agi/configure.engine
new file mode 100644
index 0000000000..fad659f86d
--- /dev/null
+++ b/engines/agi/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine agi "AGI" yes
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 0c2c3ed3be..a7a3920df8 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -642,6 +642,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"),
FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"),
GAME("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a", 0x2917, GID_FANMADE),
+ FANMADE("AGI Tetris (1998)", "1afcbc25bfafded2d5fb82de9da0bd9a"),
FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440),
FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256),
FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2),
@@ -848,6 +849,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"),
FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"),
FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"),
+ FANMADE("Ultimate AGI Fangame (Demo)", "2d14d6fa2a2136d681e46e06821905bf"),
FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"),
FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"),
{
diff --git a/engines/agi/loader_v1.cpp b/engines/agi/loader_v1.cpp
index 33e956af41..3b862ed91f 100644
--- a/engines/agi/loader_v1.cpp
+++ b/engines/agi/loader_v1.cpp
@@ -202,7 +202,7 @@ int AgiLoader_v1::loadResource(int t, int n) {
uint8 *data = NULL;
debugC(3, kDebugLevelResources, "(t = %d, n = %d)", t, n);
- if (n > MAX_DIRS)
+ if (n >= MAX_DIRS)
return errBadResource;
switch (t) {
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index ee69bb5b27..458927a3bc 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -178,7 +178,7 @@ int AgiLoader_v2::loadResource(int t, int n) {
uint8 *data = NULL;
debugC(3, kDebugLevelResources, "(t = %d, n = %d)", t, n);
- if (n > MAX_DIRS)
+ if (n >= MAX_DIRS)
return errBadResource;
switch (t) {
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 250d8e7615..1dd00dc18e 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -257,7 +257,7 @@ int AgiLoader_v3::loadResource(int t, int n) {
int ec = errOK;
uint8 *data = NULL;
- if (n > MAX_DIRS)
+ if (n >= MAX_DIRS)
return errBadResource;
switch (t) {
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 807ab2dc2c..d893e44c12 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -367,6 +367,18 @@ void AgiEngine::setupOpcodes() {
logicNamesTest = insV2Test;
logicNamesCmd = insV2;
+
+ // Alter opcode parameters for specific games
+ // TODO: This could be either turned into a game feature, or a version
+ // specific check, instead of a game version check
+
+ // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
+ // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
+ if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
+ getPlatform() == Common::kPlatformApple2GS) {
+ logicNamesCmd[176].args = "n"; // hide.mouse
+ logicNamesCmd[178].args = "n"; // show.mouse
+ }
} else {
for (int i = 0; i < ARRAYSIZE(insV1Test); ++i)
_agiCondCommands[i] = insV1Test[i].func;
@@ -376,18 +388,6 @@ void AgiEngine::setupOpcodes() {
logicNamesTest = insV1Test;
logicNamesCmd = insV1;
}
-
- // Alter opcode parameters for specific games
- // TODO: This could be either turned into a game feature, or a version
- // specific check, instead of a game version check
-
- // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
- // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
- if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
- getPlatform() == Common::kPlatformApple2GS) {
- logicNamesCmd[176].args = "n"; // hide.mouse
- logicNamesCmd[178].args = "n"; // show.mouse
- }
}
}
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index ed4882fcab..d0f6540651 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -850,7 +850,7 @@ void MickeyEngine::drawRoomAnimation() {
}
void MickeyEngine::drawRoom() {
- uint8 buffer[256];
+ uint8 buffer[512];
int pBuf = 0;
int nObjs;
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/agi/wagparser.cpp b/engines/agi/wagparser.cpp
index 8dee6545c0..644ca7c103 100644
--- a/engines/agi/wagparser.cpp
+++ b/engines/agi/wagparser.cpp
@@ -178,7 +178,7 @@ bool WagFileParser::parse(const Common::FSNode &node) {
_parsedOk = false; // We haven't parsed the file yet
stream = node.createReadStream(); // Open the file
- if (stream) { // Check that opening the file was succesful
+ if (stream) { // Check that opening the file was successful
if (checkWagVersion(*stream)) { // Check that WinAGI version string is valid
// It seems we've got a valid *.wag file so let's parse its properties from the start.
stream->seek(0); // Rewind the stream
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 9c5b3d349a..f423995de8 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -93,14 +93,25 @@ int AgiEngine::loadWords(const char *fname) {
} while (!(c & 0x80) && k < (int)sizeof(str) - 1);
str[k] = 0;
- // And store it in our internal dictionary
- AgiWord *w = new AgiWord;
- w->word = myStrndup(str, k);
- w->id = fp.readUint16BE();
- _game.words[i].push_back(w);
+ // WORKAROUND:
+ // The SQ0 fan game stores words starting with numbers (like '7up')
+ // in its dictionary under the 'a' entry. We skip these.
+ // See bug #3615061
+ if (str[0] == 'a' + i) {
+ // And store it in our internal dictionary
+ AgiWord *w = new AgiWord;
+ w->word = myStrndup(str, k);
+ w->id = fp.readUint16BE();
+ _game.words[i].push_back(w);
+ }
+
+ k = fp.readByte();
// Are there more words with an already known prefix?
- if (!(k = fp.readByte()))
+ // WORKAROUND: We only break after already seeing words with the
+ // right prefix, for the SQ0 words starting with digits filed under
+ // 'a'. See above comment and bug #3615061.
+ if (k == 0 && str[0] >= 'a' + i)
break;
}
}
diff --git a/engines/agos/POTFILES b/engines/agos/POTFILES
new file mode 100644
index 0000000000..7045ed9afe
--- /dev/null
+++ b/engines/agos/POTFILES
@@ -0,0 +1,2 @@
+engines/agos/saveload.cpp
+engines/agos/animation.cpp
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 65f8dd1420..87a1228c6a 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -1272,7 +1272,7 @@ protected:
Item *getNextItemPtrStrange();
- virtual bool loadGame(const char *filename, bool restartMode = false);
+ virtual bool loadGame(const Common::String &filename, bool restartMode = false);
virtual bool saveGame(uint slot, const char *caption);
void openTextWindow();
@@ -1311,7 +1311,7 @@ protected:
int countSaveGames();
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
class AGOSEngine_PN : public AGOSEngine {
@@ -1517,8 +1517,8 @@ protected:
virtual void windowPutChar(WindowBlock *window, byte c, byte b = 0);
bool badload(int8 errorNum);
- int loadFile(char *name);
- int saveFile(char *name);
+ int loadFile(const Common::String &name);
+ int saveFile(const Common::String &name);
void getFilename();
void sysftodb();
void dbtosysf();
@@ -1640,7 +1640,7 @@ protected:
virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
class AGOSEngine_Elvira2 : public AGOSEngine_Elvira1 {
@@ -1709,7 +1709,7 @@ protected:
virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp);
- virtual bool loadGame(const char *filename, bool restartMode = false);
+ virtual bool loadGame(const Common::String &filename, bool restartMode = false);
virtual bool saveGame(uint slot, const char *caption);
virtual void addArrows(WindowBlock *window, uint8 num);
@@ -1735,7 +1735,7 @@ protected:
virtual void userGame(bool load);
virtual int userGameGetKey(bool *b, char *buf, uint maxChar);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
class AGOSEngine_Waxworks : public AGOSEngine_Elvira2 {
@@ -1802,7 +1802,7 @@ protected:
virtual bool confirmOverWrite(WindowBlock *window);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
class AGOSEngine_Simon1 : public AGOSEngine_Waxworks {
@@ -1873,7 +1873,7 @@ protected:
virtual void vcStopAnimation(uint16 zone, uint16 sprite);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
class AGOSEngine_Simon2 : public AGOSEngine_Simon1 {
@@ -1919,7 +1919,7 @@ protected:
virtual void playSpeech(uint16 speechId, uint16 vgaSpriteId);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
#ifdef ENABLE_AGOS2
@@ -2059,7 +2059,7 @@ protected:
void saveUserGame(int slot);
void windowBackSpace(WindowBlock *window);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
virtual void quickLoadOrSave();
};
@@ -2139,7 +2139,7 @@ protected:
void printInfoText(const char *itemText);
- virtual char *genSaveName(int slot);
+ virtual Common::String genSaveName(int slot) const;
};
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 9176412e0e..40c9d1d049 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -272,7 +272,7 @@ void MoviePlayerDXA::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
if (!surface)
return;
- byte *src = (byte *)surface->pixels;
+ const byte *src = (const byte *)surface->getPixels();
dst += y * pitch + x;
do {
@@ -344,7 +344,7 @@ void MoviePlayerDXA::handleNextFrame() {
bool MoviePlayerDXA::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
+ copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
uint32 soundTime = _mixer->getSoundElapsedTime(_bgSound);
@@ -443,7 +443,7 @@ void MoviePlayerSMK::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
if (!surface)
return;
- byte *src = (byte *)surface->pixels;
+ const byte *src = (const byte *)surface->getPixels();
dst += y * pitch + x;
do {
@@ -495,7 +495,7 @@ void MoviePlayerSMK::nextFrame() {
bool MoviePlayerSMK::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
+ copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
uint32 waitTime = getTimeToNextFrame();
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index 262ae44f01..b6b90eefcc 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -2924,7 +2924,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
Graphics::Surface *screen = _system->lockScreen();
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dstPitch = screen->pitch;
h = 8;
w = 6;
@@ -2961,7 +2961,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
error("windowDrawChar: Unknown language %d", _language);
}
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dstPitch = screen->pitch;
h = 8;
w = 6;
@@ -2986,14 +2986,14 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
error("windowDrawChar: Unknown language %d", _language);
}
} else if (getGameType() == GType_ELVIRA1) {
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dstPitch = screen->pitch;
h = 8;
w = 6;
src = english_elvira1Font + (chr - 32) * 8;
} else {
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dstPitch = screen->pitch;
h = 8;
w = 8;
diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp
index f58f4397b5..eca9728643 100644
--- a/engines/agos/charset.cpp
+++ b/engines/agos/charset.cpp
@@ -362,7 +362,7 @@ void AGOSEngine::windowScroll(WindowBlock *window) {
w = window->width * 8;
h = (window->height -1) * 8;
- dst = (byte *)screen->pixels + window->y * screen->pitch + window->x * 8;
+ dst = (byte *)screen->getBasePtr(window->x * 8, window->y);
src = dst + 8 * screen->pitch;
do {
diff --git a/engines/agos/configure.engine b/engines/agos/configure.engine
new file mode 100644
index 0000000000..3ae1fb16f2
--- /dev/null
+++ b/engines/agos/configure.engine
@@ -0,0 +1,4 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine agos "AGOS" yes "agos2" "AGOS 1 games"
+add_engine agos2 "AGOS 2 games" yes
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index cf3a12ceb8..d27aed29db 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -32,15 +32,15 @@
namespace AGOS {
byte *AGOSEngine::getBackBuf() {
- return (byte *)_backBuf->pixels;
+ return (byte *)_backBuf->getPixels();
}
byte *AGOSEngine::getBackGround() {
- return (byte *)_backGroundBuf->pixels;
+ return (byte *)_backGroundBuf->getPixels();
}
byte *AGOSEngine::getScaleBuf() {
- return (byte *)_scaleBuf->pixels;
+ return (byte *)_scaleBuf->getPixels();
}
#ifdef ENABLE_AGOS2
@@ -226,7 +226,7 @@ void AGOSEngine::animateSprites() {
debug(0, "Using special wall");
uint8 color, h, len;
- byte *dst = (byte *)_window4BackScn->pixels;
+ byte *dst = (byte *)_window4BackScn->getPixels();
color = (_variableArray[293] & 1) ? 13 : 15;
_wallOn = 2;
@@ -256,7 +256,7 @@ void AGOSEngine::animateSprites() {
} else if (getGameType() == GType_ELVIRA2 && _variableArray[71] & 2) {
// Used by the Unholy Barrier spell
uint8 color, h, len;
- byte *dst = (byte *)_window4BackScn->pixels;
+ byte *dst = (byte *)_window4BackScn->getPixels();
color = 1;
_wallOn = 2;
@@ -491,7 +491,7 @@ void AGOSEngine::saveBackGround(VgaSprite *vsp) {
int16 y = vsp->y - _scrollY;
if (_window3Flag == 1) {
- animTable->srcPtr = (const byte *)_window4BackScn->pixels;
+ animTable->srcPtr = (const byte *)_window4BackScn->getPixels();
} else {
int xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8;
int yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y);
@@ -565,7 +565,7 @@ void AGOSEngine::displayBoxStars() {
if (x_ >= 311)
continue;
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += (((screen->pitch / 4) * y_) * 4) + x_;
@@ -673,7 +673,7 @@ void AGOSEngine::scrollScreen() {
if (getGameType() == GType_SIMON2) {
src = getBackGround();
- dst = (byte *)_window4BackScn->pixels;
+ dst = (byte *)_window4BackScn->getPixels();
for (int i = 0; i < _scrollHeight; i++) {
memcpy(dst, src, _screenWidth);
src += _backGroundBuf->pitch;
@@ -725,7 +725,7 @@ void AGOSEngine::fillBackFromBackGround(uint16 height, uint16 width) {
void AGOSEngine::fillBackFromFront() {
Graphics::Surface *screen = _system->lockScreen();
- byte *src = (byte *)screen->pixels;
+ byte *src = (byte *)screen->getPixels();
byte *dst = getBackBuf();
for (int i = 0; i < _screenHeight; i++) {
@@ -748,7 +748,7 @@ void AGOSEngine::fillBackGroundFromBack() {
void AGOSEngine::fillBackGroundFromFront() {
Graphics::Surface *screen = _system->lockScreen();
- byte *src = (byte *)screen->pixels;
+ byte *src = (byte *)screen->getPixels();
byte *dst = getBackGround();
for (int i = 0; i < _screenHeight; i++) {
@@ -785,7 +785,7 @@ void AGOSEngine::displayScreen() {
Graphics::Surface *screen = _system->lockScreen();
if (getGameType() == GType_PP || getGameType() == GType_FF) {
byte *src = getBackBuf();
- byte *dst = (byte *)screen->pixels;
+ byte *dst = (byte *)screen->getPixels();
for (int i = 0; i < _screenHeight; i++) {
memcpy(dst, src, _screenWidth);
src += _backBuf->pitch;
@@ -798,9 +798,9 @@ void AGOSEngine::displayScreen() {
_window4Flag = 0;
uint16 srcWidth, width, height;
- byte *dst = (byte *)screen->pixels;
+ byte *dst = (byte *)screen->getPixels();
- const byte *src = (const byte *)_window4BackScn->pixels;
+ const byte *src = (const byte *)_window4BackScn->getPixels();
if (_window3Flag == 1) {
src = getBackGround();
}
@@ -831,8 +831,8 @@ void AGOSEngine::displayScreen() {
if (_window6Flag == 2) {
_window6Flag = 0;
- byte *src = (byte *)_window6BackScn->pixels;
- byte *dst = (byte *)screen->pixels + 51 * screen->pitch;
+ byte *src = (byte *)_window6BackScn->getPixels();
+ byte *dst = (byte *)screen->getBasePtr(0, 51);
for (int i = 0; i < 80; i++) {
memcpy(dst, src, _window6BackScn->w);
dst += screen->pitch;
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index cc1c40c207..65c7f7fd77 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -365,7 +365,7 @@ void AGOSEngine::drawStuff(const byte *src, uint xoffs) {
const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135;
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels + y * screen->pitch + xoffs;
+ byte *dst = (byte *)screen->getBasePtr(xoffs, y);
for (uint h = 0; h < 6; h++) {
memcpy(dst, src, 4);
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index db0817250b..266fcc9796 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -649,7 +649,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
state->surf2_addr = getBackGround();
state->surf2_pitch = _backGroundBuf->pitch;
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _window4BackScn->pitch;
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
@@ -666,7 +666,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
state->surf2_addr = getBackGround();
state->surf2_pitch = _backGroundBuf->pitch;
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _videoWindows[18] * 16;
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
@@ -678,7 +678,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
_window4Flag = 1;
} else {
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
@@ -696,7 +696,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
state->surf2_addr = getBackGround();
state->surf2_pitch = _backGroundBuf->pitch;
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _window4BackScn->pitch;
}
@@ -712,7 +712,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
state->surf2_addr = getBackGround();
state->surf2_pitch = _backGroundBuf->pitch;
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
@@ -861,7 +861,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
uint16 xoffs = 0, yoffs = 0;
if (getGameType() == GType_WW) {
if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) {
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _videoWindows[18] * 16;
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
@@ -873,7 +873,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
_window4Flag = 1;
} else {
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
@@ -881,7 +881,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
}
} else if (getGameType() == GType_ELVIRA2) {
if (_windowNum == 4 || _windowNum >= 10) {
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _videoWindows[18] * 16;
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
@@ -893,7 +893,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
_window4Flag = 1;
} else {
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
@@ -901,19 +901,19 @@ void AGOSEngine::drawImage(VC10_state *state) {
}
} else if (getGameType() == GType_ELVIRA1) {
if (_windowNum == 6) {
- state->surf_addr = (byte *)_window6BackScn->pixels;
+ state->surf_addr = (byte *)_window6BackScn->getPixels();
state->surf_pitch = _window6BackScn->pitch;
xoffs = state->x * 8;
yoffs = state->y;
} else if (_windowNum == 2 || _windowNum == 3) {
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
yoffs = vlut[1] + state->y;
} else {
- state->surf_addr = (byte *)_window4BackScn->pixels;
+ state->surf_addr = (byte *)_window4BackScn->getPixels();
state->surf_pitch = _videoWindows[18] * 16;
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
@@ -926,7 +926,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
_window4Flag = 1;
}
} else {
- state->surf_addr = (byte *)screen->pixels;
+ state->surf_addr = (byte *)screen->getPixels();
state->surf_pitch = screen->pitch;
xoffs = (vlut[0] * 2 + state->x) * 8;
@@ -973,7 +973,7 @@ void AGOSEngine::horizontalScroll(VC10_state *state) {
vcWriteVar(251, _scrollX);
if (getGameType() == GType_SIMON2) {
- dst = (byte *)_window4BackScn->pixels;
+ dst = (byte *)_window4BackScn->getPixels();
dstPitch = _window4BackScn->pitch;
} else {
dst = getBackBuf();
@@ -1375,10 +1375,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
} else if (getGameType() == GType_SIMON1 && (getFeatures() & GF_DEMO)) {
// The DOS Floppy demo was based off Waxworks engine
if (updateWindow == 4 || updateWindow >= 10) {
- src = (byte *)_window4BackScn->pixels;
+ src = (byte *)_window4BackScn->getPixels();
srcWidth = _videoWindows[18] * 16;
} else if (updateWindow == 3 || updateWindow == 9) {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
@@ -1387,13 +1387,13 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
}
} else if (getGameType() == GType_SIMON1) {
if (updateWindow == 4) {
- src = (byte *)_window4BackScn->pixels;
+ src = (byte *)_window4BackScn->getPixels();
srcWidth = _videoWindows[18] * 16;
} else if (updateWindow >= 10) {
- src = (byte *)_window4BackScn->pixels + xoffs + yoffs * 320;
+ src = (byte *)_window4BackScn->getBasePtr(xoffs, yoffs);
srcWidth = _videoWindows[18] * 16;
} else if (updateWindow == 0) {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
@@ -1402,10 +1402,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
}
} else if (getGameType() == GType_WW) {
if (updateWindow == 4 || updateWindow >= 10) {
- src = (byte *)_window4BackScn->pixels;
+ src = (byte *)_window4BackScn->getPixels();
srcWidth = _videoWindows[18] * 16;
} else if (updateWindow == 3 || updateWindow == 9) {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
@@ -1414,10 +1414,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
}
} else if (getGameType() == GType_ELVIRA2) {
if (updateWindow == 4 || updateWindow >= 10) {
- src = (byte *)_window4BackScn->pixels;
+ src = (byte *)_window4BackScn->getPixels();
srcWidth = _videoWindows[18] * 16;
} else if (updateWindow == 3) {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
@@ -1427,17 +1427,17 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
} else if (getGameType() == GType_ELVIRA1) {
if (updateWindow == 6) {
_window6Flag = 1;
- src = (byte *)_window6BackScn->pixels;
+ src = (byte *)_window6BackScn->getPixels();
srcWidth = 48;
} else if (updateWindow == 2 || updateWindow == 3) {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
- src = (byte *)_window4BackScn->pixels;
+ src = (byte *)_window4BackScn->getPixels();
srcWidth = _videoWindows[18] * 16;
}
} else {
- src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs;
+ src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
}
@@ -1451,13 +1451,13 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
if (getGameType() == GType_PN && !_wiped && !specialCase) {
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
- dst = (byte *)screen->pixels + 48;
+ dst = (byte *)screen->getBasePtr(48, 0);
memset(dst, color, 224);
- dst = (byte *)screen->pixels + 132 * screen->pitch + 48;
+ dst = (byte *)screen->getBasePtr(48, 132);
memset(dst, color, 224);
} else if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) {
- dst = (byte *)screen->pixels + 133 * screen->pitch;
+ dst = (byte *)screen->getBasePtr(0, 133);
for (int h = 0; h < 67; h++) {
for (int w = 0; w < _screenWidth; w++)
@@ -1479,7 +1479,7 @@ void AGOSEngine::drawEdging() {
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels + 136 * screen->pitch;
+ dst = (byte *)screen->getBasePtr(0, 136);
uint8 len = 52;
while (len--) {
@@ -1488,7 +1488,7 @@ void AGOSEngine::drawEdging() {
dst += screen->pitch;
}
- dst = (byte *)screen->pixels + 187 * screen->pitch;
+ dst = (byte *)screen->getBasePtr(0, 187);
memset(dst, color, _screenWidth);
_system->unlockScreen();
diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp
index 0ee1d62fde..5647fece7e 100644
--- a/engines/agos/icons.cpp
+++ b/engines/agos/icons.cpp
@@ -202,7 +202,7 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += 110;
dst += x;
@@ -228,7 +228,7 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 25 + window->y) * screen->pitch;
@@ -256,7 +256,7 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 20 + window->y) * screen->pitch;
@@ -284,7 +284,7 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 8 + window->y) * screen->pitch;
@@ -312,7 +312,7 @@ void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 8 + window->y) * screen->pitch;
@@ -339,7 +339,7 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels + y * screen->pitch + x * 8;
+ dst = (byte *)screen->getBasePtr(x * 8, y);
src = _iconFilePtr + icon * 146;
if (icon == 0xFF) {
@@ -951,7 +951,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
}
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels + y * screen->pitch + x * 8;
+ byte *dst = (byte *)screen->getBasePtr(x * 8, y);
for (h = 0; h < 19; h++) {
for (w = 0; w < 16; w++) {
@@ -1042,7 +1042,7 @@ static const byte hitBarData[12 * 7] = {
// Personal Nightmare specific
void AGOSEngine_PN::drawIconHitBar() {
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels + 3 * screen->pitch + 6 * 8;
+ byte *dst = (byte *)screen->getBasePtr(6 * 8, 3);
const byte *src = hitBarData;
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
@@ -1089,15 +1089,15 @@ bool AGOSEngine_PN::ifObjectInInv(uint16 a) {
}
bool AGOSEngine_PN::testContainer(uint16 a) {
- return bitextract(_quickptr[1] + a * _quickshort[1], 0) != 0;
+ return bitextract(_quickptr[1] + a * _quickshort[1], 0) != 0;
}
bool AGOSEngine_PN::testObvious(uint16 a) {
- return bitextract(_quickptr[1] + a * _quickshort[1], 4) != 0;
+ return bitextract(_quickptr[1] + a * _quickshort[1], 4) != 0;
}
bool AGOSEngine_PN::testSeen(uint16 a) {
- return bitextract(_quickptr[1] + a * _quickshort[1], 3) != 0;
+ return bitextract(_quickptr[1] + a * _quickshort[1], 3) != 0;
}
void AGOSEngine_PN::printIcon(HitArea *ha, uint8 i, uint8 r) {
diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp
index a0d2bdcaa0..85c50e421b 100644
--- a/engines/agos/menus.cpp
+++ b/engines/agos/menus.cpp
@@ -164,7 +164,7 @@ void AGOSEngine::unlightMenuStrip() {
mouseOff();
Graphics::Surface *screen = _system->lockScreen();
- src = (byte *)screen->pixels + 8 * screen->pitch + 272;
+ src = (byte *)screen->getBasePtr(272, 8);
w = 48;
h = 82;
@@ -192,7 +192,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) {
mouseOff();
Graphics::Surface *screen = _system->lockScreen();
- src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x;
+ src = (byte *)screen->getBasePtr(ha->x, ha->y);
w = ha->width;
h = ha->height;
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 48671390f0..8eb7f066b3 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -33,32 +33,35 @@
namespace AGOS {
+
+// FIXME: This code counts savegames, but callers in many cases assume
+// that the return value + 1 indicates an empty slot.
int AGOSEngine::countSaveGames() {
Common::InSaveFile *f = NULL;
Common::StringArray filenames;
uint i = 1;
- char slot[4];
int slotNum;
bool marks[256];
- char *prefix = genSaveName(998);
- prefix[strlen(prefix)-3] = '*';
- prefix[strlen(prefix)-2] = '\0';
+ // Get the name of (possibly non-existent) savegame slot 998, and replace
+ // the extension by * to get a pattern.
+ Common::String tmp = genSaveName(998);
+ assert(tmp.size() >= 4 && tmp[tmp.size()-4] == '.');
+ Common::String prefix = Common::String(tmp.c_str(), tmp.size()-3) + "*";
+
memset(marks, false, 256 * sizeof(bool)); //assume no savegames for this title
filenames = _saveFileMan->listSavefiles(prefix);
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file){
//Obtain the last 3 digits of the filename, since they correspond to the save slot
- slot[0] = file->c_str()[file->size()-3];
- slot[1] = file->c_str()[file->size()-2];
- slot[2] = file->c_str()[file->size()-1];
- slot[3] = '\0';
-
- slotNum = atoi(slot);
+ assert(file->size() >= 4);
+ slotNum = atoi(file->c_str() + file->size() - 3);
if (slotNum >= 0 && slotNum < 256)
marks[slotNum] = true; //mark this slot as valid
}
+ // FIXME: Why does this already try to actually open the savegames?
+ // Historical accident?
while (i < 256) {
if (marks[i] &&
(f = _saveFileMan->openForLoading(genSaveName(i)))) {
@@ -72,68 +75,46 @@ int AGOSEngine::countSaveGames() {
}
#ifdef ENABLE_AGOS2
-char *AGOSEngine_PuzzlePack::genSaveName(int slot) {
- static char buf[20];
-
+Common::String AGOSEngine_PuzzlePack::genSaveName(int slot) const {
if (getGameId() == GID_DIMP)
- sprintf(buf, "dimp.sav");
+ return "dimp.sav";
else
- sprintf(buf, "swampy.sav");
-
- return buf;
+ return "swampy.sav";
}
-char *AGOSEngine_Feeble::genSaveName(int slot) {
- static char buf[20];
- sprintf(buf, "feeble.%.3d", slot);
- return buf;
+Common::String AGOSEngine_Feeble::genSaveName(int slot) const {
+ return Common::String::format("feeble.%.3d", slot);
}
#endif
-char *AGOSEngine_Simon2::genSaveName(int slot) {
- static char buf[20];
- sprintf(buf, "simon2.%.3d", slot);
- return buf;
+Common::String AGOSEngine_Simon2::genSaveName(int slot) const {
+ return Common::String::format("simon2.%.3d", slot);
}
-char *AGOSEngine_Simon1::genSaveName(int slot) {
- static char buf[20];
- sprintf(buf, "simon1.%.3d", slot);
- return buf;
+Common::String AGOSEngine_Simon1::genSaveName(int slot) const {
+ return Common::String::format("simon1.%.3d", slot);
}
-char *AGOSEngine_Waxworks::genSaveName(int slot) {
- static char buf[20];
-
+Common::String AGOSEngine_Waxworks::genSaveName(int slot) const {
if (getPlatform() == Common::kPlatformDOS)
- sprintf(buf, "waxworks-pc.%.3d", slot);
+ return Common::String::format("waxworks-pc.%.3d", slot);
else
- sprintf(buf, "waxworks.%.3d", slot);
-
- return buf;
+ return Common::String::format("waxworks.%.3d", slot);
}
-char *AGOSEngine_Elvira2::genSaveName(int slot) {
- static char buf[20];
-
+Common::String AGOSEngine_Elvira2::genSaveName(int slot) const {
if (getPlatform() == Common::kPlatformDOS)
- sprintf(buf, "elvira2-pc.%.3d", slot);
+ return Common::String::format("elvira2-pc.%.3d", slot);
else
- sprintf(buf, "elvira2.%.3d", slot);
-
- return buf;
+ return Common::String::format("elvira2.%.3d", slot);
}
-char *AGOSEngine_Elvira1::genSaveName(int slot) {
- static char buf[20];
- sprintf(buf, "elvira1.%.3d", slot);
- return buf;
+Common::String AGOSEngine_Elvira1::genSaveName(int slot) const {
+ return Common::String::format("elvira1.%.3d", slot);
}
-char *AGOSEngine::genSaveName(int slot) {
- static char buf[20];
- sprintf(buf, "pn.%.3d", slot);
- return buf;
+Common::String AGOSEngine::genSaveName(int slot) const {
+ return Common::String::format("pn.%.3d", slot);
}
#ifdef ENABLE_AGOS2
@@ -177,12 +158,12 @@ void AGOSEngine::quickLoadOrSave() {
waitForSync(1122);
}
- char *filename = genSaveName(_saveLoadSlot);
+ Common::String filename = genSaveName(_saveLoadSlot);
if (_saveLoadType == 2) {
Subroutine *sub;
success = loadGame(genSaveName(_saveLoadSlot));
if (!success) {
- buf = Common::String::format(_("Failed to load game state from file:\n\n%s"), filename);
+ buf = Common::String::format(_("Failed to load game state from file:\n\n%s"), filename.c_str());
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
drawIconArray(2, me(), 0, 0);
setBitFlag(97, true);
@@ -217,7 +198,7 @@ void AGOSEngine::quickLoadOrSave() {
} else {
success = saveGame(_saveLoadSlot, _saveLoadName);
if (!success)
- buf = Common::String::format(_("Failed to save game state to file:\n\n%s"), filename);
+ buf = Common::String::format(_("Failed to save game state to file:\n\n%s"), filename.c_str());
}
if (!success) {
@@ -225,7 +206,7 @@ void AGOSEngine::quickLoadOrSave() {
dialog.runModal();
} else if (_saveLoadType == 1) {
- buf = Common::String::format(_("Successfully saved game state in file:\n\n%s"), filename);
+ buf = Common::String::format(_("Successfully saved game state in file:\n\n%s"), filename.c_str());
GUI::TimedMessageDialog dialog(buf, 1500);
dialog.runModal();
@@ -1041,7 +1022,7 @@ void writeItemID(Common::WriteStream *f, uint16 val) {
f->writeUint32BE(val - 1);
}
-bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
+bool AGOSEngine::loadGame(const Common::String &filename, bool restartMode) {
char ident[100];
Common::SeekableReadStream *f = NULL;
uint num, item_index, i;
@@ -1215,7 +1196,7 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
return result;
}
-bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
+bool AGOSEngine_Elvira2::loadGame(const Common::String &filename, bool restartMode) {
char ident[100];
Common::SeekableReadStream *f = NULL;
uint num, item_index, i, j;
@@ -1633,7 +1614,7 @@ void AGOSEngine_PN::getFilename() {
}
}
-int AGOSEngine_PN::loadFile(char *name) {
+int AGOSEngine_PN::loadFile(const Common::String &name) {
Common::InSaveFile *f;
haltAnimation();
@@ -1666,7 +1647,7 @@ int AGOSEngine_PN::loadFile(char *name) {
return 0;
}
-int AGOSEngine_PN::saveFile(char *name) {
+int AGOSEngine_PN::saveFile(const Common::String &name) {
Common::OutSaveFile *f;
sysftodb();
haltAnimation();
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 60a1376f25..e98cd2795a 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -370,7 +370,7 @@ void AGOSEngine_PN::opn_opcode30() {
void AGOSEngine_PN::opn_opcode31() {
int a, slot = 0;
- char bf[60];
+ Common::String bf;
if ((a = varval()) > 2) {
setScriptReturn(false);
@@ -381,10 +381,10 @@ void AGOSEngine_PN::opn_opcode31() {
case 0:
getFilename();
slot = matchSaveGame(_saveFile, countSaveGames());
- strcpy(bf, genSaveName(slot));
+ bf = genSaveName(slot);
break;
case 1:
- strcpy(bf, "pn.sav");
+ bf = "pn.sav";
break;
case 2:
// NOTE: Is this case ever used?
@@ -404,7 +404,7 @@ void AGOSEngine_PN::opn_opcode31() {
}
void AGOSEngine_PN::opn_opcode32() {
- char bf[60];
+ Common::String bf;
int a, slot;
a = varval();
@@ -419,12 +419,12 @@ void AGOSEngine_PN::opn_opcode32() {
getFilename();
slot = matchSaveGame(_saveFile, curSlot);
if (slot != -1)
- strcpy(bf, genSaveName(slot));
+ bf = genSaveName(slot);
else
- strcpy(bf, genSaveName(curSlot));
+ bf = genSaveName(curSlot);
break;
case 1:
- strcpy(bf, "pn.sav");
+ bf = "pn.sav";
break;
case 2:
// NOTE: Is this case ever used?
diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp
index 93077ed83e..f5b57a01c8 100644
--- a/engines/agos/verb.cpp
+++ b/engines/agos/verb.cpp
@@ -973,7 +973,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x;
+ src = (byte *)screen->getBasePtr(ha->x, ha->y);
// WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations
if (getGameType() == GType_SIMON2 && ha->id >= 208 && ha->id <= 213) {
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index 8541f579d6..cc5ede5f2c 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -1179,7 +1179,7 @@ void AGOSEngine::vc32_saveScreen() {
if (getGameType() == GType_PN) {
Graphics::Surface *screen = _system->lockScreen();
byte *dst = getBackGround();
- byte *src = (byte *)screen->pixels;
+ byte *src = (byte *)screen->getPixels();
for (int i = 0; i < _screenHeight; i++) {
memcpy(dst, src, _screenWidth);
dst += _backGroundBuf->pitch;
@@ -1193,7 +1193,7 @@ void AGOSEngine::vc32_saveScreen() {
uint16 height = _videoWindows[4 * 4 + 3];
byte *dst = (byte *)_backGroundBuf->getBasePtr(xoffs, yoffs);
- byte *src = (byte *)_window4BackScn->pixels;
+ byte *src = (byte *)_window4BackScn->getPixels();
uint16 srcWidth = _videoWindows[4 * 4 + 2] * 16;
for (; height > 0; height--) {
memcpy(dst, src, width);
@@ -1247,7 +1247,7 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) {
if (getGameType() == GType_ELVIRA1 && num == 3) {
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels;
+ byte *dst = (byte *)screen->getPixels();
for (int i = 0; i < _screenHeight; i++) {
memset(dst, color, _screenWidth);
dst += screen->pitch;
@@ -1258,7 +1258,10 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) {
uint16 xoffs = (vlut[0] - _videoWindows[16]) * 16;
uint16 yoffs = (vlut[1] - _videoWindows[17]);
uint16 dstWidth = _videoWindows[18] * 16;
- byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth;
+ // TODO: Is there any known connection between dstWidth and the pitch
+ // of the _window4BackScn Surface? If so, we might be able to pass
+ // yoffs as proper y parameter to getBasePtr.
+ byte *dst = (byte *)_window4BackScn->getBasePtr(xoffs, 0) + yoffs * dstWidth;
setMoveRect(0, 0, vlut[2] * 16, vlut[3]);
diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp
index d4aafd3d7b..4eb337c687 100644
--- a/engines/agos/vga_e2.cpp
+++ b/engines/agos/vga_e2.cpp
@@ -76,7 +76,7 @@ void AGOSEngine::vc45_setWindowPalette() {
uint8 height = vlut[3];
if (num == 4) {
- byte *dst = (byte *)_window4BackScn->pixels;
+ byte *dst = (byte *)_window4BackScn->getPixels();
for (uint8 h = 0; h < height; h++) {
for (uint8 w = 0; w < width; w++) {
@@ -223,11 +223,11 @@ void AGOSEngine::vc53_dissolveIn() {
uint16 count = dissolveCheck * 2;
while (count--) {
Graphics::Surface *screen = _system->lockScreen();
- byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch;
+ byte *dstPtr = (byte *)screen->getBasePtr(x, y);
yoffs = _rnd.getRandomNumber(dissolveY);
dst = dstPtr + yoffs * screen->pitch;
- src = (byte *)_window4BackScn->pixels + yoffs * _window4BackScn->pitch;
+ src = (byte *)_window4BackScn->getBasePtr(0, yoffs);
xoffs = _rnd.getRandomNumber(dissolveX);
dst += xoffs;
@@ -296,7 +296,7 @@ void AGOSEngine::vc54_dissolveOut() {
uint16 count = dissolveCheck * 2;
while (count--) {
Graphics::Surface *screen = _system->lockScreen();
- byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch;
+ byte *dstPtr = (byte *)screen->getBasePtr(x, y);
color |= dstPtr[0] & 0xF0;
yoffs = _rnd.getRandomNumber(dissolveY);
@@ -378,7 +378,7 @@ void AGOSEngine::fullFade() {
void AGOSEngine::vc56_fullScreen() {
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels;
+ byte *dst = (byte *)screen->getPixels();
byte *src = _curVgaFile2 + 800;
for (int i = 0; i < _screenHeight; i++) {
diff --git a/engines/agos/vga_pn.cpp b/engines/agos/vga_pn.cpp
index 1e7b2ba060..b7f80ebf91 100644
--- a/engines/agos/vga_pn.cpp
+++ b/engines/agos/vga_pn.cpp
@@ -155,7 +155,7 @@ void AGOSEngine::vc48_specialEffect() {
if (getPlatform() == Common::kPlatformDOS) {
if (num == 1) {
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels;
+ byte *dst = (byte *)screen->getPixels();
for (uint h = 0; h < _screenHeight; h++) {
for (uint w = 0; w < _screenWidth; w++) {
@@ -205,7 +205,7 @@ void AGOSEngine_PN::clearVideoWindow(uint16 num, uint16 color) {
uint16 yoffs = vlut[1];
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels + xoffs + yoffs * screen->pitch;
+ byte *dst = (byte *)screen->getBasePtr(xoffs, yoffs);
for (uint h = 0; h < vlut[3]; h++) {
memset(dst, color, vlut[2] * 16);
dst += screen->pitch;
diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp
index 9b9ed4e297..e0780b491a 100644
--- a/engines/agos/vga_s2.cpp
+++ b/engines/agos/vga_s2.cpp
@@ -213,7 +213,10 @@ void AGOSEngine_Simon2::clearVideoWindow(uint16 num, uint16 color) {
uint16 xoffs = vlut[0] * 16;
uint16 yoffs = vlut[1];
uint16 dstWidth = _videoWindows[18] * 16;
- byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth;
+ // TODO: Is there any known connection between dstWidth and the pitch
+ // of the _window4BackScn Surface? If so, we might be able to pass
+ // yoffs as proper y parameter to getBasePtr.
+ byte *dst = (byte *)_window4BackScn->getBasePtr(xoffs, 0) + yoffs * dstWidth;
setMoveRect(0, 0, vlut[2] * 16, vlut[3]);
diff --git a/engines/agos/vga_ww.cpp b/engines/agos/vga_ww.cpp
index c74f0cf52b..ca93fa9fec 100644
--- a/engines/agos/vga_ww.cpp
+++ b/engines/agos/vga_ww.cpp
@@ -143,7 +143,7 @@ void AGOSEngine::vc61() {
uint h, tmp;
Graphics::Surface *screen = _system->lockScreen();
- dstPtr = (byte *)screen->pixels;
+ dstPtr = (byte *)screen->getPixels();
if (a == 6) {
src = _curVgaFile2 + 800;
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index 0365c736d8..892df92554 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -170,7 +170,7 @@ void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, u
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
- byte *dst = (byte *)screen->pixels + y * screen->pitch + x;
+ byte *dst = (byte *)screen->getBasePtr(x, y);
uint8 color = window->fillColor;
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
@@ -232,7 +232,7 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) {
uint i;
Graphics::Surface *screen = _system->lockScreen();
- dst = (byte *)screen->pixels;
+ dst = (byte *)screen->getPixels();
src = getBackGround();
dst += y * screen->pitch;
diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp
new file mode 100644
index 0000000000..cef4088722
--- /dev/null
+++ b/engines/avalanche/animation.cpp
@@ -0,0 +1,1498 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* TRIP5 Trippancy V - the sprite animation subsystem */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/animation.h"
+
+namespace Avalanche {
+
+// Art gallery at 2,1; notice about this at 2,2.
+const int32 Animation::kCatacombMap[8][8] = {
+ // Geida's room
+ // 1 2 3 4 5 6 7 8
+ {0x204, 0x200, 0xd0f0, 0xf0ff, 0xff, 0xd20f, 0xd200, 0x200},
+ {0x50f1, 0x20ff, 0x2ff, 0xff, 0xe0ff, 0x20ff, 0x200f, 0x7210},
+ {0xe3f0, 0xe10f, 0x72f0, 0xff, 0xe0ff, 0xff, 0xff, 0x800f},
+ {0x2201, 0x2030, 0x800f, 0x220, 0x20f, 0x30, 0xff, 0x23f}, // >> Oubliette
+ {0x5024, 0xf3, 0xff, 0x200f, 0x22f0, 0x20f, 0x200, 0x7260},
+ {0xf0, 0x2ff, 0xe2ff, 0xff, 0x200f, 0x50f0, 0x72ff, 0x201f},
+ {0xf6, 0x220f, 0x22f0, 0x30f, 0xf0, 0x20f, 0x8200, 0x2f0}, // <<< In here
+ {0x34, 0x200f, 0x51f0, 0x201f, 0xf1, 0x50ff, 0x902f, 0x2062}
+};
+
+AnimationType::AnimationType(Animation *anim) {
+ _anim = anim;
+
+ _xLength = 0;
+ _yLength = 0;
+ for (int i = 0; i < 24; i++) {
+ _mani[i] = nullptr;
+ _sil[i] = nullptr;
+ }
+ _frameNum = 0;
+ _seq = 0;
+ _characterId = 0;
+ _count = 0;
+ _facingDir = kDirNone;
+ _stepNum = 0;
+ _x = 0;
+ _y = 0;
+ _moveX = 0;
+ _moveY = 0;
+ _quick = false;
+ _visible = false;
+ _homing = false;
+ _doCheck = false;
+ _homingX = 0;
+ _homingY = 0;
+ _speedX = 0;
+ _speedY = 0;
+ _vanishIfStill = false;
+ _callEachStepFl = false;
+ _eachStepProc = Animation::kProcNone;
+ _fgBubbleCol = kColorWhite;
+ _bgBubbleCol = kColorBlack;
+ _id = 177;
+}
+
+/**
+ * Loads & sets up the sprite.
+ */
+void AnimationType::init(byte spritenum, bool doCheck) {
+ const int32 idshould = -1317732048;
+
+ if (spritenum == 177)
+ return; // Already running!
+
+ Common::File inf;
+ Common::String filename = Common::String::format("sprite%d.avd", spritenum);
+ if (!inf.open(filename))
+ error("AVALANCHE: Trip: File not found: %s", filename.c_str());
+
+ inf.seek(177);
+
+ int32 id = inf.readSint32LE();
+ if (id != idshould) {
+ inf.close();
+ return;
+ }
+
+ // Replace variable named 'soa' in the original code.
+ inf.skip(2);
+ // Skip real name Size (1 byte) then fixed sized zone containing name (12 bytes)
+ inf.skip(1 + 12);
+ // Skip real comment size (1 byte) then fixed sized zone containing comment (16 bytes)
+ inf.skip(1 + 16);
+
+ _frameNum = inf.readByte();
+ _xLength = inf.readByte();
+ _yLength = inf.readByte();
+ _seq = inf.readByte();
+ uint16 size = inf.readUint16LE();
+ assert (size > 6);
+ _fgBubbleCol = (Color)inf.readByte();
+ _bgBubbleCol = (Color)inf.readByte();
+ _characterId = inf.readByte();
+
+ byte xWidth = _xLength / 8;
+ if ((_xLength % 8) > 0)
+ xWidth++;
+ for (int i = 0; i < _frameNum; i++) {
+ _sil[i] = new SilType[11 * (_yLength + 1)];
+ _mani[i] = new ManiType[size - 6];
+ for (int j = 0; j <= _yLength; j++)
+ inf.read((*_sil[i])[j], xWidth);
+ inf.read(*_mani[i], size - 6);
+ }
+
+ _x = 0;
+ _y = 0;
+ _quick = true;
+ _visible = false;
+ _speedX = kWalk;
+ _speedY = 1;
+ _homing = false;
+ _moveX = 0;
+ _moveY = 0;
+ _stepNum = 0;
+ _doCheck = doCheck;
+ _count = 0;
+ _id = spritenum;
+ _vanishIfStill = false;
+ _callEachStepFl = false;
+
+ inf.close();
+}
+
+/**
+ * Just sets 'quick' to false.
+ * @remarks Originally called 'original'
+ */
+void AnimationType::reset() {
+ _quick = false;
+ _id = 177;
+}
+
+/**
+ * Drops sprite onto screen.
+ * @remarks Originally called 'andexor'
+ */
+void AnimationType::draw() {
+ if (_vanishIfStill && (_moveX == 0) && (_moveY == 0))
+ return;
+
+ byte picnum = _facingDir * _seq + _stepNum;
+
+ _anim->_vm->_graphics->drawSprite(this, picnum, _x, _y);
+}
+
+/**
+ * Turns character round.
+ */
+void AnimationType::turn(Direction whichway) {
+ if (whichway == 8)
+ _facingDir = kDirUp;
+ else
+ _facingDir = whichway;
+}
+
+/**
+ * Switches it on.
+ */
+void AnimationType::appear(int16 wx, int16 wy, Direction wf) {
+ _x = (wx / 8) * 8;
+ _y = wy;
+ _oldX[_anim->_vm->_cp] = wx;
+ _oldY[_anim->_vm->_cp] = wy;
+ turn(wf);
+ _visible = true;
+ _moveX = 0;
+ _moveY = 0;
+}
+
+/**
+ * Check collision
+ * @remarks Originally called 'collision_check'
+ */
+bool AnimationType::checkCollision() {
+ for (int i = 0; i < _anim->kSpriteNumbMax; i++) {
+ AnimationType *spr = _anim->_sprites[i];
+ if (spr->_quick && (spr->_id != _id) && (_x + _xLength > spr->_x) && (_x < spr->_x + spr->_xLength) && (spr->_y == _y))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Prepares for draw(), etc.
+ */
+void AnimationType::walk() {
+ if (!_anim->_vm->_doingSpriteRun) {
+ _oldX[_anim->_vm->_cp] = _x;
+ _oldY[_anim->_vm->_cp] = _y;
+ if (_homing)
+ homeStep();
+ _x += _moveX;
+ _y += _moveY;
+ }
+
+ if (_doCheck) {
+ if (checkCollision()) {
+ bounce();
+ return;
+ }
+
+ byte magicColor = _anim->checkFeet(_x, _x + _xLength, _oldY[_anim->_vm->_cp], _y, _yLength) - 1;
+ // -1 is because the modified array indexes of magics[] compared to Pascal .
+
+ if ((magicColor != 255) & !_anim->_vm->_doingSpriteRun) {
+ MagicType *magic = &_anim->_vm->_magics[magicColor];
+ switch (magic->_operation) {
+ case kMagicExclaim:
+ bounce();
+ _anim->_mustExclaim = true;
+ _anim->_sayWhat = magic->_data;
+ break;
+ case kMagicBounce:
+ bounce();
+ break;
+ case kMagicTransport:
+ _anim->_vm->flipRoom((Room)(magic->_data >> 8), magic->_data & 0xff);
+ break;
+ case kMagicUnfinished: {
+ bounce();
+ Common::String tmpStr = Common::String::format("%c%cSorry.%cThis place is not available yet!",
+ kControlBell, kControlCenter, kControlRoman);
+ _anim->_vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case kMagicSpecial:
+ _anim->callSpecial(magic->_data);
+ break;
+ case kMagicOpenDoor:
+ _anim->_vm->openDoor((Room)(magic->_data >> 8), magic->_data & 0xff, magicColor);
+ break;
+ }
+ }
+ }
+
+ if (!_anim->_vm->_doingSpriteRun) {
+ _count++;
+ if (((_moveX != 0) || (_moveY != 0)) && (_count > 1)) {
+ _stepNum++;
+ if (_stepNum == _seq)
+ _stepNum = 0;
+ _count = 0;
+ }
+ }
+}
+
+/**
+ * Bounces off walls
+ */
+void AnimationType::bounce() {
+ _x = _oldX[_anim->_vm->_cp];
+ _y = _oldY[_anim->_vm->_cp];
+ if (_doCheck)
+ _anim->stopWalking();
+ else
+ stopWalk();
+ _anim->_vm->drawDirection();
+}
+
+int8 AnimationType::getSign(int16 val) {
+ if (val > 0)
+ return 1;
+ else if (val < 0)
+ return -1;
+ else
+ return 0;
+}
+
+/**
+ * Home in on a point.
+ */
+void AnimationType::walkTo(byte pedNum) {
+ PedType *curPed = &_anim->_vm->_peds[pedNum];
+
+ setSpeed(getSign(curPed->_x - _x) * 4, getSign(curPed->_y - _y));
+ _homingX = curPed->_x - _xLength / 2;
+ _homingY = curPed->_y - _yLength;
+ _homing = true;
+}
+
+void AnimationType::stopHoming() {
+ _homing = false;
+}
+
+/**
+ * Calculates ix & iy for one homing step.
+ */
+void AnimationType::homeStep() {
+ int16 temp;
+
+ if ((_homingX == _x) && (_homingY == _y)) {
+ // touching the target
+ stopWalk();
+ return;
+ }
+ _moveX = 0;
+ _moveY = 0;
+ if (_homingY != _y) {
+ temp = _homingY - _y;
+ if (temp > 4)
+ _moveY = 4;
+ else if (temp < -4)
+ _moveY = -4;
+ else
+ _moveY = temp;
+ }
+ if (_homingX != _x) {
+ temp = _homingX - _x;
+ if (temp > 4)
+ _moveX = 4;
+ else if (temp < -4)
+ _moveX = -4;
+ else
+ _moveX = temp;
+ }
+}
+
+/**
+ * Sets ix & iy, non-homing, etc.
+ */
+void AnimationType::setSpeed(int8 xx, int8 yy) {
+ _moveX = xx;
+ _moveY = yy;
+ if ((_moveX == 0) && (_moveY == 0))
+ return; // no movement
+ if (_moveX == 0) {
+ // No horz movement
+ if (_moveY < 0)
+ turn(kDirUp);
+ else
+ turn(kDirDown);
+ } else {
+ if (_moveX < 0)
+ turn(kDirLeft);
+ else
+ turn(kDirRight);
+ }
+}
+
+/**
+ * Stops the sprite from moving.
+ */
+void AnimationType::stopWalk() {
+ _moveX = 0;
+ _moveY = 0;
+ _homing = false;
+}
+
+/**
+ * Sets up talk vars.
+ */
+void AnimationType::chatter() {
+ _anim->_vm->_dialogs->setTalkPos(_x + _xLength / 2, _y);
+ _anim->_vm->_graphics->setDialogColor(_bgBubbleCol, _fgBubbleCol);
+}
+
+void AnimationType::remove() {
+ for (int i = 0; i < _frameNum; i++) {
+ delete[] _mani[i];
+ delete[] _sil[i];
+ }
+
+ _quick = false;
+ _id = 177;
+}
+
+Animation::Animation(AvalancheEngine *vm) {
+ _vm = vm;
+ _mustExclaim = false;
+
+ for (int16 i = 0; i < kSpriteNumbMax; i++) {
+ _sprites[i] = new AnimationType(this);
+ }
+
+ _direction = kDirNone;
+ _oldDirection = kDirNone;
+ _arrowTriggered = false;
+ _geidaSpin = 0;
+ _geidaTime = 0;
+ _sayWhat = 0;
+}
+
+Animation::~Animation() {
+ for (int16 i = 0; i < kSpriteNumbMax; i++) {
+ AnimationType *curSpr = _sprites[i];
+
+ if (curSpr->_quick)
+ curSpr->remove();
+ delete(curSpr);
+ }
+}
+
+/**
+ * Resets Animation variables.
+ * @remarks Originally called 'loadtrip'
+ */
+void Animation::resetAnims() {
+ setDirection(kDirStopped);
+ for (int16 i = 0; i < kSpriteNumbMax; i++)
+ _sprites[i]->reset();
+}
+
+byte Animation::checkFeet(int16 x1, int16 x2, int16 oy, int16 y, byte yl) {
+ if (!_vm->_alive)
+ return 0;
+
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 > 639)
+ x2 = 639;
+
+ int16 minY = MIN(oy, y) + yl;
+ int16 maxY = MAX(oy, y) + yl;
+
+ return _vm->_graphics->getAlsoColor(x1, minY, x2, maxY);
+}
+
+byte Animation::geidaPed(byte ped) {
+ switch (ped) {
+ case 1:
+ return 6;
+ case 2:
+ case 6:
+ return 7;
+ case 3:
+ case 5:
+ return 8;
+ case 4:
+ return 9;
+ default:
+ error("geidaPed(): Unhandled ped value %d", ped);
+ }
+}
+
+/**
+ * When you enter a new position in the catacombs, this procedure should be
+ * called. It changes the 'also' codes so that they may match the picture
+ * on the screen.
+ */
+void Animation::catacombMove(byte ped) {
+ // XY_uint16 is _catacombX+_catacombY*256. Thus, every room in the
+ // catacombs has a different number for it.
+ uint16 xy = _vm->_catacombX + _vm->_catacombY * 256;
+ _geidaSpin = 0;
+
+ switch (xy) {
+ case 1801: // Exit catacombs
+ _vm->flipRoom(kRoomLustiesRoom, 4);
+ _vm->_dialogs->displayText("Phew! Nice to be out of there!");
+ return;
+ case 1033:{ // Oubliette
+ _vm->flipRoom(kRoomOubliette, 1);
+ Common::String tmpStr = Common::String::format("Oh, NO!%c1%c", kControlRegister, kControlSpeechBubble);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ return;
+ case 4:
+ _vm->flipRoom(kRoomGeidas, 1);
+ return;
+ case 2307:
+ _vm->flipRoom(kRoomLusties, 5);
+ _vm->_dialogs->displayText("Oh no... here we go again...");
+ _vm->_userMovesAvvy = false;
+ _sprites[0]->_moveY = 1;
+ _sprites[0]->_moveX = 0;
+ return;
+ }
+
+ if (!_vm->_enterCatacombsFromLustiesRoom)
+ _vm->loadRoom(29);
+ int32 here = kCatacombMap[_vm->_catacombY - 1][_vm->_catacombX - 1];
+
+ switch (here & 0xf) { // West.
+ case 0: // no connection (wall)
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 27);
+ break;
+ case 0x1: // no connection (wall + shield),
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 28); // ...shield.
+ break;
+ case 0x2: // wall with door
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 29); // ...door.
+ break;
+ case 0x3: // wall with door and shield
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 29); // ...door, and...
+ _vm->_background->draw(-1, -1, 28); // ...shield.
+ break;
+ case 0x4: // no connection (wall + window),
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 4); // ...window.
+ break;
+ case 0x5: // wall with door and window
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 29); // ...door, and...
+ _vm->_background->draw(-1, -1, 4); // ...window.
+ break;
+ case 0x6: // no connection (wall + torches),
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicNothing; // No door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 6); // ...torches.
+ break;
+ case 0x7: // wall with door and torches
+ _vm->_magics[1]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[4]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 27); // Wall, plus...
+ _vm->_background->draw(-1, -1, 29); // ...door, and...
+ _vm->_background->draw(-1, -1, 6); // ...torches.
+ break;
+ case 0xf: // straight-through corridor.
+ _vm->_magics[1]._operation = kMagicNothing; // Sloping wall.
+ _vm->_magics[2]._operation = kMagicSpecial; // Straight wall.
+ break;
+ }
+
+ /* ---- */
+
+ switch ((here & 0xf0) >> 4) { // East
+ case 0: // no connection (wall)
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 18);
+ break;
+ case 0x1: // no connection (wall + window),
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 18); // Wall, plus...
+ _vm->_background->draw(-1, -1, 19); // ...window.
+ break;
+ case 0x2: // wall with door
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 18); // Wall, plus...
+ _vm->_background->draw(-1, -1, 20); // ...door.
+ break;
+ case 0x3: // wall with door and window
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 18); // Wall, plus...
+ _vm->_background->draw(-1, -1, 19); // ...door, and...
+ _vm->_background->draw(-1, -1, 20); // ...window.
+ break;
+ case 0x6: // no connection (wall + torches),
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicNothing; // No door.
+ _vm->_background->draw(-1, -1, 18); // Wall, plus...
+ _vm->_background->draw(-1, -1, 17); // ...torches.
+ break;
+ case 0x7: // wall with door and torches
+ _vm->_magics[4]._operation = kMagicBounce; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicNothing; // Straight wall.
+ _vm->_portals[6]._operation = kMagicSpecial; // Door.
+ _vm->_background->draw(-1, -1, 18); // Wall, plus...
+ _vm->_background->draw(-1, -1, 20); // ...door, and...
+ _vm->_background->draw(-1, -1, 17); // ...torches.
+ break;
+ case 0xf: // straight-through corridor.
+ _vm->_magics[4]._operation = kMagicNothing; // Sloping wall.
+ _vm->_magics[5]._operation = kMagicSpecial; // Straight wall.
+ _vm->_portals[6]._operation = kMagicNothing; // Door.
+ break;
+ }
+
+ switch ((here & 0xf00) >> 8) { // South
+ case 0: // No connection.
+ _vm->_magics[6]._operation = kMagicBounce;
+ _vm->_magics[11]._operation = kMagicBounce;
+ _vm->_magics[12]._operation = kMagicBounce;
+ break;
+ case 0x1:
+ _vm->_background->draw(-1, -1, 21);
+
+ if ((xy == 2051) && _vm->_geidaFollows)
+ _vm->_magics[12]._operation = kMagicExclaim;
+ else
+ _vm->_magics[12]._operation = kMagicSpecial; // Right exit south.
+
+ _vm->_magics[6]._operation = kMagicBounce;
+ _vm->_magics[11]._operation = kMagicBounce;
+ break;
+ case 0x2:
+ _vm->_background->draw(-1, -1, 22);
+ _vm->_magics[6]._operation = kMagicSpecial; // Middle exit south.
+ _vm->_magics[11]._operation = kMagicBounce;
+ _vm->_magics[12]._operation = kMagicBounce;
+ break;
+ case 0x3:
+ _vm->_background->draw(-1, -1, 23);
+ _vm->_magics[11]._operation = kMagicSpecial; // Left exit south.
+ _vm->_magics[6]._operation = kMagicBounce;
+ _vm->_magics[12]._operation = kMagicBounce;
+ break;
+ }
+
+ switch ((here & 0xf000) >> 12) { // North
+ case 0: // No connection
+ _vm->_magics[0]._operation = kMagicBounce;
+ _vm->_portals[3]._operation = kMagicNothing; // Door.
+ break;
+ // LEFT handles:
+#if 0
+ case 0x1:
+ _vm->_celer->show_one(-1, -1, 4);
+ _vm->magics[1].op = _vm->bounces; // { Left exit north. } { Change magic number! }
+ _vm->portals[12].op = _vm->special; // { Door. }
+ break;
+#endif
+ case 0x2:
+ _vm->_background->draw(-1, -1, 3);
+ _vm->_magics[0]._operation = kMagicBounce; // Middle exit north.
+ _vm->_portals[3]._operation = kMagicSpecial; // Door.
+ break;
+#if 0
+ case 0x3:
+ _vm->_celer->show_one(-1, -1, 4);
+ _vm->magics[1].op = _vm->bounces; // { Right exit north. } { Change magic number! }
+ _vm->portals[12].op = _vm->special; // { Door. }
+ break;
+ // RIGHT handles:
+ case 0x4:
+ _vm->_celer->show_one(-1, -1, 3);
+ _vm->magics[1].op = _vm->bounces; // { Left exit north. } { Change magic number! }
+ _vm->portals[12].op = _vm->special; // { Door. }
+ break;
+#endif
+ case 0x5:
+ _vm->_background->draw(-1, -1, 2);
+ _vm->_magics[0]._operation = kMagicBounce; // Middle exit north.
+ _vm->_portals[3]._operation = kMagicSpecial; // Door.
+ break;
+#if 0
+ case 0x6:
+ _vm->_celer->show_one(-1, -1, 3);
+ _vm->magics[1].op = _vm->bounces; // { Right exit north. }
+ _vm->portals[12].op = _vm->special; // { Door. }
+ break;
+#endif
+ // ARCHWAYS:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ _vm->_background->draw(-1, -1, 5);
+
+ if (((here & 0xf000) >> 12) > 0x7)
+ _vm->_background->draw(-1, -1, 30);
+ if (((here & 0xf000) >> 12) == 0x9)
+ _vm->_background->draw(-1, -1, 31);
+
+ _vm->_magics[0]._operation = kMagicSpecial; // Middle arch north.
+ _vm->_portals[3]._operation = kMagicNothing; // Door.
+ break;
+ // DECORATIONS:
+ case 0xd: // No connection + WINDOW
+ _vm->_magics[0]._operation = kMagicBounce;
+ _vm->_portals[3]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 13);
+ break;
+ case 0xe: // No connection + TORCH
+ _vm->_magics[0]._operation = kMagicBounce;
+ _vm->_portals[3]._operation = kMagicNothing; // Door.
+ _vm->_background->draw(-1, -1, 7);
+ break;
+ // Recessed door:
+ case 0xf:
+ _vm->_magics[0]._operation = kMagicNothing; // Door to Geida's room.
+ _vm->_background->draw(-1, -1, 0);
+ _vm->_portals[3]._operation = kMagicSpecial; // Door.
+ break;
+ }
+
+ switch (xy) {
+ case 514:
+ _vm->_background->draw(-1, -1, 16);
+ break; // [2,2] : "Art Gallery" sign over door.
+ case 264:
+ _vm->_background->draw(-1, -1, 8);
+ break; // [8,1] : "The Wrong Way!" sign.
+ case 1797:
+ _vm->_background->draw(-1, -1, 1);
+ break; // [5,7] : "Ite Mingite" sign.
+ case 258:
+ for (int i = 0; i <= 2; i++) { // [2,1] : Art gallery - pictures
+ _vm->_background->draw(130 + i * 120, 70, 14);
+ _vm->_background->draw(184 + i * 120, 78, 15);
+ }
+ break;
+ case 1287:
+ for (int i = 10; i <= 13; i++)
+ _vm->_background->draw(-1, -1, i - 1);
+ break; // [7,5] : 4 candles.
+ case 776:
+ _vm->_background->draw(-1, -1, 9);
+ break; // [8,3] : 1 candle.
+ case 2049:
+ _vm->_background->draw(-1, -1, 10);
+ break; // [1,8] : another candle.
+ case 257:
+ _vm->_background->draw(-1, -1, 11);
+ _vm->_background->draw(-1, -1, 12);
+ break; // [1,1] : the other two.
+ }
+
+ if (_vm->_geidaFollows && (ped > 0)) {
+ AnimationType *spr1 = _sprites[1];
+
+ if (!spr1->_quick) // If we don't already have her...
+ spr1->init(5, true); // ...Load Geida.
+ appearPed(1, geidaPed(ped));
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = kProcGeida;
+ }
+}
+
+/**
+ * This proc gets called whenever you touch a line defined as _vm->special.
+ */
+void Animation::dawnDelay() {
+ _vm->_timer->addTimer(2, Timer::kProcDawnDelay, Timer::kReasonDawndelay);
+}
+
+void Animation::callSpecial(uint16 which) {
+ switch (which) {
+ case 1: // _vm->special 1: Room 22: top of stairs.
+ _vm->_background->draw(-1, -1, 0);
+ _vm->_brummieStairs = 1;
+ _vm->_magics[9]._operation = kMagicNothing;
+ _vm->_timer->addTimer(10, Timer::kProcStairs, Timer::kReasonBrummieStairs);
+ stopWalking();
+ _vm->_userMovesAvvy = false;
+ break;
+ case 2: // _vm->special 2: Room 22: bottom of stairs.
+ _vm->_brummieStairs = 3;
+ _vm->_magics[10]._operation = kMagicNothing;
+ _vm->_magics[11]._operation = kMagicExclaim;
+ _vm->_magics[11]._data = 5;
+ _vm->_magics[3]._operation = kMagicBounce; // Now works as planned!
+ stopWalking();
+ _vm->_dialogs->displayScrollChain('Q', 26);
+ _vm->_userMovesAvvy = true;
+ break;
+ case 3: // _vm->special 3: Room 71: triggers dart.
+ _sprites[0]->bounce(); // Must include that.
+
+ if (!_arrowTriggered) {
+ _arrowTriggered = true;
+
+ AnimationType *spr1 = _sprites[1];
+ appearPed(1, 3); // The dart starts at ped 4, and...
+ spr1->walkTo(4); // flies to ped 5 (- 1 for pascal to C conversion).
+ spr1->_facingDir = kDirUp; // Only face.
+ // Should call some kind of Eachstep procedure which will deallocate
+ // the sprite when it hits the wall, and replace it with the chunk
+ // graphic of the arrow buried in the plaster. */
+
+ // OK!
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = kProcArrow;
+ }
+ break;
+ case 4: // This is the ghost room link.
+ _vm->fadeOut();
+ _sprites[0]->turn(kDirRight); // you'll see this after we get back from bootstrap
+ _vm->_timer->addTimer(1, Timer::kProcGhostRoomPhew, Timer::kReasonGhostRoomPhew);
+ //_vm->_enid->backToBootstrap(3); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then!
+ break;
+ case 5:
+ if (_vm->_friarWillTieYouUp) {
+ // _vm->special 5: Room 42: touched tree, and get tied up.
+ _vm->_magics[4]._operation = kMagicBounce; // Boundary effect is now working again.
+ _vm->_dialogs->displayScrollChain('Q', 35);
+ _sprites[0]->remove();
+
+ AnimationType *spr1 = _sprites[1];
+ _vm->_background->draw(-1, -1, 1);
+ _vm->_dialogs->displayScrollChain('Q', 36);
+ _vm->_tiedUp = true;
+ _vm->_friarWillTieYouUp = false;
+ spr1->walkTo(2);
+ spr1->_vanishIfStill = true;
+ spr1->_doCheck = true; // One of them must have Check_Me switched on.
+ _vm->setRoom(kPeopleFriarTuck, kRoomDummy); // Not here, then.
+ _vm->_timer->addTimer(364, Timer::kProcHangAround, Timer::kReasonHangingAround);
+ }
+ break;
+ case 6: {
+ // _vm->special 6: fall down oubliette.
+ AnimationType *avvy = _sprites[0];
+ _vm->_userMovesAvvy = false;
+ avvy->_moveX = 3;
+ avvy->_moveY = 0;
+ avvy->_facingDir = kDirRight;
+ _vm->_timer->addTimer(1, Timer::kProcFallDownOubliette, Timer::kReasonFallingDownOubliette);
+ }
+ break;
+ case 7: // _vm->special 7: stop falling down oubliette.
+ _sprites[0]->_visible = false;
+ _vm->_magics[9]._operation = kMagicNothing;
+ stopWalking();
+ _vm->_timer->loseTimer(Timer::kReasonFallingDownOubliette);
+ //_vm->mblit(12, 80, 38, 160, 3, 0);
+ //_vm->mblit(12, 80, 38, 160, 3, 1);
+ _vm->_dialogs->displayText("Oh dear, you seem to be down the bottom of an oubliette.");
+ _vm->_timer->addTimer(200, Timer::kProcMeetAvaroid, Timer::kReasonMeetingAvaroid);
+ break;
+ case 8: // _vm->special 8: leave du Lustie's room.
+ if (_vm->_geidaFollows && !_vm->_lustieIsAsleep) {
+ AnimationType *spr1 = _sprites[1];
+ _vm->_dialogs->displayScrollChain('Q', 63);
+ spr1->turn(kDirDown);
+ spr1->stopWalk();
+ spr1->_callEachStepFl = false; // Geida
+ _vm->gameOver();
+ }
+ break;
+ case 9: {
+ // _vm->special 9: lose Geida to Robin Hood...
+ if (!_vm->_geidaFollows)
+ return; // DOESN'T COUNT: no Geida.
+ AnimationType *spr1 = _sprites[1];
+ spr1->_callEachStepFl = false; // She no longer follows Avvy around.
+ spr1->walkTo(3); // She walks to somewhere...
+ _sprites[0]->remove(); // Lose Avvy.
+ _vm->_userMovesAvvy = false;
+ _vm->_timer->addTimer(40, Timer::kProcRobinHoodAndGeida, Timer::kReasonRobinHoodAndGeida);
+ }
+ break;
+ case 10: // _vm->special 10: transfer north in catacombs.
+ if ((_vm->_catacombX == 4) && (_vm->_catacombY == 1)) {
+ // Into Geida's room.
+ if (_vm->_objects[kObjectKey - 1])
+ _vm->_dialogs->displayScrollChain('Q', 62);
+ else {
+ _vm->_dialogs->displayScrollChain('Q', 61);
+ return;
+ }
+ }
+ _vm->fadeOut();
+ _vm->_catacombY--;
+ catacombMove(4);
+ if (_vm->_room != kRoomCatacombs)
+ return;
+ switch ((kCatacombMap[_vm->_catacombY - 1][_vm->_catacombX - 1] & 0xf00) >> 8) {
+ case 0x1:
+ appearPed(0, 11);
+ break;
+ case 0x3:
+ appearPed(0, 10);
+ break;
+ default:
+ appearPed(0, 3);
+ }
+ dawnDelay();
+ break;
+ case 11: // _vm->special 11: transfer east in catacombs.
+ _vm->fadeOut();
+ _vm->_catacombX++;
+ catacombMove(1);
+ if (_vm->_room != kRoomCatacombs)
+ return;
+ appearPed(0, 0);
+ dawnDelay();
+ break;
+ case 12: // _vm->special 12: transfer south in catacombs.
+ _vm->fadeOut();
+ _vm->_catacombY++;
+ catacombMove(2);
+ if (_vm->_room != kRoomCatacombs)
+ return;
+ appearPed(0, 1);
+ dawnDelay();
+ break;
+ case 13: // _vm->special 13: transfer west in catacombs.
+ _vm->fadeOut();
+ _vm->_catacombX--;
+ catacombMove(3);
+ if (_vm->_room != kRoomCatacombs)
+ return;
+ appearPed(0, 2);
+ dawnDelay();
+ break;
+ }
+}
+
+void Animation::updateSpeed() {
+ AnimationType *avvy = _sprites[0];
+ // Given that you've just changed the speed in _speedX, this adjusts _moveX.
+ avvy->_moveX = (avvy->_moveX / 3) * avvy->_speedX;
+ _vm->_graphics->drawSpeedBar(avvy->_speedX);
+}
+
+void Animation::setMoveSpeed(byte t, Direction dir) {
+ AnimationType *spr = _sprites[t];
+ switch (dir) {
+ case kDirUp:
+ spr->setSpeed(0, -spr->_speedY);
+ break;
+ case kDirDown:
+ spr->setSpeed(0, spr->_speedY);
+ break;
+ case kDirLeft:
+ spr->setSpeed(-spr->_speedX, 0);
+ break;
+ case kDirRight:
+ spr->setSpeed(spr->_speedX, 0);
+ break;
+ case kDirUpLeft:
+ spr->setSpeed(-spr->_speedX, -spr->_speedY);
+ break;
+ case kDirUpRight:
+ spr->setSpeed(spr->_speedX, -spr->_speedY);
+ break;
+ case kDirDownLeft:
+ spr->setSpeed(-spr->_speedX, spr->_speedY);
+ break;
+ case kDirDownRight:
+ spr->setSpeed(spr->_speedX, spr->_speedY);
+ break;
+ default:
+ break;
+ }
+}
+
+void Animation::appearPed(byte sprNum, byte pedNum) {
+ AnimationType *curSpr = _sprites[sprNum];
+ PedType *curPed = &_vm->_peds[pedNum];
+ curSpr->appear(curPed->_x - curSpr->_xLength / 2, curPed->_y - curSpr->_yLength, curPed->_direction);
+ setMoveSpeed(sprNum, curPed->_direction);
+}
+
+/**
+ * @remarks Originally called 'follow_avvy_y'
+ */
+void Animation::followAvalotY(byte tripnum) {
+ if (_sprites[0]->_facingDir == kDirLeft)
+ return;
+
+ AnimationType *tripSpr = _sprites[tripnum];
+ AnimationType *spr1 = _sprites[1];
+
+ if (tripSpr->_homing)
+ tripSpr->_homingY = spr1->_y;
+ else {
+ if (tripSpr->_y < spr1->_y)
+ tripSpr->_y++;
+ else if (tripSpr->_y > spr1->_y)
+ tripSpr->_y--;
+ else
+ return;
+
+ if (tripSpr->_moveX == 0) {
+ tripSpr->_stepNum++;
+ if (tripSpr->_stepNum == tripSpr->_seq)
+ tripSpr->_stepNum = 0;
+ tripSpr->_count = 0;
+ }
+ }
+}
+
+void Animation::backAndForth(byte tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+
+ if (!tripSpr->_homing) {
+ if (tripSpr->_facingDir == kDirRight)
+ tripSpr->walkTo(3);
+ else
+ tripSpr->walkTo(4);
+ }
+}
+
+void Animation::faceAvvy(byte tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+
+ if (!tripSpr->_homing) {
+ if (_sprites[0]->_x >= tripSpr->_x)
+ tripSpr->_facingDir = kDirRight;
+ else
+ tripSpr->_facingDir = kDirLeft;
+ }
+}
+
+void Animation::arrowProcs(byte tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+ AnimationType *avvy = _sprites[tripnum];
+
+ if (tripSpr->_homing) {
+ // Arrow is still in flight.
+ // We must check whether or not the arrow has collided tr[tripnum] Avvy's head.
+ // This is so if: a) the bottom of the arrow is below Avvy's head,
+ // b) the left of the arrow is left of the right of Avvy's head, and
+ // c) the right of the arrow is right of the left of Avvy's head.
+ if ((tripSpr->_y + tripSpr->_yLength >= avvy->_y) // A
+ && (tripSpr->_x <= avvy->_x + avvy->_xLength) // B
+ && (tripSpr->_x + tripSpr->_xLength >= avvy->_x)) { // C
+ // OK, it's hit him... what now?
+
+ _sprites[1]->_callEachStepFl = false; // prevent recursion.
+ _vm->_dialogs->displayScrollChain('Q', 47); // Complaint!
+ tripSpr->remove(); // Deallocate the arrow.
+
+ _vm->gameOver();
+
+ _vm->_userMovesAvvy = false; // Stop the user from moving him.
+ _vm->_timer->addTimer(55, Timer::kProcNaughtyDuke, Timer::kReasonNaughtyDuke);
+ }
+ } else { // Arrow has hit the wall!
+ tripSpr->remove(); // Deallocate the arrow.
+ _vm->_background->draw(-1, -1, 2); // Show pic of arrow stuck into the door.
+ _vm->_arrowInTheDoor = true; // So that we can pick it up.
+ }
+}
+
+void Animation::grabAvvy(byte tripnum) { // For Friar Tuck, in Nottingham.
+ AnimationType *tripSpr = _sprites[tripnum];
+ AnimationType *avvy = _sprites[0];
+
+ int16 tox = avvy->_x + 17;
+ int16 toy = avvy->_y - 1;
+ if ((tripSpr->_x == tox) && (tripSpr->_y == toy)) {
+ tripSpr->_callEachStepFl = false;
+ tripSpr->_facingDir = kDirLeft;
+ tripSpr->stopWalk();
+ // ... whatever ...
+ } else {
+ // Still some way to go.
+ if (tripSpr->_x < tox) {
+ tripSpr->_x += 5;
+ if (tripSpr->_x > tox)
+ tripSpr->_x = tox;
+ }
+ if (tripSpr->_y < toy)
+ tripSpr->_y++;
+ tripSpr->_stepNum++;
+ if (tripSpr->_stepNum == tripSpr->_seq)
+ tripSpr->_stepNum = 0;
+ }
+}
+
+void Animation::takeAStep(byte &tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+
+ if (tripSpr->_moveX == 0) {
+ tripSpr->_stepNum++;
+ if (tripSpr->_stepNum == tripSpr->_seq)
+ tripSpr->_stepNum = 0;
+ tripSpr->_count = 0;
+ }
+}
+
+void Animation::spin(Direction dir, byte &tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+
+ if (tripSpr->_facingDir == dir)
+ return;
+
+ tripSpr->_facingDir = dir;
+ if (tripSpr->_id == 2)
+ return; // Not for Spludwick
+
+ _geidaSpin++;
+ _geidaTime = 20;
+ if (_geidaSpin == 5) {
+ _vm->_dialogs->displayText("Steady on, Avvy, you'll make the poor girl dizzy!");
+ _geidaSpin = 0;
+ _geidaTime = 0; // knock out records
+ }
+}
+
+void Animation::geidaProcs(byte tripnum) {
+ AnimationType *tripSpr = _sprites[tripnum];
+ AnimationType *avvy = _sprites[0];
+
+ if (_geidaTime > 0) {
+ _geidaTime--;
+ if (_geidaTime == 0)
+ _geidaSpin = 0;
+ }
+
+ if (tripSpr->_y < (avvy->_y - 2)) {
+ // Geida is further from the screen than Avvy.
+ spin(kDirDown, tripnum);
+ tripSpr->_moveY = 1;
+ tripSpr->_moveX = 0;
+ takeAStep(tripnum);
+ return;
+ } else if (tripSpr->_y > (avvy->_y + 2)) {
+ // Avvy is further from the screen than Geida.
+ spin(kDirUp, tripnum);
+ tripSpr->_moveY = -1;
+ tripSpr->_moveX = 0;
+ takeAStep(tripnum);
+ return;
+ }
+
+ tripSpr->_moveY = 0;
+ // These 12-s are not in the original, I added them to make the following method more "smooth".
+ // Now the NPC which is following Avvy won't block his way and will walk next to him properly.
+ if (tripSpr->_x < avvy->_x - avvy->_speedX * 8 - 12) {
+ tripSpr->_moveX = avvy->_speedX;
+ spin(kDirRight, tripnum);
+ takeAStep(tripnum);
+ } else if (tripSpr->_x > avvy->_x + avvy->_speedX * 8 + 12) {
+ tripSpr->_moveX = -avvy->_speedX;
+ spin(kDirLeft, tripnum);
+ takeAStep(tripnum);
+ } else
+ tripSpr->_moveX = 0;
+}
+
+/**
+ * @remarks Originally called 'call_andexors'
+ */
+void Animation::drawSprites() {
+ int8 order[5];
+ byte temp;
+ bool ok;
+
+ for (int i = 0; i < 5; i++)
+ order[i] = -1;
+
+ for (int16 i = 0; i < kSpriteNumbMax; i++) {
+ AnimationType *curSpr = _sprites[i];
+ if (curSpr->_quick && curSpr->_visible)
+ order[i] = i;
+ }
+
+ do {
+ ok = true;
+ for (int i = 0; i < 4; i++) {
+ if ((order[i] != -1) && (order[i + 1] != -1) && (_sprites[order[i]]->_y > _sprites[order[i + 1]]->_y)) {
+ // Swap them!
+ temp = order[i];
+ order[i] = order[i + 1];
+ order[i + 1] = temp;
+ ok = false;
+ }
+ }
+ } while (!ok);
+
+ _vm->_graphics->refreshBackground();
+
+ for (int i = 0; i < 5; i++) {
+ if (order[i] > -1)
+ _sprites[order[i]]->draw();
+ }
+}
+
+/**
+ * Animation links
+ * @remarks Originally called 'trippancy_link'
+ */
+void Animation::animLink() {
+ if (_vm->_menu->isActive() || _vm->_seeScroll)
+ return;
+ for (int16 i = 0; i < kSpriteNumbMax; i++) {
+ AnimationType *curSpr = _sprites[i];
+ if (curSpr->_quick && curSpr->_visible)
+ curSpr->walk();
+ }
+
+ drawSprites();
+
+ for (int16 i = 0; i < kSpriteNumbMax; i++) {
+ AnimationType *curSpr = _sprites[i];
+ if (curSpr->_quick && curSpr->_callEachStepFl) {
+ switch (curSpr->_eachStepProc) {
+ case kProcFollowAvvyY :
+ followAvalotY(i);
+ break;
+ case kProcBackAndForth :
+ backAndForth(i);
+ break;
+ case kProcFaceAvvy :
+ faceAvvy(i);
+ break;
+ case kProcArrow :
+ arrowProcs(i);
+ break;
+ // PROCSpludwick_procs : spludwick_procs(fv);
+ case kProcGrabAvvy :
+ grabAvvy(i);
+ break;
+ case kProcGeida :
+ geidaProcs(i);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_mustExclaim) {
+ _mustExclaim = false;
+ _vm->_dialogs->displayScrollChain('X', _sayWhat);
+ }
+}
+
+void Animation::stopWalking() {
+ AnimationType *avvy = _sprites[0];
+
+ avvy->stopWalk();
+ _direction = kDirStopped;
+ if (_vm->_alive)
+ avvy->_stepNum = 1;
+}
+
+/**
+ * Hide in the cupboard
+ * @remarks Originally called 'hide_in_the_cupboard'
+ */
+void Animation::hideInCupboard() {
+ if (_vm->_avvysInTheCupboard) {
+ if (_vm->_parser->_wearing == kObjectDummy) {
+ Common::String tmpStr = Common::String::format("%cAVVY!%cGet dressed first!", kControlItalic, kControlRoman);
+ _vm->_dialogs->displayText(tmpStr);
+ } else {
+ _sprites[0]->_visible = true;
+ _vm->_userMovesAvvy = true;
+ appearPed(0, 2); // Walk out of the cupboard.
+ _vm->_dialogs->displayText("You leave the cupboard. Nice to be out of there!");
+ _vm->_avvysInTheCupboard = false;
+ _vm->_sequence->startCupboardSeq();
+ }
+ } else {
+ // Not hiding in the cupboard
+ _sprites[0]->_visible = false;
+ _vm->_userMovesAvvy = false;
+ Common::String tmpStr = Common::String::format("You walk into the room...%cIt seems to be an empty, " \
+ "but dusty, cupboard. Hmmmm... you leave the door slightly open to avoid suffocation.", kControlParagraph);
+ _vm->_dialogs->displayText(tmpStr);
+ _vm->_avvysInTheCupboard = true;
+ _vm->_background->draw(-1, -1, 7);
+ }
+}
+
+/**
+ * Returns true if you're within field "which".
+ */
+bool Animation::inField(byte which) {
+ AnimationType *avvy = _sprites[0];
+
+ FieldType *curField = &_vm->_fields[which];
+ int16 yy = avvy->_y + avvy->_yLength;
+
+ return (avvy->_x >= curField->_x1) && (avvy->_x <= curField->_x2) && (yy >= curField->_y1) && (yy <= curField->_y2);
+}
+
+/**
+ * Returns True if you're near a door.
+ */
+bool Animation::nearDoor() {
+ if (_vm->_fieldNum < 8)
+ // there ARE no doors here!
+ return false;
+
+ AnimationType *avvy = _sprites[0];
+
+ int16 ux = avvy->_x;
+ int16 uy = avvy->_y + avvy->_yLength;
+
+ for (int i = 8; i < _vm->_fieldNum; i++) {
+ FieldType *curField = &_vm->_fields[i];
+ if ((ux >= curField->_x1) && (ux <= curField->_x2) && (uy >= curField->_y1) && (uy <= curField->_y2))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * @remarks Originally called 'tripkey'
+ */
+void Animation::handleMoveKey(const Common::Event &event) {
+ if (!_vm->_userMovesAvvy)
+ return;
+
+ if (_vm->_menu->_activeMenuItem._activeNow)
+ _vm->_parser->tryDropdown();
+ else {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_UP:
+ if (_direction != kDirUp) {
+ _direction = kDirUp;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_DOWN:
+ if (_direction != kDirDown) {
+ _direction = kDirDown;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_LEFT:
+ if (_direction != kDirLeft) {
+ _direction = kDirLeft;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_RIGHT:
+ if (_direction != kDirRight) {
+ _direction = kDirRight;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_PAGEUP:
+ if (_direction != kDirUpRight) {
+ _direction = kDirUpRight;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_PAGEDOWN:
+ if (_direction != kDirDownRight) {
+ _direction = kDirDownRight;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_END:
+ if (_direction != kDirDownLeft) {
+ _direction = kDirDownLeft;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_HOME:
+ if (_direction != kDirUpLeft) {
+ _direction = kDirUpLeft;
+ setMoveSpeed(0, _direction);
+ } else
+ stopWalking();
+ break;
+ case Common::KEYCODE_KP5:
+ stopWalking();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void Animation::setDirection(Direction dir) {
+ _direction = dir;
+}
+
+void Animation::setOldDirection(Direction dir) {
+ _oldDirection = dir;
+}
+
+Direction Animation::getDirection() {
+ return _direction;
+}
+
+Direction Animation::getOldDirection() {
+ return _oldDirection;
+}
+
+void Animation::setAvvyClothes(int id) {
+ AnimationType *spr = _sprites[0];
+ if (spr->_id == id)
+ return;
+
+ int16 x = spr->_x;
+ int16 y = spr->_y;
+ spr->remove();
+ spr->init(id, true);
+ spr->appear(x, y, kDirLeft);
+ spr->_visible = false;
+}
+
+int Animation::getAvvyClothes() {
+ return _sprites[0]->_id;
+}
+
+void Animation::resetVariables() {
+ _geidaSpin = 0;
+ _geidaTime = 0;
+ _arrowTriggered = false;
+}
+
+void Animation::synchronize(Common::Serializer &sz) {
+ sz.syncAsByte(_direction);
+ sz.syncAsByte(_geidaSpin);
+ sz.syncAsByte(_geidaTime);
+
+ byte spriteNum = 0;
+ if (sz.isSaving()) {
+ for (int i = 0; i < kSpriteNumbMax; i++) {
+ if (_sprites[i]->_quick)
+ spriteNum++;
+ }
+ }
+ sz.syncAsByte(spriteNum);
+
+ if (sz.isLoading()) {
+ for (int i = 0; i < kSpriteNumbMax; i++) { // Deallocate sprites.
+ AnimationType *spr = _sprites[i];
+ if (spr->_quick)
+ spr->remove();
+ }
+ }
+
+ for (int i = 0; i < spriteNum; i++) {
+ AnimationType *spr = _sprites[i];
+ sz.syncAsByte(spr->_id);
+ sz.syncAsByte(spr->_doCheck);
+
+ if (sz.isLoading()) {
+ spr->_quick = true;
+ spr->init(spr->_id, spr->_doCheck);
+ }
+
+ sz.syncAsByte(spr->_moveX);
+ sz.syncAsByte(spr->_moveY);
+ sz.syncAsByte(spr->_facingDir);
+ sz.syncAsByte(spr->_stepNum);
+ sz.syncAsByte(spr->_visible);
+ sz.syncAsByte(spr->_homing);
+ sz.syncAsByte(spr->_count);
+ sz.syncAsByte(spr->_speedX);
+ sz.syncAsByte(spr->_speedY);
+ sz.syncAsByte(spr->_frameNum);
+ sz.syncAsSint16LE(spr->_homingX);
+ sz.syncAsSint16LE(spr->_homingY);
+ sz.syncAsByte(spr->_callEachStepFl);
+ sz.syncAsByte(spr->_eachStepProc);
+ sz.syncAsByte(spr->_vanishIfStill);
+ sz.syncAsSint16LE(spr->_x);
+ sz.syncAsSint16LE(spr->_y);
+
+ if (sz.isLoading() && spr->_visible)
+ spr->appear(spr->_x, spr->_y, spr->_facingDir);
+ }
+
+ sz.syncAsByte(_arrowTriggered);
+}
+
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/animation.h b/engines/avalanche/animation.h
new file mode 100644
index 0000000000..cda5f05bd0
--- /dev/null
+++ b/engines/avalanche/animation.h
@@ -0,0 +1,171 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: TRIP5 / Trippancy V - the sprite animation subsystem */
+
+#ifndef AVALANCHE_ANIMATION_H
+#define AVALANCHE_ANIMATION_H
+
+namespace Avalanche {
+class AvalancheEngine;
+class Animation;
+
+enum Direction {
+ kDirUp = 0, kDirRight, kDirDown, kDirLeft,
+ kDirUpRight, kDirDownRight, kDirDownLeft, kDirUpLeft,
+ kDirStopped, kDirNone = 177
+};
+
+class AnimationType {
+public:
+ byte _id;
+
+ byte _xLength, _yLength;
+ ManiType *_mani[24];
+ SilType *_sil[24];
+ byte _frameNum; // Number of pictures.
+ byte _seq; // How many in one stride.
+ byte _characterId; // The number according to Acci. (1=Avvy, etc.)
+ byte _count; // Counts before changing step.
+
+ Direction _facingDir;
+ byte _stepNum;
+ int16 _x, _y; // Current xy coords.
+ int8 _moveX, _moveY; // Amount to move sprite by, each step.
+ bool _quick, _visible, _homing, _doCheck;
+ int16 _homingX, _homingY; // Homing x & y coords.
+ byte _speedX, _speedY;
+ bool _vanishIfStill;
+ bool _callEachStepFl;
+ byte _eachStepProc;
+
+ AnimationType(Animation *anim);
+
+ void init(byte spritenum, bool doCheck);
+ void reset();
+ void draw();
+ void turn(Direction whichway);
+ void appear(int16 wx, int16 wy, Direction wf);
+ void bounce();
+ void walk();
+ void walkTo(byte pednum);
+ void stopHoming();
+ void setSpeed(int8 xx, int8 yy);
+ void stopWalk();
+ void chatter();
+ void remove();
+
+private:
+ Animation *_anim;
+
+ int16 _oldX[2], _oldY[2]; // Last xy coords.
+ Color _fgBubbleCol, _bgBubbleCol; // Foreground & background bubble colors.
+
+ bool checkCollision();
+ int8 getSign(int16 val);
+ void homeStep();
+};
+
+class Animation {
+public:
+ friend class AnimationType;
+
+ static const byte kSpriteNumbMax = 5; // current max no. of sprites
+
+ enum Proc {
+ kProcNone = 0,
+ kProcFollowAvvyY,
+ kProcBackAndForth,
+ kProcFaceAvvy,
+ kProcArrow,
+ kProcSpludwick, // Unused
+ kProcGrabAvvy,
+ kProcGeida // Spludwick uses it as well for homing! TODO: Unify it with kProcSpludwick.
+ };
+
+ AnimationType *_sprites[kSpriteNumbMax];
+
+ Animation(AvalancheEngine *vm);
+ ~Animation();
+
+ void animLink();
+ void resetAnims();
+ void callSpecial(uint16 which);
+ void catacombMove(byte ped);
+ void stopWalking();
+ void setMoveSpeed(byte t, Direction dir);
+ void appearPed(byte sprNum, byte pedNum);
+ bool inField(byte which);
+ bool nearDoor();
+ void updateSpeed();
+ void handleMoveKey(const Common::Event &event);
+ void hideInCupboard();
+
+ void setDirection(Direction dir);
+ void setOldDirection(Direction dir);
+ Direction getDirection();
+ Direction getOldDirection();
+
+ void setAvvyClothes(int id);
+ int getAvvyClothes();
+
+ void resetVariables();
+ void synchronize(Common::Serializer &sz);
+private:
+ Direction _direction; // The direction Avvy is currently facing.
+ Direction _oldDirection;
+ static const int32 kCatacombMap[8][8];
+ bool _arrowTriggered; // And has the arrow been triggered?
+ bool _mustExclaim;
+ byte _geidaSpin, _geidaTime; // For the making "Geida dizzy" joke.
+ uint16 _sayWhat;
+
+ AvalancheEngine *_vm;
+
+ byte checkFeet(int16 x1, int16 x2, int16 oy, int16 y, byte yl);
+ byte geidaPed(byte ped);
+ void dawnDelay();
+
+ void grabAvvy(byte tripnum);
+ void arrowProcs(byte tripnum);
+
+ // Different movements for NPCs:
+ void followAvalotY(byte tripnum);
+ void backAndForth(byte tripnum);
+ void faceAvvy(byte tripnum);
+
+ // Movements for Homing NPCs: Spludwick and Geida.
+ void spin(Direction dir, byte &tripnum);
+ void takeAStep(byte &tripnum);
+ void geidaProcs(byte tripnum);
+
+ void drawSprites();
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_ANIMATION_H
diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp
new file mode 100644
index 0000000000..2bb927646e
--- /dev/null
+++ b/engines/avalanche/avalanche.cpp
@@ -0,0 +1,629 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/avalanche.h"
+
+#include "common/random.h"
+#include "common/savefile.h"
+#include "graphics/thumbnail.h"
+
+namespace Avalanche {
+
+AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *gd) : Engine(syst), _gameDescription(gd), _fxHidden(false), _interrogation(0) {
+ _system = syst;
+ _console = new AvalancheConsole(this);
+
+ _rnd = new Common::RandomSource("avalanche");
+ TimeDate time;
+ _system->getTimeAndDate(time);
+ _rnd->setSeed(time.tm_sec + time.tm_min + time.tm_hour);
+ _showDebugLines = false;
+
+ _clock = nullptr;
+ _graphics = nullptr;
+ _parser = nullptr;
+ _pingo = nullptr;
+ _dialogs = nullptr;
+ _background = nullptr;
+ _sequence = nullptr;
+ _timer = nullptr;
+ _animation = nullptr;
+ _menu = nullptr;
+ _closing = nullptr;
+ _sound = nullptr;
+ _nim = nullptr;
+
+ _platform = gd->desc.platform;
+ initVariables();
+}
+
+AvalancheEngine::~AvalancheEngine() {
+ delete _console;
+ delete _rnd;
+
+ delete _graphics;
+ delete _parser;
+
+ delete _clock;
+ delete _pingo;
+ delete _dialogs;
+ delete _background;
+ delete _sequence;
+ delete _timer;
+ delete _animation;
+ delete _menu;
+ delete _closing;
+ delete _sound;
+ delete _nim;
+
+ for (int i = 0; i < 31; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (_also[i][j] != nullptr) {
+ delete _also[i][j];
+ _also[i][j] = nullptr;
+ }
+ }
+ }
+}
+
+void AvalancheEngine::initVariables() {
+ for (int i = 0; i < 31; i++) {
+ _also[i][0] = nullptr;
+ _also[i][1] = nullptr;
+ }
+
+ memset(_fxPal, 0, 16 * 16 * 3);
+
+ for (int i = 0; i < 15; i++) {
+ _peds[i]._direction = kDirNone;
+ _peds[i]._x = 0;
+ _peds[i]._y = 0;
+ _magics[i]._operation = kMagicNothing;
+ _magics[i]._data = 0;
+ }
+
+ for (int i = 0; i < 7; i++) {
+ _portals[i]._operation = kMagicNothing;
+ _portals[i]._data = 0;
+ }
+
+ for (int i = 0; i < 30; i++) {
+ _fields[i]._x1 = 0;
+ _fields[i]._y1 = 0;
+ _fields[i]._x2 = 0;
+ _fields[i]._y2 = 0;
+ }
+
+ _fieldNum = 0;
+ _cp = 0;
+ _ledStatus = 177;
+ _alive = false;
+ _subjectNum = 0;
+ _him = kPeoplePardon;
+ _her = kPeoplePardon;
+ _it = Parser::kPardon;
+ _roomCycles = 0;
+ _doingSpriteRun = false;
+ _isLoaded = false;
+ _soundFx = true;
+ _holdTheDawn = false;
+
+ _lineNum = 0;
+ for (int i = 0; i < 50; i++)
+ _lines[i]._color = kColorWhite;
+ _dropsOk = false;
+ _cheat = false;
+ _letMeOut = false;
+ _thinks = 2;
+ _thinkThing = true;
+ _seeScroll = false;
+ _currentMouse = 177;
+ _holdLeftMouse = false;
+
+ _jumpStatus = 0;
+ _mushroomGrowing = false;
+ _crapulusWillTell = false;
+ _enterCatacombsFromLustiesRoom = false;
+ _teetotal = false;
+ _malagauche = 0;
+ _drinking = '\0';
+ _enteredLustiesRoomAsMonk = false;
+ _catacombX = 0;
+ _catacombY = 0;
+ _avvysInTheCupboard = false;
+ _geidaFollows = false;
+ _givenPotionToGeida = false;
+ _lustieIsAsleep = false;
+ _beenTiedUp = false;
+ _sittingInPub = false;
+ _spurgeTalkCount = 0;
+ _metAvaroid = false;
+ _takenMushroom = false;
+ _givenPenToAyles = false;
+ _askedDogfoodAboutNim = false;
+ _spludwickAtHome = false;
+ _passedCwytalotInHerts = false;
+ _lastRoom = _lastRoomNotMap = kRoomDummy;
+}
+
+Common::ErrorCode AvalancheEngine::initialize() {
+ _graphics = new GraphicManager(this);
+ _parser = new Parser(this);
+
+ _clock = new Clock(this);
+ _pingo = new Pingo(this);
+ _dialogs = new Dialogs(this);
+ _background = new Background(this);
+ _sequence = new Sequence(this);
+ _timer = new Timer(this);
+ _animation = new Animation(this);
+ _menu = new Menu(this);
+ _closing = new Closing(this);
+ _sound = new SoundHandler(this);
+ _nim = new Nim(this);
+
+ _graphics->init();
+ _dialogs->init();
+ init();
+ _parser->init();
+
+ return Common::kNoError;
+}
+
+GUI::Debugger *AvalancheEngine::getDebugger() {
+ return _console;
+}
+
+Common::Platform AvalancheEngine::getPlatform() const {
+ return _platform;
+}
+
+bool AvalancheEngine::hasFeature(EngineFeature f) const {
+ return (f == kSupportsSavingDuringRuntime) || (f == kSupportsLoadingDuringRuntime);
+}
+
+const char *AvalancheEngine::getCopyrightString() const {
+ return "Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.";
+}
+
+void AvalancheEngine::synchronize(Common::Serializer &sz) {
+ _animation->synchronize(sz);
+ _parser->synchronize(sz);
+ _nim->synchronize(sz);
+ _sequence->synchronize(sz);
+ _background->synchronize(sz);
+
+ sz.syncAsByte(_carryNum);
+ for (int i = 0; i < kObjectNum; i++)
+ sz.syncAsByte(_objects[i]);
+ sz.syncAsSint16LE(_dnascore);
+ sz.syncAsSint32LE(_money);
+ sz.syncAsByte(_room);
+ if (sz.isSaving())
+ _saveNum++;
+ sz.syncAsByte(_saveNum);
+ sz.syncBytes(_roomCount, 100);
+ sz.syncAsByte(_wonNim);
+ sz.syncAsByte(_wineState);
+ sz.syncAsByte(_cwytalotGone);
+ sz.syncAsByte(_passwordNum);
+ sz.syncAsByte(_aylesIsAwake);
+ sz.syncAsByte(_drawbridgeOpen);
+ sz.syncAsByte(_avariciusTalk);
+ sz.syncAsByte(_rottenOnion);
+ sz.syncAsByte(_onionInVinegar);
+ sz.syncAsByte(_givenToSpludwick);
+ sz.syncAsByte(_brummieStairs);
+ sz.syncAsByte(_cardiffQuestionNum);
+ sz.syncAsByte(_passedCwytalotInHerts);
+ sz.syncAsByte(_avvyIsAwake);
+ sz.syncAsByte(_avvyInBed);
+ sz.syncAsByte(_userMovesAvvy);
+ sz.syncAsByte(_npcFacing);
+ sz.syncAsByte(_givenBadgeToIby);
+ sz.syncAsByte(_friarWillTieYouUp);
+ sz.syncAsByte(_tiedUp);
+ sz.syncAsByte(_boxContent);
+ sz.syncAsByte(_talkedToCrapulus);
+ sz.syncAsByte(_jacquesState);
+ sz.syncAsByte(_bellsAreRinging);
+ sz.syncAsByte(_standingOnDais);
+ sz.syncAsByte(_takenPen);
+ sz.syncAsByte(_arrowInTheDoor);
+
+ if (sz.isSaving()) {
+ uint16 like2drinkSize = _favoriteDrink.size();
+ sz.syncAsUint16LE(like2drinkSize);
+ for (uint16 i = 0; i < like2drinkSize; i++) {
+ char actChr = _favoriteDrink[i];
+ sz.syncAsByte(actChr);
+ }
+
+ uint16 favoriteSongSize = _favoriteSong.size();
+ sz.syncAsUint16LE(favoriteSongSize);
+ for (uint16 i = 0; i < favoriteSongSize; i++) {
+ char actChr = _favoriteSong[i];
+ sz.syncAsByte(actChr);
+ }
+
+ uint16 worst_place_on_earthSize = _worstPlaceOnEarth.size();
+ sz.syncAsUint16LE(worst_place_on_earthSize);
+ for (uint16 i = 0; i < worst_place_on_earthSize; i++) {
+ char actChr = _worstPlaceOnEarth[i];
+ sz.syncAsByte(actChr);
+ }
+
+ uint16 spare_eveningSize = _spareEvening.size();
+ sz.syncAsUint16LE(spare_eveningSize);
+ for (uint16 i = 0; i < spare_eveningSize; i++) {
+ char actChr = _spareEvening[i];
+ sz.syncAsByte(actChr);
+ }
+ } else {
+ if (!_favoriteDrink.empty())
+ _favoriteDrink.clear();
+ uint16 like2drinkSize = 0;
+ char actChr = ' ';
+ sz.syncAsUint16LE(like2drinkSize);
+ for (uint16 i = 0; i < like2drinkSize; i++) {
+ sz.syncAsByte(actChr);
+ _favoriteDrink += actChr;
+ }
+
+ if (!_favoriteSong.empty())
+ _favoriteSong.clear();
+ uint16 favourite_songSize = 0;
+ sz.syncAsUint16LE(favourite_songSize);
+ for (uint16 i = 0; i < favourite_songSize; i++) {
+ sz.syncAsByte(actChr);
+ _favoriteSong += actChr;
+ }
+
+ if (!_worstPlaceOnEarth.empty())
+ _worstPlaceOnEarth.clear();
+ uint16 worst_place_on_earthSize = 0;
+ sz.syncAsUint16LE(worst_place_on_earthSize);
+ for (uint16 i = 0; i < worst_place_on_earthSize; i++) {
+ sz.syncAsByte(actChr);
+ _worstPlaceOnEarth += actChr;
+ }
+
+ if (!_spareEvening.empty())
+ _spareEvening.clear();
+ uint16 spare_eveningSize = 0;
+ sz.syncAsUint16LE(spare_eveningSize);
+ for (uint16 i = 0; i < spare_eveningSize; i++) {
+ sz.syncAsByte(actChr);
+ _spareEvening += actChr;
+ }
+ }
+
+ sz.syncAsSint32LE(_totalTime);
+ sz.syncAsByte(_jumpStatus);
+ sz.syncAsByte(_mushroomGrowing);
+ sz.syncAsByte(_spludwickAtHome);
+ sz.syncAsByte(_lastRoom);
+ sz.syncAsByte(_lastRoomNotMap);
+ sz.syncAsByte(_crapulusWillTell);
+ sz.syncAsByte(_enterCatacombsFromLustiesRoom);
+ sz.syncAsByte(_teetotal);
+ sz.syncAsByte(_malagauche);
+ sz.syncAsByte(_drinking);
+ sz.syncAsByte(_enteredLustiesRoomAsMonk);
+ sz.syncAsByte(_catacombX);
+ sz.syncAsByte(_catacombY);
+ sz.syncAsByte(_avvysInTheCupboard);
+ sz.syncAsByte(_geidaFollows);
+ sz.syncAsByte(_givenPotionToGeida);
+ sz.syncAsByte(_lustieIsAsleep);
+ sz.syncAsByte(_beenTiedUp);
+ sz.syncAsByte(_sittingInPub);
+ sz.syncAsByte(_spurgeTalkCount);
+ sz.syncAsByte(_metAvaroid);
+ sz.syncAsByte(_takenMushroom);
+ sz.syncAsByte(_givenPenToAyles);
+ sz.syncAsByte(_askedDogfoodAboutNim);
+
+ for (int i = 0; i < 7; i++) {
+ sz.syncAsSint32LE(_timer->_times[i]._timeLeft);
+ sz.syncAsByte(_timer->_times[i]._action);
+ sz.syncAsByte(_timer->_times[i]._reason);
+ }
+
+}
+
+bool AvalancheEngine::canSaveGameStateCurrently() { // TODO: Refine these!!!
+ return (!_seeScroll && _alive);
+}
+
+Common::Error AvalancheEngine::saveGameState(int slot, const Common::String &desc) {
+ return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed);
+}
+
+bool AvalancheEngine::saveGame(const int16 slot, const Common::String &desc) {
+ Common::String fileName = getSaveFileName(slot);
+ Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(fileName);
+ if (!f) {
+ warning("Can't create file '%s', game not saved.", fileName.c_str());
+ return false;
+ }
+
+ f->writeUint32LE(MKTAG('A', 'V', 'A', 'L'));
+
+ // Write version. We can't restore from obsolete versions.
+ f->writeByte(kSavegameVersion);
+
+ f->writeUint32LE(desc.size());
+ f->write(desc.c_str(), desc.size());
+ Graphics::saveThumbnail(*f);
+
+ TimeDate t;
+ _system->getTimeAndDate(t);
+ f->writeSint16LE(t.tm_mday);
+ f->writeSint16LE(t.tm_mon);
+ f->writeSint16LE(t.tm_year);
+
+ _totalTime += getTimeInSeconds() - _startTime;
+
+ Common::Serializer sz(NULL, f);
+ synchronize(sz);
+ f->finalize();
+ delete f;
+
+ return true;
+}
+
+Common::String AvalancheEngine::getSaveFileName(const int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+bool AvalancheEngine::canLoadGameStateCurrently() { // TODO: Refine these!!!
+ return (!_seeScroll);
+}
+
+Common::Error AvalancheEngine::loadGameState(int slot) {
+ return (loadGame(slot) ? Common::kNoError : Common::kReadingFailed);
+}
+
+bool AvalancheEngine::loadGame(const int16 slot) {
+ Common::String fileName = getSaveFileName(slot);
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
+ if (!f)
+ return false;
+
+ uint32 signature = f->readUint32LE();
+ if (signature != MKTAG('A', 'V', 'A', 'L'))
+ return false;
+
+ // Check version. We can't restore from obsolete versions.
+ byte saveVersion = f->readByte();
+ if (saveVersion > kSavegameVersion) {
+ warning("Savegame of incompatible version!");
+ delete f;
+ return false;
+ }
+
+ // Read the description.
+ uint32 descSize = f->readUint32LE();
+ Common::String description;
+ for (uint32 i = 0; i < descSize; i++) {
+ char actChar = f->readByte();
+ description += actChar;
+ }
+
+ description.toUppercase();
+ Graphics::skipThumbnail(*f);
+
+ // Read the time the game was saved.
+ TimeDate t;
+ t.tm_mday = f->readSint16LE();
+ t.tm_mon = f->readSint16LE();
+ t.tm_year = f->readSint16LE();
+
+ resetVariables();
+
+ Common::Serializer sz(f, NULL);
+ synchronize(sz);
+ delete f;
+
+ _isLoaded = true;
+
+ _seeScroll = true; // This prevents display of the new sprites before the new picture is loaded.
+
+ if (_holdTheDawn) {
+ _holdTheDawn = false;
+ fadeIn();
+ }
+
+ _background->release();
+ minorRedraw();
+ _menu->setup();
+ setRoom(kPeopleAvalot, _room);
+ _alive = true;
+ refreshObjectList();
+ _animation->updateSpeed();
+ drawDirection();
+ _animation->animLink();
+ _background->update();
+
+ Common::String tmpStr = Common::String::format("%cLoaded: %c%s.ASG%c%c%c%s%c%csaved on %s.",
+ kControlItalic, kControlRoman, description.c_str(), kControlCenter, kControlNewLine,
+ kControlNewLine, _roomnName.c_str(), kControlNewLine, kControlNewLine,
+ expandDate(t.tm_mday, t.tm_mon, t.tm_year).c_str());
+ _dialogs->displayText(tmpStr);
+
+ AnimationType *avvy = _animation->_sprites[0];
+ if (avvy->_quick && avvy->_visible)
+ _animation->setMoveSpeed(0, _animation->getDirection()); // We push Avvy in the right direction is he was moving.
+
+ return true;
+}
+
+Common::String AvalancheEngine::expandDate(int d, int m, int y) {
+ static const char months[12][10] = {
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+ };
+
+ Common::String month = Common::String(months[m]);
+ Common::String day = intToStr(d);
+
+ if (((1 <= d) && (d <= 9)) || ((21 <= d) && (d <= 31)))
+ switch (d % 10) {
+ case 1:
+ day += "st";
+ break;
+ case 2:
+ day += "nd";
+ break;
+ case 3:
+ day += "rd";
+ break;
+ default:
+ day += "th";
+ }
+
+ return day + ' ' + month + ' ' + intToStr(y + 1900);
+}
+
+uint32 AvalancheEngine::getTimeInSeconds() {
+ TimeDate time;
+ _system->getTimeAndDate(time);
+ return time.tm_hour * 3600 + time.tm_min * 60 + time.tm_sec;
+}
+
+void AvalancheEngine::updateEvents() {
+ Common::Event event;
+
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ _holdLeftMouse = true; // Used in checkclick() and Menu::menu_link().
+ break;
+ case Common::EVENT_LBUTTONUP:
+ _holdLeftMouse = false; // Same as above.
+ break;
+ case Common::EVENT_KEYDOWN:
+ if ((event.kbd.keycode == Common::KEYCODE_d) && (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _console->attach();
+ _console->onFrame();
+ } else
+ handleKeyDown(event);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool AvalancheEngine::getEvent(Common::Event &event) {
+ return _eventMan->pollEvent(event);
+}
+
+Common::Point AvalancheEngine::getMousePos() {
+ return _eventMan->getMousePos();
+}
+
+Common::Error AvalancheEngine::run() {
+ Common::ErrorCode err = initialize();
+ if (err != Common::kNoError)
+ return err;
+
+ do {
+ runAvalot();
+
+#if 0
+ switch (_storage._operation) {
+ case kRunShootemup:
+ run("seu.avx", kJsb, kBflight, kNormal);
+ break;
+ case kRunDosshell:
+ dosShell();
+ break;
+ case kRunGhostroom:
+ run("g-room.avx", kJsb, kNoBflight, kNormal);
+ break;
+ case kRunGolden:
+ run("golden.avx", kJsb, kBflight, kMusical);
+ break;
+ }
+#endif
+
+ } while (!_letMeOut && !shouldQuit());
+
+ return Common::kNoError;
+}
+
+#if 0
+void AvalancheEngine::run(Common::String what, bool withJsb, bool withBflight, Elm how) {
+ // Probably there'll be no need of this function, as all *.AVX-es will become classes.
+ warning("STUB: run(%s)", what.c_str());
+}
+
+Common::String AvalancheEngine::elmToStr(Elm how) {
+ switch (how) {
+ case kNormal:
+ case kMusical:
+ return Common::String("jsb");
+ case kRegi:
+ return Common::String("REGI");
+ case kElmpoyten:
+ return Common::String("ELMPOYTEN");
+ // Useless, but silent a warning
+ default:
+ return Common::String("");
+ }
+}
+
+// Same as keypressed1().
+void AvalancheEngine::flushBuffer() {
+ warning("STUB: flushBuffer()");
+}
+
+void AvalancheEngine::dosShell() {
+ warning("STUB: dosShell()");
+}
+
+// Needed in dos_shell(). TODO: Remove later.
+Common::String AvalancheEngine::commandCom() {
+ warning("STUB: commandCom()");
+ return ("STUB: commandCom()");
+}
+
+// Needed for run_avalot()'s errors. TODO: Remove later.
+void AvalancheEngine::explain(byte error) {
+ warning("STUB: explain()");
+}
+
+// Needed later.
+void AvalancheEngine::quit() {
+ cursorOn();
+}
+
+#endif
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h
new file mode 100644
index 0000000000..87eb3c2158
--- /dev/null
+++ b/engines/avalanche/avalanche.h
@@ -0,0 +1,348 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_AVALANCHE_H
+#define AVALANCHE_AVALANCHE_H
+
+#include "avalanche/console.h"
+#include "avalanche/graphics.h"
+#include "avalanche/parser.h"
+#include "avalanche/avalot.h"
+#include "avalanche/pingo.h"
+#include "avalanche/dialogs.h"
+#include "avalanche/background.h"
+#include "avalanche/sequence.h"
+#include "avalanche/timer.h"
+#include "avalanche/animation.h"
+#include "avalanche/menu.h"
+#include "avalanche/closing.h"
+#include "avalanche/sound.h"
+#include "avalanche/nim.h"
+
+#include "common/serializer.h"
+
+#include "engines/engine.h"
+#include "engines/advancedDetector.h"
+
+#include "graphics/cursorman.h"
+
+namespace Common {
+class RandomSource;
+}
+
+namespace Avalanche {
+
+struct AvalancheGameDescription {
+ ADGameDescription desc;
+};
+
+static const int kSavegameVersion = 2;
+
+enum Pitch {
+ kPitchInvalid,
+ kPitchLower,
+ kPitchSame,
+ kPitchHigher
+};
+
+class AvalancheEngine : public Engine {
+public:
+ byte _saveNum; // number of times this game has been saved
+
+ Clock *_clock;
+ GraphicManager *_graphics;
+ Parser *_parser;
+ Pingo *_pingo;
+ Dialogs *_dialogs;
+ Background *_background;
+ Sequence *_sequence;
+ Timer *_timer;
+ Animation *_animation;
+ Menu *_menu;
+ Closing *_closing;
+ SoundHandler *_sound;
+ Nim *_nim;
+
+ OSystem *_system;
+
+ AvalancheEngine(OSystem *syst, const AvalancheGameDescription *gd);
+ ~AvalancheEngine();
+
+ Common::ErrorCode initialize();
+ GUI::Debugger *getDebugger();
+
+ Common::RandomSource *_rnd;
+
+ const AvalancheGameDescription *_gameDescription;
+ uint32 getFeatures() const;
+ const char *getGameId() const;
+ Common::Platform getPlatform() const;
+ bool hasFeature(EngineFeature f) const;
+ const char *getCopyrightString() const;
+
+ void synchronize(Common::Serializer &sz);
+ virtual bool canSaveGameStateCurrently();
+ Common::Error saveGameState(int slot, const Common::String &desc);
+ bool saveGame(const int16 slot, const Common::String &desc);
+ Common::String getSaveFileName(const int slot);
+ virtual bool canLoadGameStateCurrently();
+ Common::Error loadGameState(int slot);
+ bool loadGame(const int16 slot);
+ Common::String expandDate(int d, int m, int y);
+ uint32 getTimeInSeconds();
+
+ void updateEvents();
+ bool getEvent(Common::Event &event); // A wrapper around _eventMan->pollEvent(), so we can use it in Scrolls::normscroll() for example.
+ Common::Point getMousePos();
+
+protected:
+ // Engine APIs
+ Common::Error run();
+
+private:
+ AvalancheConsole *_console;
+ Common::Platform _platform;
+
+#if 0
+ struct {
+ byte _operation;
+ uint16 _skellern;
+ byte _contents[1000];
+ } _storage;
+
+ static const int16 kRunShootemup = 1, kRunDosshell = 2, kRunGhostroom = 3, kRunGolden = 4;
+ static const int16 kReset = 0;
+
+ static const bool kJsb = true, kNoJsb = false, kBflight = true, kNoBflight = false;
+
+ // From bootstrp:
+ enum Elm {kNormal, kMusical, kElmpoyten, kRegi};
+
+ Common::String _argsWithNoFilename;
+ byte _originalMode;
+ byte *_old1c;
+ Common::String _segofs;
+ int32 _soundcard, _speed, _baseaddr, _irq, _dma;
+ bool _zoomy;
+
+ void run(Common::String what, bool withJsb, bool withBflight, Elm how);
+ void bFlightOn();
+ void bFlightOff();
+ Common::String elmToStr(Elm how);
+ bool keyPressed();
+ void flushBuffer();
+ void dosShell();
+ void bFlight();
+ Common::String commandCom();
+ void explain(byte error);
+ void cursorOff();
+ void cursorOn();
+ void quit();
+#endif
+
+public:
+ // For Thinkabout:
+ static const bool kThing = true;
+ static const bool kPerson = false;
+
+ static const char kSpludwicksOrder[3];
+
+ static const uint16 kNotes[12];
+ static const TuneType kTune;
+
+ bool _holdLeftMouse;
+
+ // If this is greater than zero, the next line you type is stored in the DNA in a position dictated by the value.
+ // If a scroll comes up, or you leave the room, it's automatically set to zero.
+ byte _interrogation;
+
+ // Former DNA structure
+ byte _carryNum; // How many objects you're carrying...
+ bool _objects[kObjectNum]; // ...and which ones they are.
+ int16 _dnascore; // your score, of course
+ int32 _money; // your current amount of dosh
+ Room _room; // your current room
+ bool _wonNim; // Have you *won* Nim? (That's harder.)
+ byte _wineState; // 0=good (Notts), 1=passable(Argent) ... 3=vinegar.
+ bool _cwytalotGone; // Has Cwytalot rushed off to Jerusalem yet?
+ byte _passwordNum; // Number of the passw for this game.
+ bool _aylesIsAwake; // pretty obvious!
+ byte _drawbridgeOpen; // Between 0 (shut) and 4 (open).
+ byte _avariciusTalk; // How much Avaricius has said to you.
+ bool _rottenOnion; // And has it rotted?
+ bool _onionInVinegar; // Is the onion in the vinegar?
+ byte _givenToSpludwick; // 0 = nothing given, 1 = onion...
+ byte _brummieStairs; // Progression through the stairs trick.
+ byte _cardiffQuestionNum; // Things you get asked in Cardiff.
+ bool _avvyIsAwake; // Well? Is Avvy awake? (Screen 1 only.)
+ bool _avvyInBed; // True if Avvy's in bed, but awake.
+ bool _userMovesAvvy; // If this is false, the user has no control over Avvy's movements.
+ byte _npcFacing; // If there's an NPC in the current room which turns it's head according to Avvy's movement (keep looking at him), this variable tells which way it's facing at the moment.
+ bool _givenBadgeToIby; // Have you given the badge to Iby yet?
+ bool _friarWillTieYouUp; // If you're going to get tied up.
+ bool _tiedUp; // You ARE tied up!
+ byte _boxContent; // 0 = money (sixpence), 254 = empty, any other number implies the contents of the box.
+ bool _talkedToCrapulus; // Pretty self-explanatory.
+ byte _jacquesState; // 0=asleep, 1=awake, 2=gets up, 3=gone.
+ bool _bellsAreRinging; // Is Jacques ringing the bells?
+ bool _standingOnDais; // In room 71, inside Cardiff Castle.
+ bool _takenPen; // Have you taken the pen (in Cardiff?)
+ bool _arrowInTheDoor; // Did the arrow hit the wall?
+ Common::String _favoriteDrink, _favoriteSong, _worstPlaceOnEarth, _spareEvening; // Personalisation str's
+ uint32 _startTime; // When did you start playing this session?
+ uint32 _totalTime; // Your total time playing this game, in seconds. Updated only at saving and loading.
+ byte _jumpStatus; // Fixes how high you're jumping.
+ bool _mushroomGrowing; // Is the mushroom growing in 42?
+ bool _crapulusWillTell; // Will Crapulus tell you about Spludwick being away?
+ bool _enterCatacombsFromLustiesRoom;
+ bool _teetotal; // Are we touching any more drinks?
+ byte _malagauche; // Position of Malagauche. See Celer for more info.
+ char _drinking; // What's he getting you?
+ bool _enteredLustiesRoomAsMonk;
+ byte _catacombX, _catacombY; // XY coords in the catacombs.
+ bool _avvysInTheCupboard; // On screen 22.
+ bool _geidaFollows; // Is Geida following you?
+ bool _givenPotionToGeida; // Does Geida have the potion?
+ bool _lustieIsAsleep; // Is BDL asleep?
+ bool _beenTiedUp; // In r__Robins.
+ bool _sittingInPub; // Are you sitting down in the pub?
+ byte _spurgeTalkCount; // Count for talking to Spurge.
+ bool _metAvaroid;
+ bool _takenMushroom, _givenPenToAyles, _askedDogfoodAboutNim;
+ // End of former DNA Structure
+
+ bool _showDebugLines;
+ byte _lineNum; // Number of lines.
+ LineType _lines[50]; // For Also.
+ bool _dropsOk;
+ bool _cheat; // CHECKME: Currently unused
+ bool _letMeOut;
+ byte _thinks;
+ bool _thinkThing;
+ bool _seeScroll; // TODO: maybe this means we're interacting with the toolbar / a scroll?
+ char _objectList[10];
+ // Called .free() for them in ~Gyro().
+
+ byte _currentMouse; // current mouse-void
+ Common::String *_also[31][2];
+ PedType _peds[15];
+ MagicType _magics[15];
+ MagicType _portals[7];
+ FieldType _fields[30];
+ byte _fieldNum;
+ Common::String _listen;
+ byte _cp, _ledStatus;
+ FontType _font;
+ bool _alive;
+ byte _subjectNum; // The same thing.
+ People _him, _her;
+ byte _it;
+ uint32 _roomCycles; // Set to 0 when you enter a room, added to in every loop. Cycles since you've been in this room.
+
+ bool _doingSpriteRun; // Only set to True if we're doing a sprite_run at this moment. This stops the trippancy system from moving any of the sprites.
+ bool _soundFx;
+
+ bool _isLoaded; // Is it a loaded gamestate?
+
+ void callVerb(VerbCode id);
+ void loadRoom(byte num);
+ void thinkAbout(byte object, bool type); // Hey!!! Get it and put it!!!
+ void incScore(byte num); // Add on no. of points
+ void fxToggle();
+ void refreshObjectList();
+ void errorLed();
+ void fadeOut();
+ void fadeIn();
+ void drawDirection(); // Draws the little icon at the left end of the text input field.
+ void gameOver();
+ uint16 bearing(byte whichPed); // Returns the bearing from ped 'whichped' to Avvy, in degrees.
+
+ // There are two kinds of redraw: Major and Minor. Minor is what happens when you load a game, etc. Major redraws EVERYTHING.
+ void minorRedraw();
+ void majorRedraw();
+
+ void spriteRun();
+
+ Common::String intToStr(int32 num);
+ void newGame(); // This sets up the DNA for a completely new game.
+ bool getFlag(char x);
+ bool decreaseMoney(uint16 amount); // Called pennycheck in the original.
+
+ Common::String getName(People whose);
+ Common::String getItem(byte which); // Called get_better in the original.
+ Common::String f5Does(); // This procedure determines what f5 does.
+
+ void openDoor(Room whither, byte ped, byte magicnum); // Handles slidey-open doors.
+ void flipRoom(Room room, byte ped);
+
+ void setRoom(People persId, Room roomId);
+ Room getRoom(People persId);
+private:
+ static const int16 kMaxSprites = 2; // Current max no. of sprites.
+ static Room _whereIs[29];
+
+ // Will be used in dusk() and dawn().
+ bool _fxHidden;
+ byte _fxPal[16][16][3];
+
+ bool _spludwickAtHome; // Is Spludwick at home?
+ bool _passedCwytalotInHerts; // Have you passed Cwytalot in Herts?
+ bool _holdTheDawn; // If this is true, calling Dawn will do nothing. It's used, for example, at the start, to stop Load from dawning.
+ byte _lastRoom;
+ byte _lastRoomNotMap;
+ byte _roomCount[100]; // Add one to each every time you enter a room
+ Common::String _mouseText;
+ Common::String _flags;
+ Common::String _roomnName; // Name of actual room
+ int8 _scoreToDisplay[3];
+
+ Common::String readAlsoStringFromFile(Common::File &file);
+ void runAvalot();
+ void init();
+ void initVariables();
+ void setup();
+ void scram(Common::String &str);
+ void unScramble();
+ void handleKeyDown(Common::Event &event); // To replace Basher::keyboard_link() and Basher::typein().
+ void enterNewTown();
+ void findPeople(byte room);
+ void putGeidaAt(byte whichPed, byte ped);
+ void guideAvvy(Common::Point cursorPos);
+ void enterRoom(Room room, byte ped);
+ void exitRoom(byte x);
+ void drawToolbar();
+ void drawScore();
+ void useCompass(const Common::Point &cursorPos); // Click on the compass on the toolbar to control Avvy's movement.
+ void checkClick();
+ void fixFlashers();
+ void loadAlso(byte num);
+ void resetVariables();
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_AVALANCHE_H
diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp
new file mode 100644
index 0000000000..ec3f81e55d
--- /dev/null
+++ b/engines/avalanche/avalot.cpp
@@ -0,0 +1,1755 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman.
+ */
+
+/* AVALOT The kernel of the program. */
+
+#include "avalanche/avalanche.h"
+
+#include "common/random.h"
+#include "common/system.h"
+#include "common/config-manager.h"
+#include "graphics/palette.h"
+
+namespace Avalanche {
+
+// vv Stairs trap.
+
+/* Explanation: $NSEW.
+ Nibble N: North.
+ 0 = no connection,
+ 2 = (left,) middle(, right) door with left-hand handle,
+ 5 = (left,) middle(, right) door with right-hand handle,
+ 7 = arch,
+ 8 = arch and 1 north of it,
+ 9 = arch and 2 north of it,
+ D = no connection + WINDOW,
+ E = no connection + TORCH,
+ F = recessed door (to Geida's room.)
+
+ Nibble S: South.
+ 0 = no connection,
+ 1,2,3 = left, middle, right door.
+
+ Nibble E: East.
+ 0 = no connection (wall),
+ 1 = no connection (wall + window),
+ 2 = wall with door,
+ 3 = wall with door and window,
+ 6 = wall with candles,
+ 7 = wall with door and candles,
+ F = straight-through corridor.
+
+ Nibble W: West.
+ 0 = no connection (wall),
+ 1 = no connection (wall + shield),
+ 2 = wall with door,
+ 3 = wall with door and shield,
+ 4 = no connection (window),
+ 5 = wall with door and window,
+ 6 = wall with candles,
+ 7 = wall with door and candles,
+ F = straight-through corridor. */
+
+const char AvalancheEngine::kSpludwicksOrder[3] = {kObjectOnion, kObjectInk, kObjectMushroom};
+const uint16 AvalancheEngine::kNotes[12] = {196, 220, 247, 262, 294, 330, 350, 392, 440, 494, 523, 587};
+const TuneType AvalancheEngine::kTune = {
+ kPitchHigher, kPitchHigher, kPitchLower, kPitchSame, kPitchHigher, kPitchHigher, kPitchLower, kPitchHigher, kPitchHigher, kPitchHigher,
+ kPitchLower, kPitchHigher, kPitchHigher, kPitchSame, kPitchHigher, kPitchLower, kPitchLower, kPitchLower, kPitchLower, kPitchHigher,
+ kPitchHigher, kPitchLower, kPitchLower, kPitchLower, kPitchLower, kPitchSame, kPitchLower, kPitchHigher, kPitchSame, kPitchLower, kPitchHigher
+};
+
+Room AvalancheEngine::_whereIs[29] = {
+ // The Lads
+ kRoomYours, // Avvy
+ kRoomSpludwicks, // Spludwick
+ kRoomOutsideYours, // Crapulus
+ kRoomDucks, // Duck - r__DucksRoom's not defined yet.
+ kRoomArgentPub, // Malagauche
+ kRoomRobins, // Friar Tuck.
+ kRoomDummy, // Robin Hood - can't meet him at the start.
+ kRoomBrummieRoad, // Cwytalot
+ kRoomLustiesRoom, // Baron du Lustie.
+ kRoomOutsideCardiffCastle, // The Duke of Cardiff.
+ kRoomArgentPub, // Dogfood
+ kRoomOutsideDucks, // Trader
+ kRoomArgentPub, // Ibythneth
+ kRoomAylesOffice, // Ayles
+ kRoomNottsPub, // Port
+ kRoomNottsPub, // Spurge
+ kRoomMusicRoom, // Jacques
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ kRoomNowhere,
+ // The Lasses
+ kRoomYours, // Arkata
+ kRoomGeidas, // Geida
+ kRoomDummy, // nobody allocated here!
+ kRoomWiseWomans // The Wise Woman.
+};
+
+Clock::Clock(AvalancheEngine *vm) {
+ _vm = vm;
+ // Magic value to determine if we just created the instance
+ _oldHour = _oldHourAngle = _oldMinute = 17717;
+ _hour = _minute = _second = 0;
+ _hourAngle = 0;
+}
+
+void Clock::update() {
+ TimeDate t;
+ _vm->_system->getTimeAndDate(t);
+ _hour = t.tm_hour;
+ _minute = t.tm_min;
+ _second = t.tm_sec;
+
+ _hourAngle = (_hour % 12) * 30 + _minute / 2;
+
+ if (_oldHour != _hour) {
+ plotHands();
+ chime();
+ }
+
+ if (_oldMinute != _minute)
+ plotHands();
+
+ if ((_hour == 0) && (_oldHour != 0) && (_oldHour != 17717)) {
+ Common::String tmpStr = Common::String::format("Good morning!%c%cYes, it's just past " \
+ "midnight. Are you having an all-night Avvy session? Glad you like the game that much!",
+ kControlNewLine, kControlNewLine);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ _oldHour = _hour;
+ _oldHourAngle = _hourAngle;
+ _oldMinute = _minute;
+}
+
+Common::Point Clock::calcHand(uint16 angle, uint16 length, Color color) {
+ if (angle > 900) {
+ return(Common::Point(177, 177));
+ }
+
+ return(_vm->_graphics->drawScreenArc(kCenterX, kCenterY, 449 - angle, 450 - angle, length, color));
+}
+
+void Clock::drawHand(const Common::Point &endPoint, Color color) {
+ if (endPoint.x == 177)
+ return;
+
+ _vm->_graphics->drawScreenLine(kCenterX, kCenterY, endPoint.x, endPoint.y, color);
+}
+
+void Clock::plotHands() {
+ _clockHandHour = calcHand(_oldHourAngle, 14, kColorYellow);
+ _clockHandMinute = calcHand(_oldMinute * 6, 17, kColorYellow);
+ drawHand(_clockHandHour, kColorBrown);
+ drawHand(_clockHandMinute, kColorBrown);
+
+ _clockHandHour = calcHand(_hourAngle, 14, kColorBrown);
+ _clockHandMinute = calcHand(_minute * 6, 17, kColorBrown);
+ drawHand(_clockHandHour, kColorYellow);
+ drawHand(_clockHandMinute, kColorYellow);
+}
+
+void Clock::chime() {
+ // Too high - must be first time around
+ // Mute - skip the sound generation
+ if ((_oldHour == 17717) || (!_vm->_soundFx))
+ return;
+
+ byte hour = _hour % 12;
+ if (hour == 0)
+ hour = 12;
+
+ _vm->_graphics->loadMouse(kCurWait);
+
+ for (int i = 1; i <= hour; i++) {
+ for (int j = 1; j <= 3; j++)
+ _vm->_sound->playNote((i % 3) * 64 + 140 - j * 30, 50 - j * 12);
+ if (i != hour)
+ _vm->_system->delayMillis(100);
+ }
+}
+
+void AvalancheEngine::handleKeyDown(Common::Event &event) {
+ _sound->click();
+
+ if ((Common::KEYCODE_F1 <= event.kbd.keycode) && (event.kbd.keycode <= Common::KEYCODE_F15))
+ _parser->handleFunctionKey(event);
+ else if ((32 <= event.kbd.ascii) && (event.kbd.ascii <= 128) && (event.kbd.ascii != 47))
+ _parser->handleInputText(event);
+ else
+ switch (event.kbd.keycode) { // We can control Avvy with the numpad as well.
+ case Common::KEYCODE_KP8:
+ event.kbd.keycode = Common::KEYCODE_UP;
+ break;
+ case Common::KEYCODE_KP2:
+ event.kbd.keycode = Common::KEYCODE_DOWN;
+ break;
+ case Common::KEYCODE_KP6:
+ event.kbd.keycode = Common::KEYCODE_RIGHT;
+ break;
+ case Common::KEYCODE_KP4:
+ event.kbd.keycode = Common::KEYCODE_LEFT;
+ break;
+ case Common::KEYCODE_KP9:
+ event.kbd.keycode = Common::KEYCODE_PAGEUP;
+ break;
+ case Common::KEYCODE_KP3:
+ event.kbd.keycode = Common::KEYCODE_PAGEDOWN;
+ break;
+ case Common::KEYCODE_KP7:
+ event.kbd.keycode = Common::KEYCODE_HOME;
+ break;
+ case Common::KEYCODE_KP1:
+ event.kbd.keycode = Common::KEYCODE_END;
+ break;
+ default:
+ break;
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_HOME:
+ case Common::KEYCODE_END:
+ case Common::KEYCODE_KP5:
+ if (_alive && _avvyIsAwake) {
+ _animation->handleMoveKey(event); // Fallthroughs are intended.
+ drawDirection();
+ return;
+ }
+ case Common::KEYCODE_BACKSPACE:
+ _parser->handleBackspace();
+ break;
+ case Common::KEYCODE_RETURN:
+ _parser->handleReturn();
+ break;
+ default:
+ break;
+ }
+
+ drawDirection();
+}
+
+void AvalancheEngine::setup() {
+ init();
+
+ _dialogs->reset();
+ fadeOut();
+ _graphics->loadDigits();
+
+ _parser->_inputTextPos = 0;
+ _parser->_quote = true;
+
+ _animation->resetAnims();
+
+ drawToolbar();
+ _dialogs->setReadyLight(2);
+
+ fadeIn();
+ _parser->_cursorState = false;
+ _parser->cursorOn();
+ _animation->_sprites[0]->_speedX = kWalk;
+ _animation->updateSpeed();
+
+ _menu->init();
+
+ int16 loadSlot = ConfMan.instance().getInt("save_slot");
+ if (loadSlot >= 0) {
+ _thinks = 2; // You always have money.
+ thinkAbout(kObjectMoney, kThing);
+
+ loadGame(loadSlot);
+ } else {
+ newGame();
+
+ _soundFx = !_soundFx;
+ fxToggle();
+ thinkAbout(kObjectMoney, kThing);
+
+ _dialogs->displayScrollChain('Q', 83); // Info on the game, etc.
+ }
+}
+
+void AvalancheEngine::runAvalot() {
+ setup();
+
+ do {
+ uint32 beginLoop = _system->getMillis();
+
+ updateEvents(); // The event handler.
+
+ _clock->update();
+ _menu->update();
+ _background->update();
+ _animation->animLink();
+ checkClick();
+ _timer->updateTimer();
+
+ _graphics->drawDebugLines();
+ _graphics->refreshScreen();
+
+ uint32 delay = _system->getMillis() - beginLoop;
+ if (delay <= 55)
+ _system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight).
+ } while (!_letMeOut && !shouldQuit());
+
+ warning("STUB: run()");
+
+ _closing->exitGame();
+}
+
+void AvalancheEngine::init() {
+ for (int i = 0; i < 31; i++) {
+ for (int j = 0; j < 2; j++)
+ _also[i][j] = nullptr;
+ }
+
+#if 0
+ if (_vm->_enhanced->atbios)
+ atkey = "f1";
+ else
+ atkey = "alt-";
+#endif
+
+ _letMeOut = false;
+ _currentMouse = 177;
+ _dropsOk = true;
+ _mouseText = "";
+ _cheat = false;
+ _cp = 0;
+ _ledStatus = 177;
+ for (int i = 0; i < 3; i++)
+ _scoreToDisplay[i] = -1; // Impossible digits.
+ _holdTheDawn = false;
+
+ _graphics->loadMouse(kCurWait);
+ CursorMan.showMouse(true);
+}
+
+/**
+ * Call a given Verb
+ * @remarks Originally called 'callverb'
+ */
+void AvalancheEngine::callVerb(VerbCode id) {
+ if (id == _parser->kPardon) {
+ Common::String tmpStr = Common::String::format("The f5 key lets you do a particular action in certain " \
+ "situations. However, at the moment there is nothing assigned to it. You may press alt-A to see " \
+ "what the current setting of this key is.");
+ _dialogs->displayText(tmpStr);
+ } else
+ _parser->doVerb(id);
+}
+
+/**
+ * Check is it's possible to give something to Spludwick
+ * @remarks Originally called 'nextstring'
+ */
+Common::String AvalancheEngine::readAlsoStringFromFile(Common::File &file) {
+ Common::String str;
+ byte length = file.readByte();
+ for (int i = 0; i < length; i++)
+ str += file.readByte();
+ return str;
+}
+
+void AvalancheEngine::scram(Common::String &str) {
+ for (uint i = 0; i < str.size(); i++)
+ str.setChar(str[i] ^ 177, i);
+}
+
+void AvalancheEngine::unScramble() {
+ for (int i = 0; i < 31; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (_also[i][j] != nullptr)
+ scram(*_also[i][j]);
+ }
+ }
+ scram(_listen);
+ scram(_flags);
+}
+
+void AvalancheEngine::loadAlso(byte num) {
+ for (int i = 0; i < 31; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (_also[i][j] != nullptr) {
+ delete _also[i][j];
+ _also[i][j] = nullptr;
+ }
+ }
+ }
+ Common::String filename;
+ filename = Common::String::format("also%d.avd", num);
+ Common::File file;
+ if (!file.open(filename))
+ error("AVALANCHE: File not found: %s", filename.c_str());
+
+ file.seek(128);
+
+ byte alsoNum = file.readByte();
+ Common::String tmpStr;
+ for (int i = 0; i <= alsoNum; i++) {
+ for (int j = 0; j < 2; j++) {
+ _also[i][j] = new Common::String;
+ *_also[i][j] = readAlsoStringFromFile(file);
+ }
+ tmpStr = Common::String::format("\x9D%s\x9D", _also[i][0]->c_str());
+ *_also[i][0] = tmpStr;
+ }
+
+ memset(_lines, 0xFF, sizeof(_lines));
+
+ _lineNum = file.readByte();
+ for (int i = 0; i < _lineNum; i++) {
+ LineType *curLine = &_lines[i];
+ curLine->_x1 = file.readSint16LE();
+ curLine->_y1 = file.readSint16LE();
+ curLine->_x2 = file.readSint16LE();
+ curLine->_y2 = file.readSint16LE();
+ curLine->_color = (Color)file.readByte();
+ }
+
+ memset(_peds, 177, sizeof(_peds));
+ byte pedNum = file.readByte();
+ for (int i = 0; i < pedNum; i++) {
+ PedType *curPed = &_peds[i];
+ curPed->_x = file.readSint16LE();
+ curPed->_y = file.readSint16LE();
+ curPed->_direction = (Direction)file.readByte();
+ }
+
+ _fieldNum = file.readByte();
+ for (int i = 0; i < _fieldNum; i++) {
+ FieldType *curField = &_fields[i];
+ curField->_x1 = file.readSint16LE();
+ curField->_y1 = file.readSint16LE();
+ curField->_x2 = file.readSint16LE();
+ curField->_y2 = file.readSint16LE();
+ }
+
+ for (int i = 0; i < 15; i++) {
+ MagicType *magic = &_magics[i];
+ magic->_operation = file.readByte();
+ magic->_data = file.readUint16LE();
+ }
+
+ for (int i = 0; i < 7; i++) {
+ MagicType *portal = &_portals[i];
+ portal->_operation = file.readByte();
+ portal->_data = file.readUint16LE();
+ }
+
+ _flags.clear();
+ for (int i = 0; i < 26; i++)
+ _flags += file.readByte();
+
+ int16 size = file.readByte();
+ _listen.clear();
+ for (int i = 0; i < size; i++)
+ _listen += file.readByte();
+
+ _graphics->clearAlso();
+
+ CursorMan.showMouse(false);
+ for (int i = 0; i < _lineNum; i++) {
+ // We had to check if the lines are within the borders of the screen.
+ if ((_lines[i]._x1 >= 0) && (_lines[i]._x1 < kScreenWidth) && (_lines[i]._y1 >= 0) && (_lines[i]._y1 < kScreenHeight)
+ && (_lines[i]._x2 >= 0) && (_lines[i]._x2 < kScreenWidth) && (_lines[i]._y2 >= 0) && (_lines[i]._y2 < kScreenHeight))
+ _graphics->setAlsoLine(_lines[i]._x1, _lines[i]._y1, _lines[i]._x2, _lines[i]._y2, _lines[i]._color);
+ }
+ CursorMan.showMouse(true);
+
+ file.close();
+
+ unScramble();
+ for (int i = 0; i <= alsoNum; i++) {
+ tmpStr = Common::String::format(",%s,", _also[i][0]->c_str());
+ *_also[i][0] = tmpStr;
+ }
+}
+
+void AvalancheEngine::loadRoom(byte num) {
+ CursorMan.showMouse(false);
+
+ Common::String filename = Common::String::format("place%d.avd", num);
+ Common::File file;
+ if (!file.open(filename))
+ error("AVALANCHE: File not found: %s", filename.c_str());
+
+ file.seek(146);
+ if (!_roomnName.empty())
+ _roomnName.clear();
+ for (int i = 0; i < 30; i++) {
+ char actChar = file.readByte();
+ if ((32 <= actChar) && (actChar <= 126))
+ _roomnName += actChar;
+ }
+ // Compression method byte follows this...
+
+ file.seek(177);
+
+ _graphics->loadBackground(file);
+ _graphics->refreshBackground();
+
+ file.close();
+
+ loadAlso(num);
+ _background->load(num);
+ CursorMan.showMouse(true);
+}
+
+void AvalancheEngine::findPeople(byte room) {
+ for (int i = 1; i < 29; i++) {
+ if (_whereIs[i] == room) {
+ if (i < 25)
+ _him = (People)(150 + i);
+ else
+ _her = (People)(150 + i);
+ }
+ }
+}
+
+void AvalancheEngine::exitRoom(byte x) {
+ _sound->stopSound();
+ _background->release();
+ _seeScroll = true; // This stops the trippancy system working over the length of this procedure.
+
+ switch (x) {
+ case kRoomSpludwicks:
+ _timer->loseTimer(Timer::kReasonAvariciusTalks);
+ _avariciusTalk = 0;
+ // He doesn't HAVE to be talking for this to work. It just deletes it IF it exists.
+ break;
+ case kRoomBridge:
+ if (_drawbridgeOpen > 0) {
+ _drawbridgeOpen = 4; // Fully open.
+ _timer->loseTimer(Timer::kReasonDrawbridgeFalls);
+ }
+ break;
+ case kRoomOutsideCardiffCastle:
+ _timer->loseTimer(Timer::kReasonCardiffsurvey);
+ break;
+ case kRoomRobins:
+ _timer->loseTimer(Timer::kReasonGettingTiedUp);
+ break;
+ }
+
+ _interrogation = 0; // Leaving the room cancels all the questions automatically.
+ _seeScroll = false; // Now it can work again!
+
+ _lastRoom = _room;
+ if (_room != kRoomMap)
+ _lastRoomNotMap = _room;
+}
+
+/**
+ * Only when entering a NEW town! Not returning to the last one,
+ * but choosing another from the map.
+ * @remarks Originally called 'new_town'
+ */
+void AvalancheEngine::enterNewTown() {
+ _menu->setup();
+
+ switch (_room) {
+ case kRoomOutsideNottsPub: // Entry into Nottingham.
+ if ((_roomCount[kRoomRobins] > 0) && (_beenTiedUp) && (!_takenMushroom))
+ _mushroomGrowing = true;
+ break;
+ case kRoomWiseWomans: // Entry into Argent.
+ if (_talkedToCrapulus && (!_lustieIsAsleep)) {
+ _spludwickAtHome = !((_roomCount[kRoomWiseWomans] % 3) == 1);
+ _crapulusWillTell = !_spludwickAtHome;
+ } else {
+ _spludwickAtHome = true;
+ _crapulusWillTell = false;
+ }
+ if (_boxContent == kObjectWine)
+ _wineState = 3; // Vinegar
+ break;
+ default:
+ break;
+ }
+
+ if ((_room != kRoomOutsideDucks) && (_objects[kObjectOnion - 1]) && !(_onionInVinegar))
+ _rottenOnion = true; // You're holding the onion
+}
+
+void AvalancheEngine::putGeidaAt(byte whichPed, byte ped) {
+ if (ped == 0)
+ return;
+ AnimationType *spr1 = _animation->_sprites[1];
+
+ spr1->init(5, false); // load Geida
+ _animation->appearPed(1, whichPed);
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = Animation::kProcGeida;
+}
+
+void AvalancheEngine::enterRoom(Room roomId, byte ped) {
+ _seeScroll = true; // This stops the trippancy system working over the length of this procedure.
+
+ findPeople(roomId);
+ _room = roomId;
+ if (ped != 0)
+ _roomCount[roomId]++;
+
+ loadRoom(roomId);
+
+ if ((_roomCount[roomId] == 0) && (!getFlag('S')))
+ incScore(1);
+
+ _whereIs[kPeopleAvalot - 150] = _room;
+
+ if (_geidaFollows)
+ _whereIs[kPeopleGeida - 150] = roomId;
+
+ _roomCycles = 0;
+
+ if ((_lastRoom == kRoomMap) && (_lastRoomNotMap != _room))
+ enterNewTown();
+
+ _animation->updateSpeed();
+
+ switch (roomId) {
+ case kRoomYours:
+ if (_avvyInBed) {
+ _background->draw(-1, -1, 2);
+ _graphics->refreshBackground();
+ _timer->addTimer(100, Timer::kProcArkataShouts, Timer::kReasonArkataShouts);
+ }
+ break;
+
+ case kRoomOutsideYours:
+ if (ped > 0) {
+ AnimationType *spr1 = _animation->_sprites[1];
+ if (!_talkedToCrapulus) {
+ _whereIs[kPeopleCrapulus - 150] = kRoomOutsideYours;
+ spr1->init(8, false); // load Crapulus
+
+ if (_roomCount[kRoomOutsideYours] == 1) {
+ _animation->appearPed(1, 3); // Start on the right-hand side of the screen.
+ spr1->walkTo(4); // Walks up to greet you.
+ } else {
+ _animation->appearPed(1, 4); // Starts where he was before.
+ spr1->_facingDir = kDirLeft;
+ }
+
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = Animation::kProcFaceAvvy; // He always faces Avvy.
+
+ } else
+ _whereIs[kPeopleCrapulus - 150] = kRoomNowhere;
+
+ if (_crapulusWillTell) {
+ spr1->init(8, false);
+ _animation->appearPed(1, 1);
+ spr1->walkTo(3);
+ _timer->addTimer(20, Timer::kProcCrapulusSpludOut, Timer::kReasonCrapulusSaysSpludwickOut);
+ _crapulusWillTell = false;
+ }
+ }
+ break;
+
+ case kRoomOutsideSpludwicks:
+ if ((_roomCount[kRoomOutsideSpludwicks] == 1) && (ped == 1)) {
+ _timer->addTimer(20, Timer::kProcBang, Timer::kReasonExplosion);
+ _spludwickAtHome = true;
+ }
+ break;
+
+ case kRoomSpludwicks:
+ if (_spludwickAtHome) {
+ AnimationType *spr1 = _animation->_sprites[1];
+ if (ped > 0) {
+ spr1->init(2, false); // load Spludwick
+ _animation->appearPed(1, 1);
+ _whereIs[kPeopleSpludwick - 150] = kRoomSpludwicks;
+ }
+
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = Animation::kProcGeida;
+ } else
+ _whereIs[kPeopleSpludwick - 150] = kRoomNowhere;
+ break;
+
+ case kRoomBrummieRoad:
+ if (_geidaFollows)
+ putGeidaAt(4, ped);
+ if (_cwytalotGone) {
+ _magics[kColorLightred - 1]._operation = kMagicNothing;
+ _whereIs[kPeopleCwytalot - 150] = kRoomNowhere;
+ } else if (ped > 0) {
+ AnimationType *spr1 = _animation->_sprites[1];
+ spr1->init(4, false); // 4 = Cwytalot
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = Animation::kProcFollowAvvyY;
+ _whereIs[kPeopleCwytalot - 150] = kRoomBrummieRoad;
+
+ if (_roomCount[kRoomBrummieRoad] == 1) { // First time here...
+ _animation->appearPed(1, 1); // He appears on the right of the screen...
+ spr1->walkTo(3); // ...and he walks up...
+ } else {
+ // You've been here before.
+ _animation->appearPed(1, 3); // He's standing in your way straight away...
+ spr1->_facingDir = kDirLeft;
+ }
+ }
+ break;
+
+ case kRoomArgentRoad:
+ if ((_cwytalotGone) && (!_passedCwytalotInHerts) && (ped == 2) && (_roomCount[kRoomArgentRoad] > 3)) {
+ AnimationType *spr1 = _animation->_sprites[1];
+ spr1->init(4, false); // 4 = Cwytalot again
+ _animation->appearPed(1, 0);
+ spr1->walkTo(1);
+ spr1->_vanishIfStill = true;
+ _passedCwytalotInHerts = true;
+ // whereis[#157] = r__Nowhere; // can we fit this in?
+ _timer->addTimer(20, Timer::kProcCwytalotInHerts, Timer::kReasonCwytalotInHerts);
+ }
+ break;
+
+ case kRoomBridge:
+ if (_drawbridgeOpen == 4) { // open
+ _background->draw(-1, -1, 2); // Position of drawbridge
+ _graphics->refreshBackground();
+ _magics[kColorGreen - 1]._operation = kMagicNothing; // You may enter the drawbridge.
+ }
+ if (_geidaFollows)
+ putGeidaAt(ped + 2, ped); // load Geida
+ break;
+
+ case kRoomRobins:
+ if ((ped > 0) && (!_beenTiedUp)) {
+ // A welcome party... or maybe not...
+ AnimationType *spr1 = _animation->_sprites[1];
+ spr1->init(6, false);
+ _animation->appearPed(1, 1);
+ spr1->walkTo(2);
+ _timer->addTimer(36, Timer::kProcGetTiedUp, Timer::kReasonGettingTiedUp);
+ }
+
+ if (_beenTiedUp) {
+ _whereIs[kPeopleRobinHood - 150] = kRoomNowhere;
+ _whereIs[kPeopleFriarTuck - 150] = kRoomNowhere;
+ }
+
+ if (_tiedUp)
+ _background->draw(-1, -1, 1);
+
+ if (!_mushroomGrowing)
+ _background->draw(-1, -1, 2);
+ _graphics->refreshBackground();
+ break;
+
+ case kRoomOutsideCardiffCastle:
+ if (ped > 0) {
+ AnimationType *spr1 = _animation->_sprites[1];
+ switch (_cardiffQuestionNum) {
+ case 0 : // You've answered NONE of his questions.
+ spr1->init(9, false);
+ _animation->appearPed(1, 1);
+ spr1->walkTo(2);
+ _timer->addTimer(47, Timer::kProcCardiffSurvey, Timer::kReasonCardiffsurvey);
+ break;
+ case 5 :
+ _magics[1]._operation = kMagicNothing;
+ break; // You've answered ALL his questions. => nothing happens.
+ default: // You've answered SOME of his questions.
+ spr1->init(9, false);
+ _animation->appearPed(1, 2);
+ spr1->_facingDir = kDirRight;
+ _timer->addTimer(3, Timer::kProcCardiffReturn, Timer::kReasonCardiffsurvey);
+ }
+ }
+
+ if (_cardiffQuestionNum < 5)
+ _interrogation = _cardiffQuestionNum;
+ else
+ _interrogation = 0;
+ break;
+
+ case kRoomMap:
+ // You're entering the map.
+ fadeIn();
+ if (ped > 0)
+ _graphics->zoomOut(_peds[ped - 1]._x, _peds[ped - 1]._y);
+
+ if ((_objects[kObjectWine - 1]) && (_wineState != 3)) {
+ _dialogs->displayScrollChain('Q', 9); // Don't want to waste the wine!
+ _objects[kObjectWine - 1] = false;
+ refreshObjectList();
+ }
+
+ _dialogs->displayScrollChain('Q', 69);
+ break;
+
+ case kRoomCatacombs:
+ if ((ped == 0) || (ped == 3) || (ped == 5) || (ped == 6)) {
+
+ switch (ped) {
+ case 3: // Enter from oubliette
+ _catacombX = 8;
+ _catacombY = 4;
+ break;
+ case 5: // Enter from du Lustie's
+ _catacombX = 8;
+ _catacombY = 7;
+ break;
+ case 6: // Enter from Geida's
+ _catacombX = 4;
+ _catacombY = 1;
+ break;
+ }
+
+ _enterCatacombsFromLustiesRoom = true;
+ _animation->catacombMove(ped);
+ _enterCatacombsFromLustiesRoom = false;
+ }
+ break;
+
+ case kRoomArgentPub:
+ if (_wonNim)
+ _background->draw(-1, -1, 0); // No lute by the settle.
+ _malagauche = 0; // Ready to boot Malagauche
+ if (_givenBadgeToIby) {
+ _background->draw(-1, -1, 7);
+ _background->draw(-1, -1, 8);
+ }
+ _graphics->refreshBackground();
+ break;
+
+ case kRoomLustiesRoom:
+ _npcFacing = 1; // du Lustie.
+ if (_animation->getAvvyClothes() == 0) // Avvy in his normal clothes
+ _timer->addTimer(3, Timer::kProcCallsGuards, Timer::kReasonDuLustieTalks);
+ else if (!_enteredLustiesRoomAsMonk) // already
+ // Presumably, Avvy dressed as a monk.
+ _timer->addTimer(3, Timer::kProcGreetsMonk, Timer::kReasonDuLustieTalks);
+
+ if (_geidaFollows) {
+ putGeidaAt(4, ped);
+ if (_lustieIsAsleep) {
+ _background->draw(-1, -1, 4);
+ _graphics->refreshBackground();
+ }
+ }
+ break;
+
+ case kRoomMusicRoom:
+ if (_jacquesState > 0) {
+ _jacquesState = 5;
+ _background->draw(-1, -1, 1);
+ _graphics->refreshBackground();
+ _background->draw(-1, -1, 3);
+ _magics[kColorBrown - 1]._operation = kMagicNothing;
+ _whereIs[kPeopleJacques - 150] = kRoomNowhere;
+ }
+ if (ped != 0) {
+ _background->draw(-1, -1, 5);
+ _graphics->refreshBackground();
+ _sequence->startMusicRoomSeq();
+ }
+ break;
+
+ case kRoomOutsideNottsPub:
+ if (ped == 2) {
+ _background->draw(-1, -1, 2);
+ _graphics->refreshBackground();
+ _sequence->startDuckSeq();
+ }
+ break;
+
+ case kRoomOutsideArgentPub:
+ if (ped == 2) {
+ _background->draw(-1, -1, 5);
+ _graphics->refreshBackground();
+ _sequence->startMusicRoomSeq();
+ }
+ break;
+
+ case kRoomWiseWomans: {
+ AnimationType *spr1 = _animation->_sprites[1];
+ spr1->init(11, false);
+ if ((_roomCount[kRoomWiseWomans] == 1) && (ped > 0)) {
+ _animation->appearPed(1, 1); // Start on the right-hand side of the screen.
+ spr1->walkTo(3); // Walks up to greet you.
+ } else {
+ _animation->appearPed(1, 3); // Starts where she was before.
+ spr1->_facingDir = kDirLeft;
+ }
+
+ spr1->_callEachStepFl = true;
+ spr1->_eachStepProc = Animation::kProcFaceAvvy; // She always faces Avvy.
+ }
+ break;
+
+ case kRoomInsideCardiffCastle:
+ if (ped > 0) {
+ _animation->_sprites[1]->init(10, false); // Define the dart.
+ _background->draw(-1, -1, 0);
+ _graphics->refreshBackground();
+ _sequence->startCardiffSeq2();
+ } else {
+ _background->draw(-1, -1, 0);
+ if (_arrowInTheDoor)
+ _background->draw(-1, -1, 2);
+ else
+ _background->draw(-1, -1, 1);
+ _graphics->refreshBackground();
+ }
+ break;
+
+ case kRoomAvvysGarden:
+ if (ped == 1) {
+ _background->draw(-1, -1, 1);
+ _graphics->refreshBackground();
+ _sequence->startGardenSeq();
+ }
+ break;
+
+ case kRoomEntranceHall:
+ case kRoomInsideAbbey:
+ case kRoomYourHall:
+ if (ped == 2) {
+#if 0
+ // It was the original:
+ _celer->show_one(-1, -1, 2);
+ _sequence->first_show(1);
+ _sequence->then_show(3);
+ _sequence->start_to_close();
+#endif
+
+ _background->draw(-1, -1, 1);
+ _graphics->refreshBackground();
+ _sequence->startGardenSeq();
+ }
+ break;
+
+ case kRoomAylesOffice:
+ if (_aylesIsAwake)
+ _background->draw(-1, -1, 1);
+ _graphics->refreshBackground();
+ break; // Ayles awake.
+
+ case kRoomGeidas:
+ putGeidaAt(1, ped);
+ break; // load Geida
+
+ case kRoomEastHall:
+ case kRoomWestHall:
+ if (_geidaFollows)
+ putGeidaAt(ped + 1, ped);
+ break;
+
+ case kRoomLusties:
+ if (_geidaFollows)
+ putGeidaAt(ped + 5, ped);
+ break;
+
+ case kRoomNottsPub:
+ if (_sittingInPub)
+ _background->draw(-1, -1, 2);
+ _npcFacing = 1; // Port.
+ break;
+
+ case kRoomOutsideDucks:
+ if (ped == 2) {
+ // Shut the door
+ _background->draw(-1, -1, 2);
+ _graphics->refreshBackground();
+ _sequence->startDuckSeq();
+ }
+ break;
+
+ case kRoomDucks:
+ _npcFacing = 1; // Duck.
+ break;
+
+ default:
+ break;
+ }
+
+ _seeScroll = false; // Now it can work again!
+}
+
+void AvalancheEngine::thinkAbout(byte object, bool type) {
+ _thinks = object;
+ object--;
+
+ Common::String filename;
+ if (type == kThing) {
+ filename = "thinks.avd";
+ } else { // kPerson
+ filename = "folk.avd";
+
+ object -= 149;
+ if (object >= 25)
+ object -= 8;
+ if (object == 20)
+ object--; // Last time...
+ }
+
+ _graphics->loadMouse(kCurWait);
+ CursorMan.showMouse(false);
+ _graphics->drawThinkPic(filename, object);
+ CursorMan.showMouse(true);
+
+ _thinkThing = type;
+}
+
+void AvalancheEngine::drawToolbar() {
+ _graphics->drawToolbar();
+ _animation->setOldDirection(kDirNone);
+ drawDirection();
+}
+
+void AvalancheEngine::drawScore() {
+ uint16 score = _dnascore;
+ int8 numbers[3] = {0, 0, 0};
+ for (int i = 0; i < 2; i++) {
+ byte divisor = 1;
+ for (int j = 0; j < (2 - i); j++)
+ divisor *= 10;
+ numbers[i] = score / divisor;
+ score -= numbers[i] * divisor;
+ }
+ numbers[2] = score;
+
+ CursorMan.showMouse(false);
+
+ for (int i = 0; i < 3; i++) {
+ if (_scoreToDisplay[i] != numbers[i])
+ _graphics->drawDigit(numbers[i], 250 + (i + 1) * 15, 177);
+ }
+
+ CursorMan.showMouse(true);
+
+ for (int i = 0; i < 3; i++)
+ _scoreToDisplay[i] = numbers[i];
+}
+
+void AvalancheEngine::incScore(byte num) {
+ for (int i = 1; i <= num; i++) {
+ _dnascore++;
+
+ if (_soundFx) {
+ for (int j = 1; j <= 97; j++)
+ // Length os 2 is a guess, the original doesn't have a delay specified
+ _sound->playNote(177 + _dnascore * 3, 2);
+ }
+ }
+ warning("STUB: points()");
+
+ drawScore();
+}
+
+void AvalancheEngine::useCompass(const Common::Point &cursorPos) {
+ byte color = _graphics->getScreenColor(cursorPos);
+
+ switch (color) {
+ case kColorGreen:
+ _animation->setDirection(kDirUp);
+ _animation->setMoveSpeed(0, kDirUp);
+ drawDirection();
+ break;
+ case kColorBrown:
+ _animation->setDirection(kDirDown);
+ _animation->setMoveSpeed(0, kDirDown);
+ drawDirection();
+ break;
+ case kColorCyan:
+ _animation->setDirection(kDirLeft);
+ _animation->setMoveSpeed(0, kDirLeft);
+ drawDirection();
+ break;
+ case kColorLightmagenta:
+ _animation->setDirection(kDirRight);
+ _animation->setMoveSpeed(0, kDirRight);
+ drawDirection();
+ break;
+ case kColorRed:
+ case kColorWhite:
+ case kColorLightcyan:
+ case kColorYellow: // Fall-throughs are intended.
+ _animation->stopWalking();
+ drawDirection();
+ break;
+ }
+}
+
+void AvalancheEngine::fxToggle() {
+ warning("STUB: fxtoggle()");
+}
+
+void AvalancheEngine::refreshObjectList() {
+ _carryNum = 0;
+ if (_thinkThing && !_objects[_thinks - 1])
+ thinkAbout(kObjectMoney, kThing); // you always have money
+
+ for (int i = 0; i < kObjectNum; i++) {
+ if (_objects[i]) {
+ _objectList[_carryNum] = i + 1;
+ _carryNum++;
+ }
+ }
+}
+
+/**
+ * @remarks Originally called 'verte'
+ */
+void AvalancheEngine::guideAvvy(Common::Point cursorPos) {
+ if (!_userMovesAvvy)
+ return;
+
+ cursorPos.y /= 2;
+ byte what;
+
+ // _animation->tr[0] is Avalot.)
+ AnimationType *avvy = _animation->_sprites[0];
+ if (cursorPos.x < avvy->_x)
+ what = 1;
+ else if (cursorPos.x > (avvy->_x + avvy->_xLength))
+ what = 2;
+ else
+ what = 0; // On top
+
+ if (cursorPos.y < avvy->_y)
+ what += 3;
+ else if (cursorPos.y > (avvy->_y + avvy->_yLength))
+ what += 6;
+
+ switch (what) {
+ case 0:
+ _animation->stopWalking();
+ break; // Clicked on Avvy: no movement.
+ case 1:
+ _animation->setMoveSpeed(0, kDirLeft);
+ break;
+ case 2:
+ _animation->setMoveSpeed(0, kDirRight);
+ break;
+ case 3:
+ _animation->setMoveSpeed(0, kDirUp);
+ break;
+ case 4:
+ _animation->setMoveSpeed(0, kDirUpLeft);
+ break;
+ case 5:
+ _animation->setMoveSpeed(0, kDirUpRight);
+ break;
+ case 6:
+ _animation->setMoveSpeed(0, kDirDown);
+ break;
+ case 7:
+ _animation->setMoveSpeed(0, kDirDownLeft);
+ break;
+ case 8:
+ _animation->setMoveSpeed(0, kDirDownRight);
+ break;
+ } // No other values are possible.
+
+ drawDirection();
+}
+
+void AvalancheEngine::checkClick() {
+ Common::Point cursorPos = getMousePos();
+
+ /*if (mrelease > 0)
+ after_the_scroll = false;*/
+
+ if ((0 <= cursorPos.y) && (cursorPos.y <= 21))
+ _graphics->loadMouse(kCurUpArrow); // up arrow
+ else if ((317 <= cursorPos.y) && (cursorPos.y <= 339))
+ _graphics->loadMouse(kCurIBeam); //I-beam
+ else if ((340 <= cursorPos.y) && (cursorPos.y <= 399))
+ _graphics->loadMouse(kCurScrewDriver); // screwdriver
+ else if (!_menu->isActive()) { // Dropdown can handle its own pointers.
+ if (_holdLeftMouse) {
+ _graphics->loadMouse(kCurCrosshair); // Mark's crosshairs
+ guideAvvy(cursorPos); // Normally, if you click on the picture, you're guiding Avvy around.
+ } else
+ _graphics->loadMouse(kCurFletch); // fletch
+ }
+
+ if (_holdLeftMouse) {
+ if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) { // Click on the dropdown menu.
+ if (_dropsOk)
+ _menu->update();
+ } else if ((317 <= cursorPos.y) && (cursorPos.y <= 339)) { // Click on the command line.
+ _parser->_inputTextPos = (cursorPos.x - 23) / 8;
+ if (_parser->_inputTextPos > _parser->_inputText.size() + 1)
+ _parser->_inputTextPos = _parser->_inputText.size() + 1;
+ if (_parser->_inputTextPos < 1)
+ _parser->_inputTextPos = 1;
+ _parser->_inputTextPos--;
+ _parser->plotText();
+ } else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) { // Check the toolbar.
+ if ((137 <= cursorPos.x) && (cursorPos.x <= 207)) { // Control Avvy with the compass.
+ if (_alive && _avvyIsAwake)
+ useCompass(cursorPos);
+ } else if ((208 <= cursorPos.x) && (cursorPos.x <= 260)) { // Examine the _thing.
+ do {
+ updateEvents();
+ } while (_holdLeftMouse);
+
+ if (_thinkThing) {
+ _parser->_thing = _thinks;
+ _parser->_thing += 49;
+ _parser->_person = kPeoplePardon;
+ } else {
+ _parser->_person = (People)_thinks;
+ _parser->_thing = _parser->kPardon;
+ }
+ callVerb(kVerbCodeExam);
+ } else if ((261 <= cursorPos.x) && (cursorPos.x <= 319)) { // Display the score.
+ do {
+ updateEvents();
+ } while (_holdLeftMouse);
+
+ callVerb(kVerbCodeScore);
+ } else if ((320 <= cursorPos.x) && (cursorPos.x <= 357)) { // Change speed.
+ _animation->_sprites[0]->_speedX = kWalk;
+ _animation->updateSpeed();
+ } else if ((358 <= cursorPos.x) && (cursorPos.x <= 395)) { // Change speed.
+ _animation->_sprites[0]->_speedX = kRun;
+ _animation->updateSpeed();
+ } else if ((396 <= cursorPos.x) && (cursorPos.x <= 483))
+ fxToggle();
+ else if ((535 <= cursorPos.x) && (cursorPos.x <= 640))
+ _mouseText.insertChar(kControlNewLine, 0);
+ } else if (!_dropsOk)
+ _mouseText = Common::String(13) + _mouseText;
+ }
+}
+
+void AvalancheEngine::errorLed() {
+ warning("STUB: errorled()");
+}
+
+/**
+ * Displays a fade out, full screen.
+ * This version is different to the one in the original, which was fading in 3 steps.
+ * @remarks Originally called 'dusk'
+ */
+void AvalancheEngine::fadeOut() {
+ byte pal[3], tmpPal[3];
+
+ _graphics->setBackgroundColor(kColorBlack);
+ if (_fxHidden)
+ return;
+ _fxHidden = true;
+
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ g_system->getPaletteManager()->grabPalette((byte *)tmpPal, j, 1);
+ _fxPal[i][j][0] = tmpPal[0];
+ _fxPal[i][j][1] = tmpPal[1];
+ _fxPal[i][j][2] = tmpPal[2];
+ if (tmpPal[0] >= 16)
+ pal[0] = tmpPal[0] - 16;
+ else
+ pal[0] = 0;
+
+ if (tmpPal[1] >= 16)
+ pal[1] = tmpPal[1] - 16;
+ else
+ pal[1] = 0;
+
+ if (tmpPal[2] >= 16)
+ pal[2] = tmpPal[2] - 16;
+ else
+ pal[2] = 0;
+
+ g_system->getPaletteManager()->setPalette(pal, j, 1);
+ }
+ _system->delayMillis(10);
+ _graphics->refreshScreen();
+ }
+}
+
+/**
+ * Displays a fade in, full screen.
+ * This version is different to the one in the original, which was fading in 3 steps.
+ * @remarks Originally called 'dawn'
+ */
+void AvalancheEngine::fadeIn() {
+ if (_holdTheDawn || !_fxHidden)
+ return;
+
+ _fxHidden = false;
+
+ byte pal[3];
+ for (int i = 15; i >= 0; i--) {
+ for (int j = 0; j < 16; j++) {
+ pal[0] = _fxPal[i][j][0];
+ pal[1] = _fxPal[i][j][1];
+ pal[2] = _fxPal[i][j][2];
+ g_system->getPaletteManager()->setPalette(pal, j, 1);
+ }
+ _system->delayMillis(10);
+ _graphics->refreshScreen();
+ }
+
+ if ((_room == kRoomYours) && _avvyInBed && _teetotal)
+ _graphics->setBackgroundColor(kColorYellow);
+}
+
+void AvalancheEngine::drawDirection() { // It's data is loaded in load_digits().
+ if (_animation->getOldDirection() == _animation->getDirection())
+ return;
+
+ _animation->setOldDirection(_animation->getDirection());
+
+ CursorMan.showMouse(false);
+ _graphics->drawDirection(_animation->getDirection(), 0, 161);
+ CursorMan.showMouse(true);
+}
+
+void AvalancheEngine::gameOver() {
+ _userMovesAvvy = false;
+
+ AnimationType *avvy = _animation->_sprites[0];
+ int16 sx = avvy->_x;
+ int16 sy = avvy->_y;
+
+ avvy->remove();
+ avvy->init(12, true); // 12 = Avalot falls
+ avvy->_stepNum = 0;
+ avvy->appear(sx, sy, kDirUp);
+
+ _timer->addTimer(3, Timer::kProcAvalotFalls, Timer::kReasonFallingOver);
+ _alive = false;
+}
+
+void AvalancheEngine::minorRedraw() {
+ fadeOut();
+
+ enterRoom(_room, 0); // Ped unknown or non-existant.
+
+ for (int i = 0; i < 3; i++)
+ _scoreToDisplay[i] = -1; // impossible digits
+ drawScore();
+
+ fadeIn();
+}
+
+void AvalancheEngine::majorRedraw() {
+ warning("STUB: major_redraw()");
+}
+
+uint16 AvalancheEngine::bearing(byte whichPed) {
+ AnimationType *avvy = _animation->_sprites[0];
+ PedType *curPed = &_peds[whichPed];
+
+ if (avvy->_x == curPed->_x)
+ return 0;
+
+ int16 deltaX = avvy->_x - curPed->_x;
+ int16 deltaY = avvy->_y - curPed->_y;
+ uint16 result = (uint16)(atan((float)(deltaY / deltaX)) * 180 / M_PI);
+ if (avvy->_x < curPed->_x) {
+ return result + 90;
+ } else {
+ return result + 270;
+ }
+}
+
+/**
+ * @remarks Originally called 'sprite_run'
+ */
+void AvalancheEngine::spriteRun() {
+ _doingSpriteRun = true;
+ _animation->animLink();
+ _doingSpriteRun = false;
+}
+
+// CHECKME: Unused function
+void AvalancheEngine::fixFlashers() {
+ _ledStatus = 177;
+ _animation->setOldDirection(kDirNone);
+ _dialogs->setReadyLight(2);
+ drawDirection();
+}
+
+Common::String AvalancheEngine::intToStr(int32 num) {
+ return Common::String::format("%d", num);
+}
+
+void AvalancheEngine::resetVariables() {
+ _animation->setDirection(kDirUp);
+ _carryNum = 0;
+ for (int i = 0; i < kObjectNum; i++)
+ _objects[i] = false;
+
+ _dnascore = 0;
+ _money = 0;
+ _room = kRoomNowhere;
+ _saveNum = 0;
+ for (int i = 0; i < 100; i++)
+ _roomCount[i] = 0;
+
+ _wonNim = false;
+ _wineState = 0;
+ _cwytalotGone = false;
+ _passwordNum = 0;
+ _aylesIsAwake = false;
+ _drawbridgeOpen = 0;
+ _avariciusTalk = 0;
+ _rottenOnion = false;
+ _onionInVinegar = false;
+ _givenToSpludwick = 0;
+ _brummieStairs = 0;
+ _cardiffQuestionNum = 0;
+ _passedCwytalotInHerts = false;
+ _avvyIsAwake = false;
+ _avvyInBed = false;
+ _userMovesAvvy = false;
+ _npcFacing = 0;
+ _givenBadgeToIby = false;
+ _friarWillTieYouUp = false;
+ _tiedUp = false;
+ _boxContent = 0;
+ _talkedToCrapulus = false;
+ _jacquesState = 0;
+ _bellsAreRinging = false;
+ _standingOnDais = false;
+ _takenPen = false;
+ _arrowInTheDoor = false;
+ _favoriteDrink = "";
+ _favoriteSong = "";
+ _worstPlaceOnEarth = "";
+ _spareEvening = "";
+ _totalTime = 0;
+ _jumpStatus = 0;
+ _mushroomGrowing = false;
+ _spludwickAtHome = false;
+ _lastRoom = kRoomDummy;
+ _lastRoomNotMap = kRoomDummy;
+ _crapulusWillTell = false;
+ _enterCatacombsFromLustiesRoom = false;
+ _teetotal = false;
+ _malagauche = 0;
+ _drinking = 0;
+ _enteredLustiesRoomAsMonk = false;
+ _catacombX = 0;
+ _catacombY = 0;
+ _avvysInTheCupboard = false;
+ _geidaFollows = false;
+ _givenPotionToGeida = false;
+ _lustieIsAsleep = false;
+ _beenTiedUp = false;
+ _sittingInPub = false;
+ _spurgeTalkCount = 0;
+ _metAvaroid = false;
+ _takenMushroom = false;
+ _givenPenToAyles = false;
+ _askedDogfoodAboutNim = false;
+ _startTime = getTimeInSeconds();
+
+ _parser->resetVariables();
+ _nim->resetVariables();
+ _animation->resetVariables();
+ _sequence->resetVariables();
+ _background->resetVariables();
+ _menu->resetVariables();
+ _timer->resetVariables();
+}
+
+void AvalancheEngine::newGame() {
+ for (int i = 0; i < kMaxSprites; i++) {
+ AnimationType *spr = _animation->_sprites[i];
+ if (spr->_quick)
+ spr->remove();
+ }
+ // Deallocate sprite. Sorry, beta testers!
+
+ AnimationType *avvy = _animation->_sprites[0];
+ avvy->init(0, true);
+
+ _alive = true;
+ resetVariables();
+
+ _dialogs->setBubbleStateNatural();
+
+ _spareEvening = "answer a questionnaire";
+ _favoriteDrink = "beer";
+ _money = 30; // 2/6
+ _animation->setDirection(kDirStopped);
+ _parser->_wearing = kObjectClothes;
+ _objects[kObjectMoney - 1] = true;
+ _objects[kObjectBodkin - 1] = true;
+ _objects[kObjectBell - 1] = true;
+ _objects[kObjectClothes - 1] = true;
+
+ _thinkThing = true;
+ _thinks = 2;
+ refreshObjectList();
+ _seeScroll = false;
+
+ avvy->appear(300, 117, kDirRight); // Needed to initialize Avalot.
+ //for (gd = 0; gd <= 30; gd++) for (gm = 0; gm <= 1; gm++) also[gd][gm] = nil;
+ // fillchar(previous^,sizeof(previous^),#0); { blank out array }
+ _him = kPeoplePardon;
+ _her = kPeoplePardon;
+ _it = Parser::kPardon;
+ _passwordNum = _rnd->getRandomNumber(29) + 1; //Random(30) + 1;
+ _userMovesAvvy = false;
+ _doingSpriteRun = false;
+ _avvyInBed = true;
+
+ _isLoaded = false;
+
+ enterRoom(kRoomYours, 1);
+ avvy->_visible = false;
+ drawScore();
+ _menu->setup();
+ _clock->update();
+ spriteRun();
+}
+
+bool AvalancheEngine::getFlag(char x) {
+ for (uint16 i = 0; i < _flags.size(); i++) {
+ if (_flags[i] == x)
+ return true;
+ }
+
+ return false;
+}
+
+bool AvalancheEngine::decreaseMoney(uint16 amount) {
+ _money -= amount;
+ if (_money < 0) {
+ _dialogs->displayScrollChain('Q', 2); // "You are now denariusless!"
+ gameOver();
+ return false;
+ } else
+ return true;
+}
+
+Common::String AvalancheEngine::getName(People whose) {
+ static const char lads[17][20] = {
+ "Avalot", "Spludwick", "Crapulus", "Dr. Duck", "Malagauche",
+ "Friar Tuck", "Robin Hood", "Cwytalot", "du Lustie", "the Duke of Cardiff",
+ "Dogfood", "A trader", "Ibythneth", "Ayles", "Port",
+ "Spurge", "Jacques"
+ };
+
+ static const char lasses[4][15] = {"Arkata", "Geida", "\0xB1", "the Wise Woman"};
+
+ if (whose <= kPeopleJacques)
+ return Common::String(lads[whose - kPeopleAvalot]);
+ else if ((whose >= kPeopleArkata) && (whose <= kPeopleWisewoman))
+ return Common::String(lasses[whose - kPeopleArkata]);
+ else
+ error("getName() - Unexpected character id %d", (byte) whose);
+}
+
+Common::String AvalancheEngine::getItem(byte which) {
+ static const char items[kObjectNum][18] = {
+ "some wine", "your money-bag", "your bodkin", "a potion", "a chastity belt",
+ "a crossbow bolt", "a crossbow", "a lute", "a pilgrim's badge", "a mushroom",
+ "a key", "a bell", "a scroll", "a pen", "some ink",
+ "your clothes", "a habit", "an onion"
+ };
+
+ Common::String result;
+ if (which > 150)
+ which -= 149;
+
+ switch (which) {
+ case kObjectWine:
+ switch (_wineState) {
+ case 0:
+ case 1:
+ case 4:
+ result = Common::String(items[which - 1]);
+ break;
+ case 3:
+ result = "some vinegar";
+ break;
+ }
+ break;
+ case kObjectOnion:
+ if (_rottenOnion)
+ result = "a rotten onion";
+ else if (_onionInVinegar)
+ result = "a pickled onion (in the vinegar)";
+ else
+ result = Common::String(items[which - 1]);
+ break;
+ default:
+ if ((which < kObjectNum) && (which > 0))
+ result = Common::String(items[which - 1]);
+ else
+ result = "";
+ }
+ return result;
+}
+
+Common::String AvalancheEngine::f5Does() {
+ switch (_room) {
+ case kRoomYours:
+ if (!_avvyIsAwake)
+ return Common::String::format("%cWWake up", kVerbCodeWake);
+ else if (_avvyInBed)
+ return Common::String::format("%cGGet up", kVerbCodeStand);
+ break;
+ case kRoomInsideCardiffCastle:
+ if (_standingOnDais)
+ return Common::String::format("%cCClimb down", kVerbCodeClimb);
+ else
+ return Common::String::format("%cCClimb up", kVerbCodeClimb);
+ break;
+ case kRoomNottsPub:
+ if (_sittingInPub)
+ return Common::String::format("%cSStand up", kVerbCodeStand);
+ else
+ return Common::String::format("%cSSit down", kVerbCodeSit);
+ break;
+ case kRoomMusicRoom:
+ if (_animation->inField(5))
+ return Common::String::format("%cPPlay the harp", kVerbCodePlay);
+ break;
+ default:
+ break;
+ }
+
+ return Common::String::format("%c", kVerbCodePardon); // If all else fails...
+}
+
+void AvalancheEngine::flipRoom(Room room, byte ped) {
+ assert((ped > 0) && (ped < 15));
+ if (!_alive) {
+ // You can't leave the room if you're dead.
+ _animation->_sprites[0]->_moveX = 0;
+ _animation->_sprites[0]->_moveY = 0; // Stop him from moving.
+ return;
+ }
+
+ if ((room == kRoomDummy) && (_room == kRoomLusties)) {
+ _animation->hideInCupboard();
+ return;
+ }
+
+ if ((_jumpStatus > 0) && (_room == kRoomInsideCardiffCastle)) {
+ // You can't *jump* out of Cardiff Castle!
+ _animation->_sprites[0]->_moveX = 0;
+ return;
+ }
+
+ exitRoom(_room);
+ fadeOut();
+
+ for (int16 i = 1; i < _animation->kSpriteNumbMax; i++) {
+ if (_animation->_sprites[i]->_quick)
+ _animation->_sprites[i]->remove();
+ } // Deallocate sprite
+
+ if (_room == kRoomLustiesRoom)
+ _enterCatacombsFromLustiesRoom = true;
+
+ if (room > kRoomMap)
+ return;
+
+ enterRoom(room, ped);
+ _animation->appearPed(0, ped - 1);
+ _enterCatacombsFromLustiesRoom = false;
+ _animation->setOldDirection(_animation->getDirection());
+ _animation->setDirection(_animation->_sprites[0]->_facingDir);
+ drawDirection();
+
+ fadeIn();
+}
+
+/**
+ * Open the Door.
+ * This slides the door open. The data really ought to be saved in
+ * the Also file, and will be next time. However, for now, they're
+ * here.
+ * @remarks Originally called 'open_the_door'
+ */
+void AvalancheEngine::openDoor(Room whither, byte ped, byte magicnum) {
+ switch (_room) {
+ case kRoomOutsideYours:
+ case kRoomOutsideNottsPub:
+ case kRoomOutsideDucks:
+ _sequence->startOutsideSeq(whither, ped);
+ break;
+ case kRoomInsideCardiffCastle:
+ _sequence->startCardiffSeq(whither, ped);
+ break;
+ case kRoomAvvysGarden:
+ case kRoomEntranceHall:
+ case kRoomInsideAbbey:
+ case kRoomYourHall:
+ _sequence->startHallSeq(whither, ped);
+ break;
+ case kRoomMusicRoom:
+ case kRoomOutsideArgentPub:
+ _sequence->startMusicRoomSeq2(whither, ped);
+ break;
+ case kRoomLusties:
+ switch (magicnum) {
+ case 14:
+ if (_avvysInTheCupboard) {
+ _animation->hideInCupboard();
+ _sequence->startCupboardSeq();
+ return;
+ } else {
+ _animation->appearPed(0, 5);
+ _animation->_sprites[0]->_facingDir = kDirRight;
+ _sequence->startLustiesSeq2(whither, ped);
+ }
+ break;
+ case 12:
+ _sequence->startLustiesSeq3(whither, ped);
+ break;
+ }
+ break;
+ default:
+ _sequence->startDummySeq(whither, ped);
+ }
+}
+
+void AvalancheEngine::setRoom(People persId, Room roomId) {
+ _whereIs[persId - kPeopleAvalot] = roomId;
+}
+
+Room AvalancheEngine::getRoom(People persId) {
+ return _whereIs[persId - kPeopleAvalot];
+}
+} // End of namespace Avalanche
diff --git a/engines/avalanche/avalot.h b/engines/avalanche/avalot.h
new file mode 100644
index 0000000000..f50ad28bc4
--- /dev/null
+++ b/engines/avalanche/avalot.h
@@ -0,0 +1,104 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* AVALOT The kernel of the program. */
+
+#ifndef AVALANCHE_AVALOT_H
+#define AVALANCHE_AVALOT_H
+
+#include "avalanche/animation.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Clock {
+public:
+ Clock(AvalancheEngine *vm);
+
+ void update();
+
+private:
+ static const int kCenterX = 510;
+ static const int kCenterY = 183;
+
+ AvalancheEngine *_vm;
+
+ uint16 _hour, _minute, _second, _hourAngle, _oldHour, _oldMinute, _oldHourAngle;
+ Common::Point _clockHandHour, _clockHandMinute;
+
+ Common::Point calcHand(uint16 angle, uint16 length, Color color);
+ void drawHand(const Common::Point &endPoint, Color color);
+ void plotHands();
+ void chime();
+};
+
+static const byte kObjectNum = 18; // always preface with a #
+static const int16 kCarryLimit = 12; // carry limit
+
+static const int16 kNumlockCode = 32; // Code for Num Lock
+static const int16 kMouseSize = 134;
+
+struct PedType {
+ int16 _x, _y;
+ Direction _direction;
+};
+
+struct MagicType {
+ byte _operation; // one of the operations
+ uint16 _data; // data for them
+};
+
+struct FieldType {
+ int16 _x1, _y1, _x2, _y2;
+};
+
+struct LineType : public FieldType {
+ Color _color;
+};
+
+typedef int8 TuneType[31];
+
+struct QuasipedType {
+ byte _whichPed;
+ Color _textColor;
+ Room _room;
+ Color _backgroundColor;
+ People _who;
+};
+
+#if 0
+struct Sundry { // Things which must be saved over a backtobootstrap, outside DNA.
+ Common::String _qEnidFilename;
+ bool _qSoundFx;
+ byte _qThinks;
+ bool _qThinkThing;
+};
+#endif
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_AVALOT_H
diff --git a/engines/avalanche/background.cpp b/engines/avalanche/background.cpp
new file mode 100644
index 0000000000..5d168a20af
--- /dev/null
+++ b/engines/avalanche/background.cpp
@@ -0,0 +1,370 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: CELER The unit for updating the screen pics. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/background.h"
+
+namespace Avalanche {
+
+const int16 Background::kOnDisk = -1;
+
+Background::Background(AvalancheEngine *vm) {
+ _vm = vm;
+ _spriteNum = 0;
+ _nextBell = 0;
+}
+
+Background::~Background() {
+ release();
+}
+
+/**
+ * @remarks Originally called 'pics_link'
+ */
+void Background::update() {
+ if (_vm->_menu->isActive())
+ return; // No animation when the menus are up.
+
+ switch (_vm->_room) {
+ case kRoomOutsideArgentPub:
+ if ((_vm->_roomCycles % 12) == 0)
+ draw(-1, -1, (_vm->_roomCycles / 12) % 4);
+ break;
+ case kRoomBrummieRoad:
+ if ((_vm->_roomCycles % 2) == 0)
+ draw(-1, -1, (_vm->_roomCycles / 2) % 4);
+ break;
+ case kRoomBridge:
+ if ((_vm->_roomCycles % 2) == 0)
+ draw(-1, -1, 3 + (_vm->_roomCycles / 2) % 4);
+ break;
+ case kRoomYours:
+ if ((!_vm->_avvyIsAwake) && ((_vm->_roomCycles % 4) == 0))
+ draw(-1, -1, (_vm->_roomCycles / 12) % 2);
+ break;
+ case kRoomArgentPub:
+ if (((_vm->_roomCycles % 7) == 1) && (_vm->_malagauche != 177)) {
+ // Malagauche cycle.
+ _vm->_malagauche++;
+ switch (_vm->_malagauche) {
+ case 1:
+ case 11:
+ case 21:
+ draw(-1, -1, 11); // Looks forwards.
+ break;
+ case 8:
+ case 18:
+ case 28:
+ case 32:
+ draw(-1, -1, 10); // Looks at you.
+ break;
+ case 30:
+ draw(-1, -1, 12); // Winks.
+ break;
+ case 33:
+ _vm->_malagauche = 0;
+ break;
+ }
+ }
+
+ switch (_vm->_roomCycles % 200) {
+ case 179:
+ case 197:
+ draw(-1, -1, 4); // Dogfood's drinking cycle.
+ break;
+ case 182:
+ case 194:
+ draw(-1, -1, 5);
+ break;
+ case 185:
+ draw(-1, -1, 6);
+ break;
+ case 199:
+ _vm->_npcFacing = 177; // Impossible value for this.
+ break;
+ default:
+ if (_vm->_roomCycles % 200 <= 178) { // Normally.
+ byte direction = 1;
+ uint16 angle = _vm->bearing(1);
+ if (((angle >= 1) && (angle <= 90)) || ((angle >= 358) && (angle <= 360)))
+ direction = 3;
+ else if ((angle >= 293) && (angle <= 357))
+ direction = 2;
+ else if ((angle >= 270) && (angle <= 292))
+ direction = 4;
+
+ if (direction != _vm->_npcFacing) { // Dogfood.
+ draw(-1, -1, direction - 1);
+ _vm->_npcFacing = direction;
+ }
+ }
+ }
+ break;
+ case kRoomWestHall:
+ if ((_vm->_roomCycles % 3) == 0) {
+ switch ((_vm->_roomCycles / 3) % 6) {
+ case 4:
+ draw(-1, -1, 0);
+ break;
+ case 1:
+ case 3:
+ case 5:
+ draw(-1, -1, 1);
+ break;
+ case 0:
+ case 2:
+ draw(-1, -1, 2);
+ break;
+ }
+ }
+ break;
+ case kRoomLustiesRoom:
+ if (!(_vm->_lustieIsAsleep)) {
+ byte direction = 0;
+ uint16 angle = _vm->bearing(1);
+ if ((_vm->_roomCycles % 45) > 42)
+ direction = 4; // du Lustie blinks.
+ // Bearing of Avvy from du Lustie.
+ else if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
+ direction = 1; // Middle.
+ else if ((angle >= 45) && (angle <= 180))
+ direction = 2; // Left.
+ else if ((angle >= 181) && (angle <= 314))
+ direction = 3; // Right.
+
+ if (direction != _vm->_npcFacing) { // du Lustie.
+ draw(-1, -1, direction - 1);
+ _vm->_npcFacing = direction;
+ }
+ }
+ break;
+ case kRoomAylesOffice:
+ if ((!_vm->_aylesIsAwake) && (_vm->_roomCycles % 14 == 0)) {
+ switch ((_vm->_roomCycles / 14) % 2) {
+ case 0:
+ draw(-1, -1, 0); // Frame 2: EGA.
+ break;
+ case 1:
+ draw(-1, -1, 2); // Frame 1: Natural.
+ break;
+ }
+ }
+ break;
+ case kRoomRobins:
+ if (_vm->_tiedUp) {
+ switch (_vm->_roomCycles % 54) {
+ case 20:
+ draw(-1, -1, 3); // Frame 4: Avalot blinks.
+ break;
+ case 23:
+ draw(-1, -1, 1); // Frame 1: Back to normal.
+ break;
+ }
+ }
+ break;
+ case kRoomNottsPub: {
+ // Bearing of Avvy from Port.
+ byte direction = 0;
+ uint16 angle = _vm->bearing(4);
+ if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
+ direction = 2; // Middle.
+ else if ((angle >= 45) && (angle <= 180))
+ direction = 6; // Left.
+ else if ((angle >= 181) && (angle <= 314))
+ direction = 8; // Right.
+
+ if ((_vm->_roomCycles % 60) > 57)
+ direction--; // Blinks.
+
+ if (direction != _vm->_npcFacing) { // Port.
+ draw(-1, -1, direction - 1);
+ _vm->_npcFacing = direction;
+ }
+
+ switch (_vm->_roomCycles % 50) {
+ case 45 :
+ draw(-1, -1, 8); // Spurge blinks.
+ break;
+ case 49 :
+ draw(-1, -1, 9);
+ break;
+ }
+ break;
+ }
+ case kRoomDucks: {
+ if ((_vm->_roomCycles % 3) == 0) // The fire flickers.
+ draw(-1, -1, (_vm->_roomCycles / 3) % 3);
+
+ // Bearing of Avvy from Duck.
+ byte direction = 0;
+ uint16 angle = _vm->bearing(1);
+ if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
+ direction = 4; // Middle.
+ else if ((angle >= 45) && (angle <= 180))
+ direction = 6; // Left.
+ else if ((angle >= 181) && (angle <= 314))
+ direction = 8; // Right.
+
+ if ((_vm->_roomCycles % 45) > 42)
+ direction++; // Duck blinks.
+
+ if (direction != _vm->_npcFacing) { // Duck.
+ draw(-1, -1, direction - 1);
+ _vm->_npcFacing = direction;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ((_vm->_bellsAreRinging) && (_vm->getFlag('B'))) {
+ // They're ringing the bells.
+ switch (_vm->_roomCycles % 4) {
+ case 1:
+ if (_nextBell < 5)
+ _nextBell = 12;
+ _nextBell--;
+ // CHECKME: 2 is a guess. No length in the original?
+ _vm->_sound->playNote(_vm->kNotes[_nextBell], 2);
+ break;
+ case 2:
+ _vm->_sound->stopSound();
+ break;
+ }
+ }
+}
+
+void Background::load(byte number) {
+ Common::File f;
+ _filename = _filename.format("chunk%d.avd", number);
+ if (!f.open(_filename))
+ return; // We skip because some rooms don't have sprites in the background.
+
+ f.seek(44);
+ _spriteNum = f.readByte();
+ for (int i = 0; i < _spriteNum; i++)
+ _offsets[i] = f.readSint32LE();
+
+ for (int i = 0; i < _spriteNum; i++) {
+ f.seek(_offsets[i]);
+
+ SpriteType sprite;
+ sprite._type = (PictureType)(f.readByte());
+ sprite._x = f.readSint16LE();
+ sprite._y = f.readSint16LE();
+ sprite._xl = f.readSint16LE();
+ sprite._yl = f.readSint16LE();
+ sprite._size = f.readSint32LE();
+ bool natural = f.readByte();
+ bool memorize = f.readByte();
+
+ if (memorize) {
+ _sprites[i]._x = sprite._x;
+ _sprites[i]._xl = sprite._xl;
+ _sprites[i]._y = sprite._y;
+ _sprites[i]._yl = sprite._yl;
+ _sprites[i]._type = sprite._type;
+
+ if (natural)
+ _vm->_graphics->getNaturalPicture(_sprites[i]);
+ else {
+ _sprites[i]._size = sprite._size;
+ _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._xl * 8, _sprites[i]._yl + 1);
+ }
+ } else
+ _sprites[i]._x = kOnDisk;
+ }
+ f.close();
+}
+
+void Background::release() {
+ for (int i = 0; i < _spriteNum; i++) {
+ if (_sprites[i]._x > kOnDisk)
+ _sprites[i]._picture.free();
+ }
+}
+
+/**
+ * Draw background animation
+ * @remarks Originally called 'show_one'
+ */
+void Background::draw(int16 destX, int16 destY, byte sprId) {
+ assert(sprId < 40);
+
+ if (_sprites[sprId]._x > kOnDisk) {
+ if (destX < 0) {
+ destX = _sprites[sprId]._x * 8;
+ destY = _sprites[sprId]._y;
+ }
+ drawSprite(destX, destY, _sprites[sprId]);
+ } else {
+ Common::File f;
+ if (!f.open(_filename)) // Filename was set in loadBackgroundSprites().
+ return; // We skip because some rooms don't have sprites in the background.
+
+ f.seek(_offsets[sprId]);
+
+ SpriteType sprite;
+ sprite._type = (PictureType)(f.readByte());
+ sprite._x = f.readSint16LE();
+ sprite._y = f.readSint16LE();
+ sprite._xl = f.readSint16LE();
+ sprite._yl = f.readSint16LE();
+ sprite._size = f.readSint32LE();
+ f.skip(2); // Natural and Memorize are used in Load()
+ sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._xl * 8, sprite._yl + 1);
+
+ if (destX < 0) {
+ destX = sprite._x * 8;
+ destY = sprite._y;
+ }
+ drawSprite(destX, destY, sprite);
+
+ sprite._picture.free();
+ f.close();
+ }
+}
+
+/**
+ * @remarks Originally called 'display_it'
+ */
+void Background::drawSprite(int16 x, int16 y, SpriteType &sprite) {
+ // These pictures are practically parts of the background. -10 is for the drop-down menu.
+ _vm->_graphics->drawBackgroundSprite(x, y - 10, sprite);
+}
+
+void Background::resetVariables() {
+ _nextBell = 0;
+}
+
+void Background::synchronize(Common::Serializer &sz) {
+ sz.syncAsByte(_nextBell);
+}
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/background.h b/engines/avalanche/background.h
new file mode 100644
index 0000000000..34d7a9a2cc
--- /dev/null
+++ b/engines/avalanche/background.h
@@ -0,0 +1,79 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: CELER The unit for updating the screen pics. */
+
+#ifndef AVALANCHE_BACKGROUND_H
+#define AVALANCHE_BACKGROUND_H
+
+#include "common/str.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+enum PictureType {kEga, kBgi, kNaturalImage};
+
+struct SpriteType {
+ PictureType _type;
+ int16 _x, _y;
+ int16 _xl, _yl;
+ int32 _size;
+ Graphics::Surface _picture;
+};
+
+class Background {
+public:
+ Background(AvalancheEngine *vm);
+ ~Background();
+
+ void update();
+ void load(byte number);
+ void release();
+
+ // Setting the destination to negative coordinates means the picture should be drawn to it's original position.
+ // If you give it positive values, the picture will be plotted to the desired coordinates on the screen.
+ // By that we get rid of show_one_at(), which would be almost identical and cause a lot of code duplication.
+ void draw(int16 destX, int16 destY, byte sprId);
+ void resetVariables();
+ void synchronize(Common::Serializer &sz);
+
+private:
+ AvalancheEngine *_vm;
+
+ byte _nextBell; // For the ringing.
+ int32 _offsets[40];
+ byte _spriteNum;
+ SpriteType _sprites[40];
+ Common::String _filename;
+ static const int16 kOnDisk; // Value of _sprites[fv]._x when it's not in memory.
+
+ void drawSprite(int16 x, int16 y, SpriteType &sprite);
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_BACKGROUND_H
diff --git a/engines/avalanche/closing.cpp b/engines/avalanche/closing.cpp
new file mode 100644
index 0000000000..1cb2e84218
--- /dev/null
+++ b/engines/avalanche/closing.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.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* CLOSING The closing screen and error handler. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/closing.h"
+
+#include "common/random.h"
+
+namespace Avalanche {
+
+Closing::Closing(AvalancheEngine *vm) {
+ _vm = vm;
+ warning("STUB: Closing::Closing()");
+}
+
+void Closing::getScreen(ScreenType which) {
+ warning("STUB: Closing::getScreen()");
+}
+
+void Closing::showScreen() {
+ warning("STUB: Closing::showScreen()");
+}
+
+void Closing::putIn(Common::String str, uint16 where) {
+ warning("STUB: Closing::putIn()");
+}
+
+void Closing::exitGame() {
+ static const char nouns[12][14] = {
+ "sackbut", "harpsichord", "camel", "conscience", "ice-cream", "serf",
+ "abacus", "castle", "carrots", "megaphone", "manticore", "drawbridge"
+ };
+
+ static const char verbs[12][12] = {
+ "haunt", "daunt", "tickle", "gobble", "erase", "provoke",
+ "surprise", "ignore", "stare at", "shriek at", "frighten", "quieten"
+ };
+
+ _vm->_sound->stopSound();
+
+ getScreen(kScreenNagScreen);
+ byte nounId = _vm->_rnd->getRandomNumber(11);
+ byte verbId = _vm->_rnd->getRandomNumber(11);
+ Common::String result = Common::String::format("%s will %s you", nouns[nounId], verbs[verbId]);
+ putIn(result, 1628);
+ showScreen(); // No halt- it's already set up.
+}
+
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/closing.h b/engines/avalanche/closing.h
new file mode 100644
index 0000000000..25217e347e
--- /dev/null
+++ b/engines/avalanche/closing.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.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* CLOSING The closing screen and error handler. */
+
+#ifndef AVALANCHE_CLOSING_H
+#define AVALANCHE_CLOSING_H
+
+#include "common/str.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Closing {
+public:
+ Closing(AvalancheEngine *vm);
+ void exitGame();
+
+private:
+ // Will be needed during implementation of Closing.
+ enum ScreenType {
+ kScreenBugAlert = 1,
+ kScreenRamCram = 2,
+ kScreenNagScreen = 3,
+ kScreenTwoCopies = 5
+ };
+
+ AvalancheEngine *_vm;
+
+ void getScreen(ScreenType which);
+ void showScreen();
+ void putIn(Common::String str, uint16 where);
+
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_CLOSING_H
diff --git a/engines/avalanche/configure.engine b/engines/avalanche/configure.engine
new file mode 100644
index 0000000000..28d6a558db
--- /dev/null
+++ b/engines/avalanche/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine avalanche "Lord Avalot d'Argent" no
diff --git a/engines/avalanche/console.cpp b/engines/avalanche/console.cpp
new file mode 100644
index 0000000000..e4b52116e4
--- /dev/null
+++ b/engines/avalanche/console.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/console.h"
+#include "avalanche/avalanche.h"
+
+namespace Avalanche {
+
+AvalancheConsole::AvalancheConsole(AvalancheEngine *vm) : GUI::Debugger(), _vm(vm) {
+ DCmd_Register("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines));
+}
+
+AvalancheConsole::~AvalancheConsole() {
+}
+
+/**
+ * This command loads up the specified new scene number
+ */
+bool AvalancheConsole::Cmd_MagicLines(int argc, const char **argv) {
+ if (argc != 1) {
+ DebugPrintf("Usage: %s\n", argv[0]);
+ return true;
+ }
+
+ _vm->_showDebugLines = !_vm->_showDebugLines;
+ return false;
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/console.h b/engines/avalanche/console.h
new file mode 100644
index 0000000000..166515d913
--- /dev/null
+++ b/engines/avalanche/console.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_CONSOLE_H
+#define AVALANCHE_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Avalanche {
+
+class AvalancheEngine;
+
+class AvalancheConsole : public GUI::Debugger {
+public:
+ AvalancheConsole(AvalancheEngine *vm);
+ virtual ~AvalancheConsole(void);
+
+protected:
+ bool Cmd_MagicLines(int argc, const char **argv);
+
+private:
+ AvalancheEngine *_vm;
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_CONSOLE_H
diff --git a/engines/avalanche/detection.cpp b/engines/avalanche/detection.cpp
new file mode 100644
index 0000000000..5f4f03a78b
--- /dev/null
+++ b/engines/avalanche/detection.cpp
@@ -0,0 +1,209 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/avalanche.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+
+#include "engines/advancedDetector.h"
+#include "graphics/thumbnail.h"
+
+namespace Avalanche {
+
+uint32 AvalancheEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+const char *AvalancheEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+static const PlainGameDescriptor avalancheGames[] = {
+ {"avalanche", "Lord Avalot d'Argent"},
+ {0, 0}
+};
+
+static const ADGameDescription gameDescriptions[] = {
+ {
+ "avalanche", 0,
+ {
+ {"avalot.sez", 0, "de10eb353228013da3d3297784f81ff9", 48763},
+ {"mainmenu.avd", 0, "89f31211af579a872045b175cc264298", 18880},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+class AvalancheMetaEngine : public AdvancedMetaEngine {
+public:
+ AvalancheMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(AvalancheGameDescription), avalancheGames) {
+ }
+
+ const char *getName() const {
+ return "Avalanche";
+ }
+
+ const char *getOriginalCopyright() const {
+ return "Avalanche Engine Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.";
+ }
+
+ bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
+ bool hasFeature(MetaEngineFeature f) const;
+
+ int getMaximumSaveSlot() const { return 99; }
+ SaveStateList listSaves(const char *target) const;
+ void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool AvalancheMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+ if (gd)
+ *engine = new AvalancheEngine(syst, (const AvalancheGameDescription *)gd);
+ return gd != 0;
+}
+
+bool AvalancheMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail);
+}
+
+SaveStateList AvalancheMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern.toUppercase();
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
+ const Common::String &fname = *filename;
+ int slotNum = atoi(fname.c_str() + fname.size() - 3);
+ if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
+ Common::InSaveFile *file = saveFileMan->openForLoading(fname);
+ if (file) {
+ // Check for our signature.
+ uint32 signature = file->readUint32LE();
+ if (signature != MKTAG('A', 'V', 'A', 'L')) {
+ warning("Savegame of incompatible type!");
+ delete file;
+ continue;
+ }
+
+ // Check version.
+ byte saveVersion = file->readByte();
+ if (saveVersion > kSavegameVersion) {
+ warning("Savegame of incompatible version!");
+ delete file;
+ continue;
+ }
+
+ // Read name.
+ uint32 nameSize = file->readUint32LE();
+ if (nameSize >= 255) {
+ delete file;
+ continue;
+ }
+ char *name = new char[nameSize + 1];
+ file->read(name, nameSize);
+ name[nameSize] = 0;
+
+ saveList.push_back(SaveStateDescriptor(slotNum, name));
+ delete[] name;
+ delete file;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void AvalancheMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+SaveStateDescriptor AvalancheMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (f) {
+ // Check for our signature.
+ uint32 signature = f->readUint32LE();
+ if (signature != MKTAG('A', 'V', 'A', 'L')) {
+ warning("Savegame of incompatible type!");
+ delete f;
+ return SaveStateDescriptor();
+ }
+
+ // Check version.
+ byte saveVersion = f->readByte();
+ if (saveVersion > kSavegameVersion) {
+ warning("Savegame of a too recent version!");
+ delete f;
+ return SaveStateDescriptor();
+ }
+
+ // Read the description.
+ uint32 descSize = f->readUint32LE();
+ Common::String description;
+ for (uint32 i = 0; i < descSize; i++) {
+ char actChar = f->readByte();
+ description += actChar;
+ }
+
+ SaveStateDescriptor desc(slot, description);
+
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*f);
+ desc.setThumbnail(thumbnail);
+
+ delete f;
+ return desc;
+ }
+ return SaveStateDescriptor();
+}
+
+} // End of namespace Avalanche
+
+#if PLUGIN_ENABLED_DYNAMIC(AVALANCHE)
+ REGISTER_PLUGIN_DYNAMIC(AVALANCHE, PLUGIN_TYPE_ENGINE, Avalanche::AvalancheMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(AVALANCHE, PLUGIN_TYPE_ENGINE, Avalanche::AvalancheMetaEngine);
+#endif
diff --git a/engines/avalanche/dialogs.cpp b/engines/avalanche/dialogs.cpp
new file mode 100644
index 0000000000..271c0b8288
--- /dev/null
+++ b/engines/avalanche/dialogs.cpp
@@ -0,0 +1,1212 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+ /* SCROLLS The scroll driver. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/dialogs.h"
+
+#include "common/random.h"
+
+namespace Avalanche {
+
+// A quasiped defines how people who aren't sprites talk. For example, quasiped
+// "A" is Dogfood. The rooms aren't stored because I'm leaving that to context.
+const QuasipedType Dialogs::kQuasipeds[16] = {
+ //_whichPed, _foregroundColor, _room, _backgroundColor, _who
+ {1, kColorLightgray, kRoomArgentPub, kColorBrown, kPeopleDogfood}, // A: Dogfood (screen 19).
+ {2, kColorGreen, kRoomArgentPub, kColorWhite, kPeopleIbythneth}, // B: Ibythneth (screen 19).
+ {2, kColorWhite, kRoomYours, kColorMagenta, kPeopleArkata}, // C: Arkata (screen 1).
+ {2, kColorBlack, kRoomLustiesRoom, kColorRed, kPeopleInvisible}, // D: Hawk (screen 23).
+ {2, kColorLightgreen, kRoomOutsideDucks, kColorBrown, kPeopleTrader}, // E: Trader (screen 50).
+ {5, kColorYellow, kRoomRobins, kColorRed, kPeopleAvalot}, // F: Avvy, tied up (scr.42)
+ {1, kColorBlue, kRoomAylesOffice, kColorWhite, kPeopleAyles}, // G: Ayles (screen 16).
+ {1, kColorBrown, kRoomMusicRoom, kColorWhite, kPeopleJacques}, // H: Jacques (screen 7).
+ {1, kColorLightgreen, kRoomNottsPub, kColorGreen, kPeopleSpurge}, // I: Spurge (screen 47).
+ {2, kColorYellow, kRoomNottsPub, kColorRed, kPeopleAvalot}, // J: Avalot (screen 47).
+ {1, kColorLightgray, kRoomLustiesRoom, kColorBlack, kPeopleDuLustie}, // K: du Lustie (screen 23).
+ {1, kColorYellow, kRoomOubliette, kColorRed, kPeopleAvalot}, // L: Avalot (screen 27).
+ {2, kColorWhite, kRoomOubliette, kColorRed, kPeopleInvisible}, // M: Avaroid (screen 27).
+ {3, kColorLightgray, kRoomArgentPub, kColorDarkgray, kPeopleMalagauche},// N: Malagauche (screen 19).
+ {4, kColorLightmagenta, kRoomNottsPub, kColorRed, kPeoplePort}, // O: Port (screen 47).
+ {1, kColorLightgreen, kRoomDucks, kColorDarkgray, kPeopleDrDuck} // P: Duck (screen 51).
+};
+
+Dialogs::Dialogs(AvalancheEngine *vm) {
+ _vm = vm;
+ _noError = true;
+
+ _aboutBox = false;
+ _talkX = 0;
+ _talkY = 0;
+ _maxLineNum = 0;
+ _scReturn = false;
+ _currentFont = kFontStyleRoman;
+ _param = 0;
+ _useIcon = 0;
+ _scrollBells = 0;
+ _underScroll = 0;
+ _shadowBoxX = 0;
+ _shadowBoxY = 0;
+}
+
+void Dialogs::init() {
+ loadFont();
+ resetScrollDriver();
+}
+
+/**
+ * Determine the color of the ready light and draw it
+ * @remarks Originally called 'state'
+ */
+void Dialogs::setReadyLight(byte state) {
+ if (_vm->_ledStatus == state)
+ return; // Already like that!
+
+ Color color = kColorBlack;
+ switch (state) {
+ case 0:
+ color = kColorBlack;
+ break; // Off
+ case 1:
+ case 2:
+ case 3:
+ color = kColorGreen;
+ break; // Hit a key
+ }
+ warning("STUB: Dialogs::setReadyLight()");
+
+ CursorMan.showMouse(false);
+ _vm->_graphics->drawReadyLight(color);
+ CursorMan.showMouse(true);
+ _vm->_ledStatus = state;
+}
+
+void Dialogs::easterEgg() {
+ warning("STUB: Scrolls::easterEgg()");
+}
+
+void Dialogs::say(int16 x, int16 y, Common::String z) {
+ FontType itw;
+ byte lz = z.size();
+
+ bool offset = x % 8 == 4;
+ x /= 8;
+ y++;
+ int16 i = 0;
+ for (int xx = 0; xx < lz; xx++) {
+ switch (z[xx]) {
+ case kControlRoman:
+ _currentFont = kFontStyleRoman;
+ break;
+ case kControlItalic:
+ _currentFont = kFontStyleItalic;
+ break;
+ default: {
+ for (int yy = 0; yy < 12; yy++)
+ itw[(byte)z[xx]][yy] = _fonts[_currentFont][(byte)z[xx]][yy + 2];
+
+ // We have to draw the characters one-by-one because of the accidental font changes.
+ i++;
+ Common::String chr(z[xx]);
+ _vm->_graphics->drawScrollText(chr, itw, 12, (x - 1) * 8 + offset * 4 + i * 8, y, kColorBlack);
+ }
+ }
+ }
+}
+
+/**
+ * One of the 3 "Mode" functions passed as ScrollsFunctionType parameters.
+ * @remarks Originally called 'normscroll'
+ */
+void Dialogs::scrollModeNormal() {
+ // Original code is:
+ // egg : array[1..8] of char = ^P^L^U^G^H+'***';
+ // this is not using kControl characters: it's the secret code to be entered to trigger the easter egg
+ // TODO: To be fixed when the Easter egg code is implemented
+ Common::String egg = Common::String::format("%c%c%c%c%c***", kControlParagraph, kControlLeftJustified, kControlNegative, kControlBell, kControlBackspace);
+ Common::String e = "(c) 1994";
+
+ setReadyLight(3);
+ _vm->_seeScroll = true;
+ _vm->_graphics->loadMouse(kCurFletch);
+
+ _vm->_graphics->saveScreen();
+ _vm->_graphics->showScroll();
+
+ Common::Event event;
+ bool escape = false;
+ while (!_vm->shouldQuit() && !escape) {
+ _vm->_graphics->refreshScreen();
+ while (_vm->getEvent(event)) {
+ if ((event.type == Common::EVENT_LBUTTONUP) ||
+ ((event.type == Common::EVENT_KEYDOWN) && ((event.kbd.keycode == Common::KEYCODE_ESCAPE) ||
+ (event.kbd.keycode == Common::KEYCODE_RETURN) || (event.kbd.keycode == Common::KEYCODE_HASH) ||
+ (event.kbd.keycode == Common::KEYCODE_PLUS)))) {
+ escape = true;
+ break;
+ }
+ }
+ }
+
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+
+ warning("STUB: scrollModeNormal() - Check Easter Egg trigger");
+#if 0
+ char r;
+ bool oktoexit;
+ do {
+ do {
+ _vm->check(); // was "checkclick;"
+
+//#ifdef RECORD slowdown(); basher::count++; #endif
+
+ if (_vm->_enhanced->keypressede())
+ break;
+ } while (!((mrelease > 0) || (buttona1()) || (buttonb1())));
+
+ if (mrelease == 0) {
+ inkey();
+ if (aboutscroll) {
+ move(e[2 - 1], e[1 - 1], 7);
+ e[8 - 1] = inchar;
+ if (egg == e)
+ easteregg();
+ }
+ oktoexit = set::of('\15', '\33', '+', '#', eos).has(inchar);
+ if (!oktoexit) errorled();
+ }
+
+ } while (!((oktoexit) || (mrelease > 0)));
+
+//#ifdef RECORD record_one(); #endif
+
+ _vm->screturn = r == '#'; // "back door"
+#endif
+
+ setReadyLight(0);
+ _vm->_seeScroll = false;
+ _vm->_holdLeftMouse = false; // Used in Lucerna::checkclick().
+
+ warning("STUB: Scrolls::scrollModeNormal()");
+}
+
+/**
+ * One of the 3 "Mode" functions passed as ScrollsFunctionType parameters.
+ * The "asking" scroll. Used indirectly in diplayQuestion().
+ * @remarks Originally called 'dialogue'
+ */
+void Dialogs::scrollModeDialogue() {
+ _vm->_graphics->loadMouse(kCurHand);
+
+ _vm->_graphics->saveScreen();
+ _vm->_graphics->showScroll();
+
+ Common::Event event;
+ while (!_vm->shouldQuit()) {
+ _vm->_graphics->refreshScreen();
+
+ _vm->getEvent(event);
+
+ Common::Point cursorPos = _vm->getMousePos();
+ cursorPos.y /= 2;
+
+ char inChar = 0;
+ if ((event.type == Common::EVENT_KEYDOWN) && (event.kbd.ascii <= 122) && (event.kbd.ascii >= 97)) {
+ inChar = (char)event.kbd.ascii;
+ Common::String temp(inChar);
+ temp.toUppercase();
+ inChar = temp[0];
+ }
+
+ if (_vm->shouldQuit() || (event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_KEYDOWN)) {
+ if (((cursorPos.x >= _shadowBoxX - 65) && (cursorPos.y >= _shadowBoxY - 24) && (cursorPos.x <= _shadowBoxX - 5) && (cursorPos.y <= _shadowBoxY - 10))
+ || (inChar == 'Y') || (inChar == 'J') || (inChar == 'O')) { // Yes, Ja, Oui
+ _scReturn = true;
+ break;
+ } else if (((cursorPos.x >= _shadowBoxX + 5) && (cursorPos.y >= _shadowBoxY - 24) && (cursorPos.x <= _shadowBoxX + 65) && (cursorPos.y <= _shadowBoxY - 10))
+ || (inChar == 'N')){ // No, Non, Nein
+ _scReturn = false;
+ break;
+ }
+ }
+ }
+
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+}
+
+void Dialogs::store(byte what, TuneType &played) {
+ memcpy(played, played + 1, sizeof(played) - 1);
+ played[30] = what;
+}
+
+bool Dialogs::theyMatch(TuneType &played) {
+ byte mistakes = 0;
+
+ for (unsigned int i = 0; i < sizeof(played); i++) {
+ if (played[i] != _vm->kTune[i])
+ mistakes++;
+ }
+
+ return mistakes < 5;
+}
+
+/**
+ * One of the 3 "Mode" functions passed as ScrollsFunctionType parameters.
+ * Part of the harp mini-game.
+ * @remarks Originally called 'music_Scroll'
+ */
+void Dialogs::scrollModeMusic() {
+ setReadyLight(3);
+ _vm->_seeScroll = true;
+ CursorMan.showMouse(false);
+ _vm->_graphics->loadMouse(kCurFletch);
+
+ TuneType played;
+ for (unsigned int i = 0; i < sizeof(played); i++)
+ played[i] = kPitchInvalid;
+ int8 lastOne = -1, thisOne = -1; // Invalid values.
+
+ _vm->_seeScroll = true;
+
+ _vm->_graphics->saveScreen();
+ _vm->_graphics->showScroll();
+
+ Common::Event event;
+ while (!_vm->shouldQuit()) {
+ _vm->_graphics->refreshScreen();
+
+ _vm->getEvent(event);
+
+ // When we stop playing?
+ if ((event.type == Common::EVENT_LBUTTONDOWN) ||
+ ((event.type == Common::EVENT_KEYDOWN) && ((event.kbd.keycode == Common::KEYCODE_RETURN) || (event.kbd.keycode == Common::KEYCODE_ESCAPE)))) {
+ break;
+ }
+
+ // When we DO play:
+ if ((event.type == Common::EVENT_KEYDOWN)
+ && ((event.kbd.keycode == Common::KEYCODE_q) || (event.kbd.keycode == Common::KEYCODE_w)
+ || (event.kbd.keycode == Common::KEYCODE_e) || (event.kbd.keycode == Common::KEYCODE_r)
+ || (event.kbd.keycode == Common::KEYCODE_t) || (event.kbd.keycode == Common::KEYCODE_y)
+ || (event.kbd.keycode == Common::KEYCODE_u) || (event.kbd.keycode == Common::KEYCODE_i)
+ || (event.kbd.keycode == Common::KEYCODE_o) || (event.kbd.keycode == Common::KEYCODE_p)
+ || (event.kbd.keycode == Common::KEYCODE_LEFTBRACKET) || (event.kbd.keycode == Common::KEYCODE_RIGHTBRACKET))) {
+ byte value;
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ value = 0;
+ break;
+ case Common::KEYCODE_w:
+ value = 1;
+ break;
+ case Common::KEYCODE_e:
+ value = 2;
+ break;
+ case Common::KEYCODE_r:
+ value = 3;
+ break;
+ case Common::KEYCODE_t:
+ value = 4;
+ break;
+ case Common::KEYCODE_y:
+ value = 5;
+ break;
+ case Common::KEYCODE_u:
+ value = 6;
+ break;
+ case Common::KEYCODE_i:
+ value = 7;
+ break;
+ case Common::KEYCODE_o:
+ value = 8;
+ break;
+ case Common::KEYCODE_p:
+ value = 9;
+ break;
+ case Common::KEYCODE_LEFTBRACKET:
+ value = 10;
+ break;
+ case Common::KEYCODE_RIGHTBRACKET:
+ value = 11;
+ break;
+ default:
+ break;
+ }
+
+ lastOne = thisOne;
+ thisOne = value;
+
+ _vm->_sound->playNote(_vm->kNotes[thisOne], 100);
+ _vm->_system->delayMillis(200);
+
+ if (!_vm->_bellsAreRinging) { // These handle playing the right tune.
+ if (thisOne < lastOne)
+ store(kPitchLower, played);
+ else if (thisOne == lastOne)
+ store(kPitchSame, played);
+ else
+ store(kPitchHigher, played);
+ }
+
+ if (theyMatch(played)) {
+ setReadyLight(0);
+ _vm->_timer->addTimer(8, Timer::kProcJacquesWakesUp, Timer::kReasonJacquesWakingUp);
+ break;
+ }
+ }
+ }
+
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+
+ _vm->_seeScroll = false;
+ CursorMan.showMouse(true);
+}
+
+void Dialogs::resetScrollDriver() {
+ _scrollBells = 0;
+ _currentFont = kFontStyleRoman;
+ _useIcon = 0;
+ _vm->_interrogation = 0; // Always reset after a scroll comes up.
+}
+
+/**
+ * Rings the bell x times
+ * @remarks Originally called 'dingdongbell'
+ */
+void Dialogs::ringBell() {
+ for (int i = 0; i < _scrollBells; i++)
+ _vm->errorLed(); // Ring the bell "_scrollBells" times.
+}
+
+/**
+ * This moves the mouse pointer off the scroll so that you can read it.
+ * @remarks Originally called 'dodgem'
+ */
+void Dialogs::dodgem() {
+ _dodgeCoord = _vm->getMousePos();
+ g_system->warpMouse(_dodgeCoord.x, _underScroll); // Move the pointer off the scroll.
+}
+
+/**
+ * This is the opposite of Dodgem.
+ * It moves the mouse pointer back, IF you haven't moved it in the meantime.
+ * @remarks Originally called 'undodgem'
+ */
+void Dialogs::unDodgem() {
+ Common::Point actCoord = _vm->getMousePos();
+ if ((actCoord.x == _dodgeCoord.x) && (actCoord.y == _underScroll))
+ g_system->warpMouse(_dodgeCoord.x, _dodgeCoord.y); // No change, so restore the pointer's original position.
+}
+
+void Dialogs::drawScroll(DialogFunctionType modeFunc) {
+ int16 lx = 0;
+ int16 ly = (_maxLineNum + 1) * 6;
+ int16 ex;
+ for (int i = 0; i <= _maxLineNum; i++) {
+ ex = _scroll[i].size() * 8;
+ if (lx < ex)
+ lx = ex;
+ }
+ int16 mx = 320;
+ int16 my = 100; // Getmaxx & getmaxy div 2, both.
+ lx /= 2;
+ ly -= 2;
+
+ if ((1 <= _useIcon) && (_useIcon <= 34))
+ lx += kHalfIconWidth;
+
+ CursorMan.showMouse(false);
+ _vm->_graphics->drawScroll(mx, lx, my, ly);
+
+ mx -= lx;
+ my -= ly + 2;
+
+ bool centre = false;
+
+ byte iconIndent = 0;
+ switch (_useIcon) {
+ case 0:
+ iconIndent = 0;
+ break; // No icon.
+ case 34:
+ _vm->_graphics->drawSign("about", 28, 76, 15);
+ iconIndent = 0;
+ break;
+ case 35:
+ _vm->_graphics->drawSign("gameover", 52, 59, 71);
+ iconIndent = 0;
+ break;
+ }
+
+ if ((1 <= _useIcon) && (_useIcon <= 33)) { // Standard icon.
+ _vm->_graphics->drawIcon(mx, my + ly / 2, _useIcon);
+ iconIndent = 53;
+ }
+
+ for (int i = 0; i <= _maxLineNum; i++) {
+ if (!_scroll[i].empty())
+ switch (_scroll[i][_scroll[i].size() - 1]) {
+ case kControlCenter:
+ centre = true;
+ _scroll[i].deleteLastChar();
+ break;
+ case kControlLeftJustified:
+ centre = false;
+ _scroll[i].deleteLastChar();
+ break;
+ case kControlQuestion:
+ _shadowBoxX = mx + lx;
+ _shadowBoxY = my + ly;
+ _scroll[i].setChar(' ', 0);
+ _vm->_graphics->drawShadowBox(_shadowBoxX - 65, _shadowBoxY - 24, _shadowBoxX - 5, _shadowBoxY - 10, "Yes.");
+ _vm->_graphics->drawShadowBox(_shadowBoxX + 5, _shadowBoxY - 24, _shadowBoxX + 65, _shadowBoxY - 10, "No.");
+ break;
+ }
+
+ if (centre)
+ say(320 - _scroll[i].size() * 4 + iconIndent, my, _scroll[i]);
+ else
+ say(mx + iconIndent, my, _scroll[i]);
+
+ my += 12;
+ }
+
+ _underScroll = (my + 3) * 2; // Multiplying because of the doubled screen height.
+ ringBell();
+
+ _vm->_dropsOk = false;
+ dodgem();
+
+ (this->*modeFunc)();
+
+ unDodgem();
+ _vm->_dropsOk = true;
+
+ resetScrollDriver();
+}
+
+void Dialogs::drawBubble(DialogFunctionType modeFunc) {
+ Common::Point points[3];
+
+ CursorMan.showMouse(false);
+ int16 xl = 0;
+ int16 yl = (_maxLineNum + 1) * 5;
+ for (int i = 0; i <= _maxLineNum; i++) {
+ uint16 textWidth = _scroll[i].size() * 8;
+ if (textWidth > xl)
+ xl = textWidth;
+ }
+ xl /= 2;
+
+ int16 xw = xl + 18;
+ int16 yw = yl + 7;
+ int16 my = yw * 2 - 2;
+ int16 xc = 0;
+
+ if (_talkX - xw < 0)
+ xc = -(_talkX - xw);
+ if (_talkX + xw > 639)
+ xc = 639 - (_talkX + xw);
+
+ // Compute triangle coords for the tail of the bubble
+ points[0].x = _talkX - 10;
+ points[0].y = yw;
+ points[1].x = _talkX + 10;
+ points[1].y = yw;
+ points[2].x = _talkX;
+ points[2].y = _talkY;
+
+ _vm->_graphics->prepareBubble(xc, xw, my, points);
+
+ // Draw the text of the bubble. The centering of the text was improved here compared to Pascal's settextjustify().
+ // The font is not the same that outtextxy() uses in Pascal. I don't have that, so I used characters instead.
+ // It's almost the same, only notable differences are '?', '!', etc.
+ for (int i = 0; i <= _maxLineNum; i++) {
+ int16 x = xc + _talkX - _scroll[i].size() / 2 * 8;
+ bool offset = _scroll[i].size() % 2;
+ _vm->_graphics->drawScrollText(_scroll[i], _vm->_font, 8, x - offset * 4, (i * 10) + 12, _vm->_graphics->_talkFontColor);
+ }
+
+ ringBell();
+ CursorMan.showMouse(false);
+ _vm->_dropsOk = false;
+
+ // This does the actual drawing to the screen.
+ (this->*modeFunc)();
+
+ _vm->_dropsOk = true;
+ CursorMan.showMouse(true); // sink;
+ resetScrollDriver();
+}
+
+void Dialogs::reset() {
+ _maxLineNum = 0;
+ for (int i = 0; i < 15; i++) {
+ if (!_scroll[i].empty())
+ _scroll[i].clear();
+ }
+}
+
+/**
+ * Natural state of bubbles
+ * @remarks Originally called 'natural'
+ */
+void Dialogs::setBubbleStateNatural() {
+ _talkX = 320;
+ _talkY = 200;
+ _vm->_graphics->setDialogColor(kColorDarkgray, kColorWhite);
+}
+
+Common::String Dialogs::displayMoney() {
+ Common::String result;
+
+ if (_vm->_money < 12) { // just pence
+ result = Common::String::format("%dd", _vm->_money);
+ } else if (_vm->_money < 240) { // shillings & pence
+ if ((_vm->_money % 12) == 0)
+ result = Common::String::format("%d/-", _vm->_money / 12);
+ else
+ result = Common::String::format("%d/%d", _vm->_money / 12, _vm->_money % 12);
+ } else { // L, s & d
+ result = Common::String::format("\x9C%d.%d.%d", _vm->_money / 240, (_vm->_money / 12) % 20,
+ _vm->_money % 12);
+ }
+ if (_vm->_money > 12) {
+ Common::String extraStr = Common::String::format(" (that's %dd)", _vm->_money);
+ result += extraStr;
+ }
+
+ return result;
+}
+
+/**
+ * Strip trailing character in a string
+ * @remarks Originally called 'strip'
+ */
+void Dialogs::stripTrailingSpaces(Common::String &str) {
+ while (str.lastChar() == ' ')
+ str.deleteLastChar();
+ // We don't use String::trim() here because we need the leading whitespaces.
+}
+
+/**
+ * Does the word wrapping.
+ */
+void Dialogs::solidify(byte n) {
+ if (!_scroll[n].contains(' '))
+ return; // No spaces.
+
+ // So there MUST be a space there, somewhere...
+ do {
+ _scroll[n + 1] = _scroll[n][_scroll[n].size() - 1] + _scroll[n + 1];
+ _scroll[n].deleteLastChar();
+ } while (_scroll[n][_scroll[n].size() - 1] != ' ');
+
+ stripTrailingSpaces(_scroll[n]);
+}
+
+/**
+ * @remarks Originally called 'calldriver'
+ * Display text by calling the dialog driver. It unifies the function of the original
+ * 'calldriver' and 'display' by using Common::String instead of a private buffer.
+ */
+void Dialogs::displayText(Common::String text) {
+// bool was_virtual; // Was the mouse cursor virtual on entry to this proc?
+ warning("STUB: Scrolls::calldrivers()");
+
+ _vm->_sound->stopSound();
+
+ setReadyLight(0);
+ _scReturn = false;
+ bool mouthnext = false;
+ bool callSpriteRun = true; // Only call sprite_run the FIRST time.
+
+ switch (text.lastChar()) {
+ case kControlToBuffer:
+ text.deleteLastChar();
+ break; // ^D = (D)on't include pagebreak
+ case kControlSpeechBubble:
+ case kControlQuestion:
+ break; // ^B = speech (B)ubble, ^Q = (Q)uestion in dialogue box
+ default:
+ text.insertChar(kControlParagraph, text.size());
+ }
+
+ for (uint16 i = 0; i < text.size(); i++) {
+ if (mouthnext) {
+ if (text[i] == kControlRegister)
+ _param = 0;
+ else if (('0' <= text[i]) && (text[i] <= '9'))
+ _param = text[i] - 48;
+ else if (('A' <= text[i]) && (text[i] <= 'Z'))
+ _param = text[i] - 55;
+
+ mouthnext = false;
+ } else {
+ switch (text[i]) {
+ case kControlParagraph:
+ if ((_maxLineNum == 0) && (_scroll[0].empty()))
+ break;
+
+ if (callSpriteRun)
+ _vm->spriteRun();
+ callSpriteRun = false;
+
+ drawScroll(&Avalanche::Dialogs::scrollModeNormal);
+
+ reset();
+
+ if (_scReturn)
+ return;
+ break;
+ case kControlBell:
+ _scrollBells++;
+ break;
+ case kControlSpeechBubble:
+ if ((_maxLineNum == 0) && (_scroll[0].empty()))
+ break;
+
+ if (callSpriteRun)
+ _vm->spriteRun();
+ callSpriteRun = false;
+
+ if (_param == 0)
+ setBubbleStateNatural();
+ else if ((1 <= _param) && (_param <= 9)) {
+ assert(_param - 1 < _vm->_animation->kSpriteNumbMax);
+ AnimationType *spr = _vm->_animation->_sprites[_param - 1];
+ if ((_param > _vm->_animation->kSpriteNumbMax) || (!spr->_quick)) { // Not valid.
+ _vm->errorLed();
+ setBubbleStateNatural();
+ } else
+ spr->chatter(); // Normal sprite talking routine.
+ } else if ((10 <= _param) && (_param <= 36)) {
+ // Quasi-peds. (This routine performs the same
+ // thing with QPs as triptype.chatter does with the
+ // sprites.)
+ assert(_param - 10 < 16);
+ PedType *quasiPed = &_vm->_peds[kQuasipeds[_param - 10]._whichPed];
+ _talkX = quasiPed->_x;
+ _talkY = quasiPed->_y; // Position.
+
+ _vm->_graphics->setDialogColor(kQuasipeds[_param - 10]._backgroundColor, kQuasipeds[_param - 10]._textColor);
+ } else {
+ _vm->errorLed(); // Not valid.
+ setBubbleStateNatural();
+ }
+
+ drawBubble(&Avalanche::Dialogs::scrollModeNormal);
+
+ reset();
+
+ if (_scReturn)
+ return;
+ break;
+
+ // CHECME: The whole kControlNegative block seems completely unused, as the only use (the easter egg check) is a false positive
+ case kControlNegative:
+ switch (_param) {
+ case 1:
+ displayText(displayMoney() + kControlToBuffer); // Insert cash balance. (Recursion)
+ break;
+ case 2: {
+ int pwdId = _vm->_parser->kFirstPassword + _vm->_passwordNum;
+ displayText(_vm->_parser->_vocabulary[pwdId]._word + kControlToBuffer);
+ }
+ break;
+ case 3:
+ displayText(_vm->_favoriteDrink + kControlToBuffer);
+ break;
+ case 4:
+ displayText(_vm->_favoriteSong + kControlToBuffer);
+ break;
+ case 5:
+ displayText(_vm->_worstPlaceOnEarth + kControlToBuffer);
+ break;
+ case 6:
+ displayText(_vm->_spareEvening + kControlToBuffer);
+ break;
+ case 9: {
+ Common::String tmpStr = Common::String::format("%d,%d%c",_vm->_catacombX, _vm->_catacombY, kControlToBuffer);
+ displayText(tmpStr);
+ }
+ break;
+ case 10:
+ switch (_vm->_boxContent) {
+ case 0: // Sixpence.
+ displayScrollChain('Q', 37); // You find the sixpence.
+ _vm->_money += 6;
+ _vm->_boxContent = _vm->_parser->kNothing;
+ _vm->incScore(2);
+ return;
+ case Parser::kNothing:
+ displayText("nothing at all. It's completely empty.");
+ break;
+ default:
+ displayText(_vm->getItem(_vm->_boxContent) + '.');
+ }
+ break;
+ case 11:
+ for (int j = 0; j < kObjectNum; j++) {
+ if (_vm->_objects[j])
+ displayText(_vm->getItem(j) + ", " + kControlToBuffer);
+ }
+ break;
+ }
+ break;
+ case kControlIcon:
+ _useIcon = _param;
+ break;
+ case kControlNewLine:
+ _maxLineNum++;
+ break;
+ case kControlQuestion:
+ if (callSpriteRun)
+ _vm->spriteRun();
+ callSpriteRun = false;
+
+ _maxLineNum++;
+ _scroll[_maxLineNum] = kControlQuestion;
+
+ drawScroll(&Avalanche::Dialogs::scrollModeDialogue);
+ reset();
+ break;
+ case kControlRegister:
+ mouthnext = true;
+ break;
+ case kControlInsertSpaces:
+ for (int j = 0; j < 9; j++)
+ _scroll[_maxLineNum] += ' ';
+ break;
+ default: // Add new char.
+ if (_scroll[_maxLineNum].size() == 50) {
+ solidify(_maxLineNum);
+ _maxLineNum++;
+ }
+ _scroll[_maxLineNum] += text[i];
+ break;
+ }
+ }
+ }
+}
+
+void Dialogs::setTalkPos(int16 x, int16 y) {
+ _talkX = x;
+ _talkY = y;
+}
+
+int16 Dialogs::getTalkPosX() {
+ return _talkX;
+}
+
+bool Dialogs::displayQuestion(Common::String question) {
+ displayText(question + kControlNewLine + kControlQuestion);
+
+ if (_scReturn && (_vm->_rnd->getRandomNumber(1) == 0)) { // Half-and-half chance.
+ Common::String tmpStr = Common::String::format("...Positive about that?%cI%c%c%c", kControlRegister, kControlIcon, kControlNewLine, kControlQuestion);
+ displayText(tmpStr); // Be annoying!
+ if (_scReturn && (_vm->_rnd->getRandomNumber(3) == 3)) { // Another 25% chance
+ // \? are used to avoid that ??! is parsed as a trigraph
+ tmpStr = Common::String::format("%c100%% certain\?\?!%c%c%c%c", kControlInsertSpaces, kControlInsertSpaces, kControlIcon, kControlNewLine, kControlQuestion);
+ displayText(tmpStr); // Be very annoying!
+ }
+ }
+
+ return _scReturn;
+}
+
+void Dialogs::loadFont() {
+ Common::File file;
+
+ if (!file.open("avalot.fnt"))
+ error("AVALANCHE: Scrolls: File not found: avalot.fnt");
+
+ for (int16 i = 0; i < 256; i++)
+ file.read(_fonts[0][i], 16);
+ file.close();
+
+ if (!file.open("avitalic.fnt"))
+ error("AVALANCHE: Scrolls: File not found: avitalic.fnt");
+
+ for (int16 i = 0; i < 256; i++)
+ file.read(_fonts[1][i], 16);
+ file.close();
+
+ if (!file.open("ttsmall.fnt"))
+ error("AVALANCHE: Scrolls: File not found: ttsmall.fnt");
+
+ for (int16 i = 0; i < 256; i++)
+ file.read(_vm->_font[i],16);
+ file.close();
+}
+
+/**
+ * Practically this one is a mini-game which called when you play the harp in the monastery.
+ * @remarks Originally called 'musical_scroll'
+ */
+void Dialogs::displayMusicalScroll() {
+ Common::String tmpStr = Common::String::format("To play the harp...%c%cUse these keys:%c%cQ W E R T Y U I O P [ ]%c%cOr press Enter to stop playing.%c",
+ kControlNewLine, kControlNewLine, kControlNewLine, kControlInsertSpaces, kControlNewLine, kControlNewLine, kControlToBuffer);
+ displayText(tmpStr);
+
+ _vm->spriteRun();
+ CursorMan.showMouse(false);
+ drawScroll(&Avalanche::Dialogs::scrollModeMusic);
+ CursorMan.showMouse(true);
+ reset();
+}
+
+void Dialogs::unSkrimble(Common::String &text) {
+ for (uint16 i = 0; i < text.size(); i++)
+ text.setChar((~(text[i] - (i + 1))) % 256, i);
+}
+
+void Dialogs::doTheBubble(Common::String &text) {
+ text.insertChar(kControlSpeechBubble, text.size());
+ assert(text.size() < 2000);
+}
+
+/**
+ * Display a string in a scroll
+ * @remarks Originally called 'dixi'
+ */
+void Dialogs::displayScrollChain(char block, byte point, bool report, bool bubbling) {
+ Common::File indexfile;
+ if (!indexfile.open("avalot.idx"))
+ error("AVALANCHE: Visa: File not found: avalot.idx");
+
+ bool error = false;
+
+ indexfile.seek((toupper(block) - 'A') * 2);
+ uint16 idx_offset = indexfile.readUint16LE();
+ if (idx_offset == 0)
+ error = true;
+
+ indexfile.seek(idx_offset + point * 2);
+ uint16 sez_offset = indexfile.readUint16LE();
+ if (sez_offset == 0)
+ error = true;
+
+ indexfile.close();
+
+ _noError = !error;
+
+ if (error) {
+ if (report) {
+ Common::String todisplay = Common::String::format("%cError accessing scroll %c%d", kControlBell, block, point);
+ displayText(todisplay);
+ }
+ return;
+ }
+
+ Common::File sezfile;
+ if (!sezfile.open("avalot.sez"))
+ ::error("AVALANCHE: Visa: File not found: avalot.sez");
+
+ sezfile.seek(sez_offset);
+ uint16 _bufSize = sezfile.readUint16LE();
+ assert(_bufSize < 2000);
+ char *_buffer = new char[_bufSize];
+ sezfile.read(_buffer, _bufSize);
+ sezfile.close();
+ Common::String text(_buffer, _bufSize);
+ delete[] _buffer;
+
+ unSkrimble(text);
+ if (bubbling)
+ doTheBubble(text);
+ displayText(text);
+}
+
+/**
+ * Start speech
+ * @remarks Originally called 'speech'
+ */
+void Dialogs::speak(byte who, byte subject) {
+ if (subject == 0) { // No subject.
+ displayScrollChain('S', who, false, true);
+ return;
+ }
+
+ // Subject given.
+ _noError = false; // Assume that until we know otherwise.
+
+ Common::File indexfile;
+ if (!indexfile.open("converse.avd"))
+ error("AVALANCHE: Visa: File not found: converse.avd");
+
+ indexfile.seek(who * 2 - 2);
+ uint16 idx_offset = indexfile.readUint16LE();
+ uint16 next_idx_offset = indexfile.readUint16LE();
+
+ if ((idx_offset == 0) || ((((next_idx_offset - idx_offset) / 2) - 1) < subject))
+ return;
+
+ indexfile.seek(idx_offset + subject * 2);
+ uint16 sezOffset = indexfile.readUint16LE();
+ if ((sezOffset == 0) || (indexfile.err()))
+ return;
+ indexfile.close();
+
+ Common::File sezfile;
+ if (!sezfile.open("avalot.sez"))
+ error("AVALANCHE: Visa: File not found: avalot.sez");
+
+ sezfile.seek(sezOffset);
+ uint16 _bufSize = sezfile.readUint16LE();
+ assert(_bufSize < 2000);
+ char *_buffer = new char[_bufSize];
+ sezfile.read(_buffer, _bufSize);
+ sezfile.close();
+ Common::String text(_buffer, _bufSize);
+ delete[] _buffer;
+
+ unSkrimble(text);
+ doTheBubble(text);
+ displayText(text);
+
+ _noError = true;
+}
+
+void Dialogs::talkTo(byte whom) {
+ if (_vm->_parser->_person == kPeoplePardon) {
+ _vm->_parser->_person = (People)_vm->_subjectNum;
+ _vm->_subjectNum = 0;
+ }
+
+ if (_vm->_subjectNum == 0) {
+ switch (whom) {
+ case kPeopleSpludwick:
+ if ((_vm->_lustieIsAsleep) & (!_vm->_objects[kObjectPotion - 1])) {
+ displayScrollChain('Q', 68);
+ _vm->_objects[kObjectPotion - 1] = true;
+ _vm->refreshObjectList();
+ _vm->incScore(3);
+ return;
+ } else if (_vm->_talkedToCrapulus) {
+ // Spludwick - what does he need?
+ // 0 - let it through to use normal routine.
+ switch (_vm->_givenToSpludwick) {
+ case 1: // Fallthrough is intended.
+ case 2: {
+ Common::String objStr = _vm->getItem(AvalancheEngine::kSpludwicksOrder[_vm->_givenToSpludwick]);
+ Common::String tmpStr = Common::String::format("Can you get me %s, please?%c2%c",
+ objStr.c_str(), kControlRegister, kControlSpeechBubble);
+ displayText(tmpStr);
+ }
+ return;
+ case 3:
+ displayScrollChain('Q', 30); // Need any help with the game?
+ return;
+ }
+ } else {
+ displayScrollChain('Q', 42); // Haven't talked to Crapulus. Go and talk to him.
+ return;
+ }
+ break;
+ case kPeopleIbythneth:
+ if (_vm->_givenBadgeToIby) {
+ displayScrollChain('Q', 33); // Thanks a lot!
+ return; // And leave the proc.
+ }
+ break; // Or... just continue, 'cos he hasn't got it.
+ case kPeopleDogfood:
+ if (_vm->_wonNim) { // We've won the game.
+ displayScrollChain('Q', 6); // "I'm Not Playing!"
+ return; // Zap back.
+ } else
+ _vm->_askedDogfoodAboutNim = true;
+ break;
+ case kPeopleAyles:
+ if (!_vm->_aylesIsAwake) {
+ displayScrollChain('Q', 43); // He's fast asleep!
+ return;
+ } else if (!_vm->_givenPenToAyles) {
+ displayScrollChain('Q', 44); // Can you get me a pen, Avvy?
+ return;
+ }
+ break;
+
+ case kPeopleJacques:
+ displayScrollChain('Q', 43);
+ return;
+
+ case kPeopleGeida:
+ if (_vm->_givenPotionToGeida)
+ _vm->_geidaFollows = true;
+ else {
+ displayScrollChain('U', 17);
+ return;
+ }
+ break;
+ case kPeopleSpurge:
+ if (!_vm->_sittingInPub) {
+ displayScrollChain('Q', 71); // Try going over and sitting down.
+ return;
+ } else {
+ if (_vm->_spurgeTalkCount < 5)
+ _vm->_spurgeTalkCount++;
+ if (_vm->_spurgeTalkCount > 1) { // no. 1 falls through
+ displayScrollChain('Q', 70 + _vm->_spurgeTalkCount);
+ return;
+ }
+ }
+ break;
+ }
+ // On a subject. Is there any reason to block it?
+ } else if ((whom == kPeopleAyles) && (!_vm->_aylesIsAwake)) {
+ displayScrollChain('Q', 43); // He's fast asleep!
+ return;
+ }
+
+ if (whom > 149)
+ whom -= 149;
+
+ bool noMatches = true;
+ for (int i = 0; i < _vm->_animation->kSpriteNumbMax; i++) {
+ if (_vm->_animation->_sprites[i]->_characterId == whom) {
+ Common::String tmpStr = Common::String::format("%c%c%c", kControlRegister, i + 49, kControlToBuffer);
+ displayText(tmpStr);
+ noMatches = false;
+ break;
+ }
+ }
+
+ if (noMatches) {
+ Common::String tmpStr = Common::String::format("%c%c%c", kControlRegister, kControlRegister, kControlToBuffer);
+ displayText(tmpStr);
+ }
+
+ speak(whom, _vm->_subjectNum);
+
+ if (!_noError)
+ displayScrollChain('N', whom); // File not found!
+
+ if ((_vm->_subjectNum == 0) && ((whom + 149) == kPeopleCrapulus)) { // Crapulus: get the badge - first time only
+ _vm->_objects[kObjectBadge - 1] = true;
+ _vm->refreshObjectList();
+ displayScrollChain('Q', 1); // Circular from Cardiff.
+ _vm->_talkedToCrapulus = true;
+ _vm->setRoom(kPeopleCrapulus, kRoomDummy); // Crapulus walks off.
+
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ spr->_vanishIfStill = true;
+ spr->walkTo(2); // Walks away.
+
+ _vm->incScore(2);
+ }
+}
+
+/**
+ * This makes Avalot say the response.
+ * @remarks Originally called 'sayit'
+ */
+void Dialogs::sayIt(Common::String str) {
+ Common::String x = str;
+ x.setChar(toupper(x[0]), 0);
+ Common::String tmpStr = Common::String::format("%c1%s.%c%c2", kControlRegister, x.c_str(), kControlSpeechBubble, kControlRegister);
+ displayText(tmpStr);
+}
+
+Common::String Dialogs::personSpeaks() {
+ if ((_vm->_parser->_person == kPeoplePardon) || (_vm->_parser->_person == kPeopleNone)) {
+ if ((_vm->_him == kPeoplePardon) || (_vm->getRoom(_vm->_him) != _vm->_room))
+ _vm->_parser->_person = _vm->_her;
+ else
+ _vm->_parser->_person = _vm->_him;
+ }
+
+ if (_vm->getRoom(_vm->_parser->_person) != _vm->_room) {
+ return Common::String::format("%c1", kControlRegister); // Avvy himself!
+ }
+
+ bool found = false; // The _person we're looking for's code is in _person.
+ Common::String tmpStr;
+
+ for (int i = 0; i < _vm->_animation->kSpriteNumbMax; i++) {
+ AnimationType *curSpr = _vm->_animation->_sprites[i];
+ if (curSpr->_quick && (curSpr->_characterId + 149 == _vm->_parser->_person)) {
+ tmpStr += Common::String::format("%c%c", kControlRegister, '1' + i);
+ found = true;
+ }
+ }
+
+ if (found)
+ return tmpStr;
+
+ for (int i = 0; i < 16; i++) {
+ if ((kQuasipeds[i]._who == _vm->_parser->_person) && (kQuasipeds[i]._room == _vm->_room))
+ tmpStr += Common::String::format("%c%c", kControlRegister, 'A' + i);
+ }
+
+ return tmpStr;
+}
+
+/**
+ * Display a message when (uselessly) giving an object away
+ * @remarks Originally called 'heythanks'
+ */
+void Dialogs::sayThanks(byte thing) {
+ Common::String tmpStr = personSpeaks();
+ tmpStr += Common::String::format("Hey, thanks!%c(But now, you've lost it!)", kControlSpeechBubble);
+ displayText(tmpStr);
+
+ if (thing < kObjectNum)
+ _vm->_objects[thing] = false;
+}
+
+/**
+ * Display a 'Hello' message
+ */
+void Dialogs::sayHello() {
+ Common::String tmpStr = personSpeaks();
+ tmpStr += Common::String::format("Hello.%c", kControlSpeechBubble);
+ displayText(tmpStr);
+}
+
+/**
+ * Display a 'OK' message
+ */
+void Dialogs::sayOK() {
+ Common::String tmpStr = personSpeaks();
+ tmpStr += Common::String::format("That's OK.%c", kControlSpeechBubble);
+ displayText(tmpStr);
+}
+
+/**
+ * Display a 'Silly' message
+ * @remarks Originally called 'silly'
+ */
+void Dialogs::saySilly() {
+ displayText("Don't be silly!");
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/dialogs.h b/engines/avalanche/dialogs.h
new file mode 100644
index 0000000000..43e6a4fec6
--- /dev/null
+++ b/engines/avalanche/dialogs.h
@@ -0,0 +1,116 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+ /* SCROLLS The scroll driver. */
+
+#ifndef AVALANCHE_DIALOGS_H
+#define AVALANCHE_DIALOGS_H
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Dialogs;
+
+typedef void (Dialogs::*DialogFunctionType)();
+
+class Dialogs {
+public:
+ bool _aboutBox; // Is this the about box? - Used in scrollModeNormal(), not yet fully implemented
+ FontType _fonts[2];
+
+ Dialogs(AvalancheEngine *vm);
+
+ void init();
+ void reset();
+ void setReadyLight(byte state);
+ void displayText(Common::String text);
+ bool displayQuestion(Common::String question);
+ void setTalkPos(int16 x, int16 y);
+ int16 getTalkPosX();
+ void setBubbleStateNatural();
+ void displayMusicalScroll();
+ void displayScrollChain(char block, byte point, bool report = true, bool bubbling = false);
+ void talkTo(byte whom);
+ void sayIt(Common::String str);
+ Common::String personSpeaks();
+ void sayThanks(byte thing);
+ void sayHello();
+ void sayOK();
+ void saySilly();
+private:
+ AvalancheEngine *_vm;
+ int16 _talkX, _talkY;
+
+ enum FontStyle {
+ kFontStyleRoman,
+ kFontStyleItalic
+ };
+
+ static const int16 kHalfIconWidth = 19;
+ static const QuasipedType kQuasipeds[16];
+
+ Common::String _scroll[15];
+ Common::Point _dodgeCoord;
+ byte _maxLineNum;
+ bool _scReturn;
+ bool _noError;
+ byte _currentFont;
+ byte _param; // For using arguments code
+ byte _useIcon;
+ byte _scrollBells; // no. of times to ring the bell
+ int16 _underScroll; // Y-coord of just under the scroll text.
+ int16 _shadowBoxX, _shadowBoxY;
+
+ void drawBubble(DialogFunctionType modeFunc);
+ void drawScroll(DialogFunctionType modeFunc);
+ void scrollModeNormal();
+ void scrollModeDialogue();
+ void scrollModeMusic();
+
+ // These 2 are used only in musicalScroll().
+ void store(byte what, TuneType &played);
+ bool theyMatch(TuneType &played);
+ void stripTrailingSpaces(Common::String &str);
+ void solidify(byte n);
+ void dodgem();
+ void unDodgem();
+
+ Common::String displayMoney();
+ void easterEgg();
+ void say(int16 x, int16 y, Common::String text);
+ void resetScrollDriver();
+ void ringBell();
+ void loadFont();
+
+ void unSkrimble(Common::String &text);
+ void doTheBubble(Common::String &text);
+ void speak(byte who, byte subject);
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_DIALOGS_H
diff --git a/engines/avalanche/enums.h b/engines/avalanche/enums.h
new file mode 100644
index 0000000000..2b5db67609
--- /dev/null
+++ b/engines/avalanche/enums.h
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_ENUMS_H
+#define AVALANCHE_ENUMS_H
+
+namespace Avalanche {
+enum Color {
+ kColorBlack = 0, kColorBlue, kColorGreen, kColorCyan, kColorRed,
+ kColorMagenta = 5, kColorBrown, kColorLightgray, kColorDarkgray, kColorLightblue,
+ kColorLightgreen = 10, kColorLightcyan, kColorLightred, kColorLightmagenta, kColorYellow,
+ kColorWhite = 15
+};
+
+// CHECKME: kRoomBossKey is a guess
+enum Room {
+ kRoomNowhere = 0, kRoomYours = 1, kRoomOutsideYours = 2, kRoomOutsideSpludwicks = 3,
+ kRoomYourHall = 5, kRoomMusicRoom = 7, kRoomOutsideArgentPub = 9, kRoomArgentRoad = 10,
+ kRoomWiseWomans = 11, kRoomSpludwicks = 12, kRoomInsideAbbey = 13, kRoomOutsideAbbey = 14,
+ kRoomAvvysGarden = 15, kRoomAylesOffice = 16, kRoomArgentPub = 19, kRoomBrummieRoad = 20,
+ kRoomBridge = 21, kRoomLusties = 22, kRoomLustiesRoom = 23, kRoomWestHall = 25,
+ kRoomEastHall = 26, kRoomOubliette = 27, kRoomGeidas = 28, kRoomCatacombs = 29,
+ kRoomEntranceHall = 40, kRoomRobins = 42, kRoomOutsideNottsPub = 46, kRoomNottsPub = 47,
+ kRoomOutsideDucks = 50, kRoomDucks = 51, kRoomOutsideCardiffCastle = 70, kRoomInsideCardiffCastle = 71,
+ kRoomBossKey = 98, kRoomMap = 99, kRoomDummy = 177 // Dummy room
+};
+
+// Objects you can hold:
+enum Object {
+ kObjectWine = 1, kObjectMoney, kObjectBodkin, kObjectPotion, kObjectChastity,
+ kObjectBolt, kObjectCrossbow, kObjectLute, kObjectBadge, kObjectMushroom,
+ kObjectKey, kObjectBell, kObjectPrescription, kObjectPen, kObjectInk,
+ kObjectClothes, kObjectHabit, kObjectOnion, kObjectDummy = 177
+};
+
+// People who hang around this game.
+enum People {
+ // Boys:
+ kPeopleAvalot = 150, kPeopleSpludwick = 151, kPeopleCrapulus = 152, kPeopleDrDuck = 153,
+ kPeopleMalagauche = 154, kPeopleFriarTuck = 155, kPeopleRobinHood = 156, kPeopleCwytalot = 157,
+ kPeopleDuLustie = 158, kPeopleDuke = 159, kPeopleDogfood = 160, kPeopleTrader = 161,
+ kPeopleIbythneth = 162, kPeopleAyles = 163, kPeoplePort = 164, kPeopleSpurge = 165,
+ kPeopleJacques = 166,
+ // Girls:
+ kPeopleArkata = 175, kPeopleGeida = 176, kPeopleInvisible = 177, kPeopleWisewoman = 178,
+ //
+ kPeoplePardon = 254, kPeopleNone = 0
+};
+
+enum VerbCode {
+ kVerbCodeExam = 1, kVerbCodeOpen = 2, kVerbCodePause = 3, kVerbCodeGet = 4, kVerbCodeDrop = 5,
+ kVerbCodeInv = 6, kVerbCodeTalk = 7, kVerbCodeGive = 8, kVerbCodeDrink = 9, kVerbCodeLoad = 10,
+ kVerbCodeSave = 11, kVerbCodePay = 12, kVerbCodeLook = 13, kVerbCodeBreak = 14, kVerbCodeQuit = 15,
+ kVerbCodeSit = 16, kVerbCodeStand = 17, kVerbCodeGo = 18, kVerbCodeInfo = 19, kVerbCodeUndress = 20,
+ kVerbCodeWear = 21, kVerbCodePlay = 22, kVerbCodeRing = 23, kVerbCodeHelp = 24, kVerbCodeLarrypass = 25,
+ kVerbCodePhaon = 26, kVerbCodeBoss = 27, kVerbCodePee = 28, kVerbCodeCheat = 29, kVerbCodeMagic = 30,
+ kVerbCodeRestart = 31, kVerbCodeEat = 32, kVerbCodeListen = 33, kVerbCodeBuy = 34, kVerbCodeAttack = 35,
+ kVerbCodePasswd = 36, kVerbCodeDir = 37, kVerbCodeDie = 38, kVerbCodeScore = 39, kVerbCodePut = 40,
+ kVerbCodeKiss = 41, kVerbCodeClimb = 42, kVerbCodeJump = 43, kVerbCodeHiscores = 44, kVerbCodeWake = 45,
+ kVerbCodeHello = 46, kVerbCodeThanks = 47,
+ kVerbCodeSmartAlec = 249, kVerbCodeExpletive = 253, kVerbCodePardon = 254
+};
+
+enum MouseCursor {
+ kCurUpArrow = 0, kCurScrewDriver = 1, kCurRightArrow = 2, kCurFletch = 3, kCurWait = 4, kCurHand = 5,
+ kCurCrosshair = 6, kCurIBeam = 7
+};
+
+// Magic/portal constants:
+enum Magics {
+ kMagicNothing, // Ignore it if this line is touched.
+ kMagicBounce, // Bounce off this line. Not valid for portals.
+ kMagicExclaim, // Put up a chain of scrolls.
+ kMagicTransport, // Enter new room.
+ kMagicUnfinished, // Unfinished connection.
+ kMagicSpecial, // Special function.
+ kMagicOpenDoor // Opening door.
+};
+
+// Constants to replace the command characters from Pascal.
+// For more information, see: https://github.com/urukgit/avalot/wiki/Scrolldrivers
+enum ControlCharacter {
+ kControlSpeechBubble = 2, // ^B
+ kControlCenter = 3, // ^C
+ kControlToBuffer = 4, // ^D
+ kControlItalic = 6, // ^F
+ kControlBell = 7, // ^G
+ kControlBackspace = 8, // ^H
+ kControlInsertSpaces = 9, // ^I
+ kControlLeftJustified = 12, // ^L
+ kControlNewLine = 13, // ^M
+ kControlParagraph = 16, // ^P
+ kControlQuestion = 17, // ^Q
+ kControlRoman = 18, // ^R
+ kControlRegister = 19, // ^S
+ kControlNegative = 21, // ^U
+ kControlIcon = 22 // ^V
+};
+
+static const int16 kScreenWidth = 640;
+static const int16 kScreenHeight = 200;
+
+static const int16 kWalk = 3;
+static const int16 kRun = 5;
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_ENUMS_H
diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp
new file mode 100644
index 0000000000..841512847f
--- /dev/null
+++ b/engines/avalanche/graphics.cpp
@@ -0,0 +1,767 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/graphics.h"
+
+#include "engines/util.h"
+#include "graphics/palette.h"
+
+namespace Avalanche {
+
+const byte GraphicManager::kEgaPaletteIndex[16] = {0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63};
+
+const MouseHotspotType GraphicManager::kMouseHotSpots[9] = {
+ {8,0}, // 0 - up-arrow
+ {0,0}, // 1 - screwdriver
+ {15,6}, // 2 - right-arrow
+ {0,0}, // 3 - fletch
+ {8,7}, // 4 - hourglass
+ {4,0}, // 5 - TTHand
+ {8,5}, // 6 - Mark's crosshairs
+ {8,7}, // 7 - I-beam
+ {0,0} // 8 - question mark
+};
+
+GraphicManager::GraphicManager(AvalancheEngine *vm) {
+ _vm = vm;
+ setDialogColor(kColorBlack, kColorWhite);
+}
+
+GraphicManager::~GraphicManager() {
+ _surface.free();
+ _magics.free();
+ _background.free();
+ _screen.free();
+ _scrolls.free();
+ _backup.free();
+
+ for (int i = 0; i < 10; i++)
+ _digits[i].free();
+ for (int i = 0; i < 9; i++)
+ _directions[i].free();
+}
+
+void GraphicManager::init() {
+ initGraphics(kScreenWidth, kScreenHeight * 2, true); // Doubling the height.
+
+ for (int i = 0; i < 64; ++i) {
+ _egaPalette[i][0] = (i >> 2 & 1) * 0xaa + (i >> 5 & 1) * 0x55;
+ _egaPalette[i][1] = (i >> 1 & 1) * 0xaa + (i >> 4 & 1) * 0x55;
+ _egaPalette[i][2] = (i & 1) * 0xaa + (i >> 3 & 1) * 0x55;
+ }
+
+ for (int i = 0; i < 16; i++)
+ g_system->getPaletteManager()->setPalette(_egaPalette[kEgaPaletteIndex[i]], i, 1);
+
+ // Set the "flesh colors":
+ g_system->getPaletteManager()->setPalette(_egaPalette[39], 13, 1);
+ g_system->getPaletteManager()->setPalette(_egaPalette[28], 5, 1);
+
+ _surface.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
+ _magics.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
+ _screen.create(kScreenWidth, kScreenHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
+ _scrolls.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
+}
+
+/**
+ * Load the scoring digits & rwlites
+ * @remarks Originally called 'load_digits'
+ */
+void GraphicManager::loadDigits() {
+ const byte digitsize = 134;
+ const byte rwlitesize = 126;
+
+ Common::File file;
+ if (!file.open("digit.avd"))
+ error("AVALANCHE: File not found: digit.avd");
+
+ for (int i = 0; i < 10; i++) {
+ file.seek(i * digitsize);
+ _digits[i] = loadPictureGraphic(file);
+ }
+
+ for (int i = 0; i < 9; i++) {
+ file.seek(10 * digitsize + i * rwlitesize);
+ _directions[i] = loadPictureGraphic(file);
+ }
+
+ file.close();
+}
+
+void GraphicManager::loadMouse(byte which) {
+ if (which == _vm->_currentMouse)
+ return;
+
+ _vm->_currentMouse = which;
+
+ Common::File f;
+ if (!f.open("mice.avd"))
+ error("AVALANCHE: Gyro: File not found: mice.avd");
+
+ Graphics::Surface cursor;
+ cursor.create(16, 32, Graphics::PixelFormat::createFormatCLUT8());
+ cursor.fillRect(Common::Rect(0, 0, 16, 32), 255);
+
+ // The AND mask.
+ f.seek(kMouseSize * 2 * which + 134);
+
+ Graphics::Surface mask = loadPictureGraphic(f);
+
+ for (int j = 0; j < mask.h; j++) {
+ for (int i = 0; i < mask.w; i++) {
+ byte pixel = *(byte *)mask.getBasePtr(i, j);
+ if (pixel == 0) {
+ *(byte *)cursor.getBasePtr(i, j * 2 ) = 0;
+ *(byte *)cursor.getBasePtr(i, j * 2 + 1) = 0;
+ }
+ }
+ }
+
+ mask.free();
+
+ // The OR mask.
+ f.seek(kMouseSize * 2 * which + 134 * 2);
+
+ mask = loadPictureGraphic(f);
+
+ for (int j = 0; j < mask.h; j++) {
+ for (int i = 0; i < mask.w; i++) {
+ byte pixel = *(byte *)mask.getBasePtr(i, j);
+ if (pixel != 0) {
+ *(byte *)cursor.getBasePtr(i, j * 2 ) = pixel;
+ *(byte *)cursor.getBasePtr(i, j * 2 + 1) = pixel;
+ }
+ }
+ }
+
+ mask.free();
+ f.close();
+
+ CursorMan.replaceCursor(cursor.getPixels(), 16, 32, kMouseHotSpots[which]._horizontal, kMouseHotSpots[which]._vertical * 2, 255, false);
+ cursor.free();
+}
+
+void GraphicManager::drawThinkPic(Common::String filename, int id) {
+ static const int16 picSize = 966;
+ Common::File file;
+ if (!file.open(filename))
+ error("drawThinkPic(): File not found: %s", filename.c_str());
+
+ file.seek(id * picSize + 65);
+ Graphics::Surface picture = loadPictureGraphic(file);
+ drawPicture(_surface, picture, 205, 170);
+
+ picture.free();
+ file.close();
+}
+
+void GraphicManager::drawToolbar() {
+ Common::File file;
+ if (!file.open("useful.avd"))
+ error("drawToolbar(): File not found: useful.avd");
+
+ file.seek(40);
+
+ CursorMan.showMouse(false);
+ Graphics::Surface picture = loadPictureGraphic(file);
+ drawPicture(_surface, picture, 5, 169);
+ CursorMan.showMouse(true);
+
+ picture.free();
+ file.close();
+}
+
+Common::Point GraphicManager::drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color) {
+ Common::Point endPoint;
+ const float convfac = M_PI / 180.0;
+
+ int32 xRadius = radius;
+ int32 yRadius = radius * kScreenWidth / (8 * kScreenHeight); // Just don't ask why...
+
+ if (xRadius == 0)
+ xRadius++;
+ if (yRadius == 0)
+ yRadius++;
+
+ // Check for an ellipse with negligable x and y radius.
+ if ((xRadius <= 1) && (yRadius <= 1)) {
+ *(byte *)_scrolls.getBasePtr(x, y) = color;
+ endPoint.x = x;
+ endPoint.y = y;
+ return endPoint;
+ }
+
+ // Check if valid angles.
+ stAngle = stAngle % 361;
+ endAngle = endAngle % 361;
+
+ // If impossible angles, then swap them!
+ if (endAngle < stAngle) {
+ uint16 tmpAngle=endAngle;
+ endAngle=stAngle;
+ stAngle=tmpAngle;
+ }
+
+ // Approximate the number of pixels required by using the circumference equation of an ellipse.
+ uint16 numOfPixels = (uint16)floor(sqrt(3.0) * sqrt(pow(double(xRadius), 2) + pow(double(yRadius), 2)) + 0.5);
+
+ // Calculate the angle precision required.
+ float delta = 90.0 / numOfPixels;
+
+ // Always just go over the first 90 degrees. Could be optimized a
+ // bit if startAngle and endAngle lie in the same quadrant, left as an
+ // exercise for the reader. :)
+ float j = 0;
+
+ // Calculate stop position, go 1 further than 90 because otherwise 1 pixel is sometimes not drawn.
+ uint16 deltaEnd = 91;
+
+ // Set the end point.
+ float tempTerm = endAngle * convfac;
+ endPoint.x = (int16)floor(xRadius * cos(tempTerm) + 0.5) + x;
+ endPoint.y = (int16)floor(yRadius * sin(tempTerm + M_PI) + 0.5) + y;
+
+ // Calculate points.
+ int16 xNext = xRadius;
+ int16 yNext = 0;
+ do {
+ int16 xTemp = xNext;
+ int16 yTemp = yNext;
+ // This is used by both sin and cos.
+ tempTerm = (j + delta) * convfac;
+
+ xNext = (int16)floor(xRadius * cos(tempTerm) + 0.5);
+ yNext = (int16)floor(yRadius * sin(tempTerm + M_PI) + 0.5);
+
+ int16 xp = x + xTemp;
+ int16 xm = x - xTemp;
+ int16 yp = y + yTemp;
+ int16 ym = y - yTemp;
+
+ if ((j >= stAngle) && (j <= endAngle))
+ *(byte *)_scrolls.getBasePtr(xp, yp) = color;
+
+ if (((180 - j) >= stAngle) && ((180 - j) <= endAngle))
+ *(byte *)_scrolls.getBasePtr(xm, yp) = color;
+
+ if (((j + 180) >= stAngle) && ((j + 180) <= endAngle))
+ *(byte *)_scrolls.getBasePtr(xm, ym) = color;
+
+ if (((360 - j) >= stAngle) && ((360 - j) <= endAngle))
+ *(byte *)_scrolls.getBasePtr(xp, ym) = color;
+
+ j += delta;
+ } while (j <= deltaEnd);
+
+ return endPoint;
+}
+
+Common::Point GraphicManager::drawScreenArc(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color) {
+ return drawArc(_surface, x, y, stAngle, endAngle, radius, color);
+}
+
+void GraphicManager::drawPieSlice(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color) {
+ while (radius > 0)
+ drawArc(_scrolls, x, y, stAngle, endAngle, radius--, color);
+}
+
+void GraphicManager::drawTriangle(Common::Point *p, Color color) {
+ // Draw the borders with a marking color.
+ _scrolls.drawLine(p[0].x, p[0].y, p[1].x, p[1].y, 255);
+ _scrolls.drawLine(p[1].x, p[1].y, p[2].x, p[2].y, 255);
+ _scrolls.drawLine(p[2].x, p[2].y, p[0].x, p[0].y, 255);
+
+ // Get the top and the bottom of the triangle.
+ uint16 maxY = p[0].y, minY = p[0].y;
+ for (int i = 1; i < 3; i++) {
+ if (p[i].y < minY)
+ minY = p[i].y;
+ if (p[i].y > maxY)
+ maxY = p[i].y;
+ }
+
+ // Fill the triangle.
+ for (uint16 y = minY; y <= maxY; y++) {
+ uint16 x = 0;
+ while (*(byte *)_scrolls.getBasePtr(x, y) != 255)
+ x++;
+ uint16 minX = x;
+ uint16 maxX = x;
+ x++;
+ while ((*(byte *)_scrolls.getBasePtr(x, y) != 255) && (x != 639))
+ x++;
+ if (x != 639)
+ maxX = x;
+ if (minX != maxX)
+ _scrolls.drawLine(minX, y, maxX, y, color);
+ }
+
+ // Redraw the borders with the actual color.
+ _scrolls.drawLine(p[0].x, p[0].y, p[1].x, p[1].y, color);
+ _scrolls.drawLine(p[1].x, p[1].y, p[2].x, p[2].y, color);
+ _scrolls.drawLine(p[2].x, p[2].y, p[0].x, p[0].y, color);
+}
+
+void GraphicManager::drawText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) {
+ for (uint i = 0; i < text.size(); i++) {
+ for (int j = 0; j < fontHeight; j++) {
+ byte pixel = font[(byte)text[i]][j];
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ if (pixelBit)
+ *(byte *)surface.getBasePtr(x + i * 8 + 7 - bit, y + j) = color;
+ }
+ }
+ }
+}
+
+void GraphicManager::drawNormalText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) {
+ drawText(_surface, text, font, fontHeight, x, y, color);
+}
+
+void GraphicManager::drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) {
+ drawText(_scrolls, text, font, fontHeight, x, y, color);
+}
+
+void GraphicManager::drawDigit(int index, int x, int y) {
+ drawPicture(_surface, _digits[index], x, y);
+}
+
+void GraphicManager::drawDirection(int index, int x, int y) {
+ drawPicture(_surface, _directions[index], x, y);
+}
+
+void GraphicManager::drawScrollShadow(int16 x1, int16 y1, int16 x2, int16 y2) {
+ for (byte i = 0; i < 2; i ++) {
+ _scrolls.fillRect(Common::Rect(x1 + i, y1 + i, x1 + i + 1, y2 - i), kColorWhite);
+ _scrolls.fillRect(Common::Rect(x1 + i, y1 + i, x2 - i, y1 + i + 1), kColorWhite);
+
+ _scrolls.fillRect(Common::Rect(x2 - i, y1 + i, x2 - i + 1, y2 - i + 1), kColorDarkgray);
+ _scrolls.fillRect(Common::Rect(x1 + i, y2 - i, x2 - i, y2 - i + 1), kColorDarkgray);
+ }
+}
+
+void GraphicManager::drawShadowBox(int16 x1, int16 y1, int16 x2, int16 y2, Common::String text) {
+ CursorMan.showMouse(false);
+
+ drawScrollShadow(x1, y1, x2, y2);
+
+ bool offset = text.size() % 2;
+ x1 = (x2 - x1) / 2 + x1 - text.size() / 2 * 8 - offset * 3;
+ y1 = (y2 - y1) / 2 + y1 - 4;
+ drawScrollText(text, _vm->_font, 8, x1, y1, kColorBlue);
+ drawScrollText(Common::String('_'), _vm->_font, 8, x1, y1, kColorBlue);
+
+ CursorMan.showMouse(true);
+}
+
+void GraphicManager::drawMenuBar(Color color) {
+ _surface.fillRect(Common::Rect(0, 0, 640, 10), color);
+}
+
+void GraphicManager::drawMenuBlock(int x1, int y1, int x2, int y2, Color color) {
+ _surface.fillRect(Common::Rect(x1, y1, x2, y2), color);
+}
+
+void GraphicManager::drawMenuItem(int x1, int y1, int x2, int y2) {
+ _surface.fillRect(Common::Rect(x1, y1, x2, y2), kMenuBackgroundColor);
+ _surface.frameRect(Common::Rect(x1 - 1, y1 - 1, x2 + 1, y2 + 1), kMenuBorderColor);
+}
+
+void GraphicManager::drawSpeedBar(int speed) {
+ if (speed == kRun) {
+ _surface.drawLine(336, 199, 338, 199, kColorLightblue);
+ _surface.drawLine(371, 199, 373, 199, kColorYellow);
+ } else {
+ _surface.drawLine(371, 199, 373, 199, kColorLightblue);
+ _surface.drawLine(336, 199, 338, 199, kColorYellow);
+ }
+}
+void GraphicManager::drawScroll(int mx, int lx, int my, int ly) {
+ _scrolls.copyFrom(_surface);
+
+ // The right corners of the scroll.
+ drawPieSlice(mx + lx, my - ly, 0, 90, 15, kColorLightgray);
+ drawPieSlice(mx + lx, my + ly, 270, 360, 15, kColorLightgray);
+ drawArc(_scrolls, mx + lx, my - ly, 0, 90, 15, kColorRed);
+ drawArc(_scrolls, mx + lx, my + ly, 270, 360, 15, kColorRed);
+
+ // The body of the scroll.
+ _scrolls.fillRect(Common::Rect(mx - lx - 30, my + ly, mx + lx, my + ly + 6), kColorLightgray);
+ _scrolls.fillRect(Common::Rect(mx - lx - 30, my - ly - 6, mx + lx, my - ly + 1), kColorLightgray);
+ _scrolls.fillRect(Common::Rect(mx - lx - 15, my - ly, mx + lx + 15, my + ly + 1), kColorLightgray);
+
+ // The left corners of the scroll.
+ drawPieSlice(mx - lx - 31, my - ly, 0, 180, 15, kColorDarkgray);
+ drawArc(_scrolls, mx - lx - 31, my - ly, 0, 180, 15, kColorRed);
+ _scrolls.drawLine(mx - lx - 31 - 15, my - ly, mx - lx - 31 + 15, my - ly, kColorRed);
+ drawPieSlice(mx - lx - 31, my + ly, 180, 360, 15, kColorDarkgray);
+ drawArc(_scrolls, mx - lx - 31, my + ly, 180, 360, 15, kColorRed);
+ _scrolls.drawLine(mx - lx - 31 - 15, my + ly, mx - lx - 31 + 15, my + ly, kColorRed);
+
+ // The rear borders of the scroll.
+ _scrolls.fillRect(Common::Rect(mx - lx - 30, my - ly - 6, mx + lx, my - ly - 5), kColorRed);
+ _scrolls.fillRect(Common::Rect(mx - lx - 30, my + ly + 6, mx + lx, my + ly + 7), kColorRed);
+ _scrolls.fillRect(Common::Rect(mx - lx - 15, my - ly, mx - lx - 14, my + ly), kColorRed);
+ _scrolls.fillRect(Common::Rect(mx + lx + 15, my - ly, mx + lx + 16, my + ly), kColorRed);
+}
+
+void GraphicManager::drawBackgroundSprite(int16 x, int16 y, SpriteType &sprite) {
+ drawPicture(_background, sprite._picture, x, y);
+}
+
+void GraphicManager::drawDebugLines() {
+ if (!_vm->_showDebugLines)
+ return;
+
+ for (int i = 0; i < _vm->_lineNum; i++) {
+ LineType *curLine = &_vm->_lines[i];
+ _surface.drawLine(curLine->_x1, curLine->_y1, curLine->_x2, curLine->_y2, curLine->_color);
+ }
+
+ for (int i = 0; i < _vm->_fieldNum; i++) {
+ FieldType *curField = &_vm->_fields[i];
+ if (curField->_x1 < 640)
+ _surface.frameRect(Common::Rect(curField->_x1, curField->_y1, curField->_x2, curField->_y2), kColorLightmagenta);
+ }
+}
+
+/**
+ * This function mimics Pascal's getimage().
+ */
+Graphics::Surface GraphicManager::loadPictureGraphic(Common::File &file) {
+ // The height and the width are stored in 2-2 bytes. We have to add 1 to each because Pascal stores the value of them -1.
+ uint16 width = file.readUint16LE() + 1;
+ uint16 height = file.readUint16LE() + 1;
+
+ Graphics::Surface picture; // We make a Surface object for the picture itself.
+ picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Produce the picture. We read it in row-by-row, and every row has 4 planes.
+ for (int y = 0; y < height; y++) {
+ for (int8 plane = 3; plane >= 0; plane--) { // The planes are in the opposite way.
+ for (uint16 x = 0; x < width; x += 8) {
+ byte pixel = file.readByte();
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ if (pixelBit != 0)
+ *(byte *)picture.getBasePtr(x + 7 - bit, y) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+ return picture;
+}
+
+/**
+ * Reads Row-planar EGA data.
+ * This function is our own creation, very much like the one above. The main differences are that
+ * we don't read the width and the height from the file, the planes are in a different order
+ * and we read the picture plane-by-plane.
+ */
+Graphics::Surface GraphicManager::loadPictureRaw(Common::File &file, uint16 width, uint16 height) {
+ Graphics::Surface picture;
+ picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int plane = 0; plane < 4; plane++) {
+ for (uint16 y = 0; y < height; y++) {
+ for (uint16 x = 0; x < width; x += 8) {
+ byte pixel = file.readByte();
+ for (int i = 0; i < 8; i++) {
+ byte pixelBit = (pixel >> i) & 1;
+ *(byte *)picture.getBasePtr(x + 7 - i, y) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+
+ return picture;
+}
+
+void GraphicManager::clearAlso() {
+ _magics.fillRect(Common::Rect(0, 0, 640, 200), 0);
+ _magics.frameRect(Common::Rect(0, 45, 640, 161), 15);
+}
+
+void GraphicManager::clearTextBar() {
+ _surface.fillRect(Common::Rect(24, 161, 640, 169), kColorBlack); // Black out the line of the text.
+}
+
+void GraphicManager::setAlsoLine(int x1, int y1, int x2, int y2, Color color) {
+ _magics.drawLine(x1, y1, x2, y2, color);
+}
+
+void GraphicManager::drawScreenLine(int16 x, int16 y, int16 x2, int16 y2, Color color) {
+ _surface.drawLine(x, y, x2, y2, color);
+}
+
+byte GraphicManager::getAlsoColor(int x1, int y1, int x2, int y2) {
+ byte returnColor = 0;
+ for (int16 i = x1; i <= x2; i++) {
+ for (int16 j = y1; j <= y2; j++) {
+ byte actColor = *(byte *)_magics.getBasePtr(i, j);
+ returnColor = MAX(returnColor, actColor);
+ }
+ }
+
+ return returnColor;
+}
+
+byte GraphicManager::getScreenColor(Common::Point pos) {
+ return *(byte *)_surface.getBasePtr(pos.x, pos.y / 2);
+}
+
+void GraphicManager::drawSprite(AnimationType *sprite, byte picnum, int16 x, int16 y) {
+ // First we make the pixels of the sprite blank.
+ for (int j = 0; j < sprite->_yLength; j++) {
+ for (int i = 0; i < sprite->_xLength; i++) {
+ if ((x + i < _surface.w) && (y + j < _surface.h)) {
+ if (((*sprite->_sil[picnum])[j][i / 8] >> ((7 - i % 8)) & 1) == 0)
+ *(byte *)_surface.getBasePtr(x + i, y + j) = 0;
+ }
+ }
+ }
+
+ // Then we draw the picture to the blank places.
+ uint16 maniPos = 0; // Because the original manitype starts at 5!!! See Graphics.h for definition.
+
+ for (int j = 0; j < sprite->_yLength; j++) {
+ for (int8 plane = 3; plane >= 0; plane--) { // The planes are in the opposite way.
+ for (uint16 i = 0; i < sprite->_xLength; i += 8) {
+ byte pixel = (*sprite->_mani[picnum])[maniPos++];
+ for (int bit = 0; bit < 8; bit++) {
+ if ((x + i + 7 < _surface.w) && (y + j < _surface.h)) {
+ byte pixelBit = (pixel >> bit) & 1;
+ *(byte *)_surface.getBasePtr(x + i + 7 - bit, y + j) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+ }
+}
+
+void GraphicManager::drawPicture(Graphics::Surface &target, const Graphics::Surface picture, uint16 destX, uint16 destY) {
+ // Copy the picture to the given place on the screen.
+ uint16 maxX = picture.w;
+ uint16 maxY = picture.h;
+
+ if (destX + maxX > target.w)
+ maxX = target.w - destX;
+
+ if (destY + maxY > target.h)
+ maxY = target.h - destY;
+
+ for (uint16 y = 0; y < maxY; y++) {
+ for (uint16 x = 0; x < maxX; x++)
+ *(byte *)target.getBasePtr(x + destX, y + destY) = *(const byte *)picture.getBasePtr(x, y);
+ }
+}
+
+void GraphicManager::drawCursor(byte pos) {
+ int pixPos = 24 + (pos * 8);
+ // Draw the '_' character.
+ for (int i = 0; i < 8; i++)
+ *(byte *)_surface.getBasePtr(pixPos + i, 168) = kColorWhite;
+}
+
+void GraphicManager::drawReadyLight(Color color) {
+ _surface.fillRect(Common::Rect(419, 195, 438, 197), color);
+}
+
+/**
+ * This is for drawing a big "about" or "gameover" picture loaded from a file into an empty scroll.
+ */
+void GraphicManager::drawSign(Common::String fn, int16 xl, int16 yl, int16 y) {
+ Common::File file;
+ Common::String filename = Common::String::format("%s.avd", fn.c_str());
+
+ if (!file.open(filename))
+ error("AVALANCHE: Scrolls: File not found: %s", filename.c_str());
+
+ // I know it looks very similar to the loadPicture methods, but in truth it's the combination of the two.
+ uint16 width = xl * 8;
+ uint16 height = yl;
+
+ Graphics::Surface sign; // We make a Surface object for the picture itself.
+ sign.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Produce the picture. We read it in row-by-row, and every row has 4 planes.
+ for (int yy = 0; yy < height; yy++) {
+ for (int8 plane = 0; plane < 4; plane++) { // The planes are in the "right" order.
+ for (uint16 xx = 0; xx < width; xx += 8) {
+ byte pixel = file.readByte();
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ if (pixelBit != 0)
+ *(byte *)sign.getBasePtr(xx + 7 - bit, yy) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+
+ drawPicture(_scrolls, sign, kScreenWidth / 2 - width / 2, y);
+
+ file.close();
+}
+
+/**
+ * Draws an icon to the current scroll.
+ * @remarks Originally called 'geticon'
+ */
+void GraphicManager::drawIcon(int16 x, int16 y, byte which) {
+ Common::File file;
+
+ if (!file.open("icons.avd"))
+ error("AVALANCHE: Scrolls: File not found: icons.avd");
+
+ which--;
+ file.seek(which * 426);
+
+ Graphics::Surface icon = loadPictureGraphic(file);
+ drawPicture(_scrolls, icon, x, y);
+
+ icon.free();
+ file.close();
+}
+
+void GraphicManager::prepareBubble(int xc, int xw, int my, Common::Point points[3]) {
+ // Backup the screen before drawing the bubble.
+ _scrolls.copyFrom(_surface);
+
+ int16 talkX = _vm->_dialogs->getTalkPosX();
+ // The body of the bubble.
+ _scrolls.fillRect(Common::Rect(xc + talkX - xw + 9, 7, talkX + xw - 8 + xc, my + 1), _talkBackgroundColor);
+ _scrolls.fillRect(Common::Rect(xc + talkX - xw - 1, 12, talkX + xw + xc + 2, my - 4), _talkBackgroundColor);
+
+ // Top the 4 rounded corners of the bubble.
+ drawPieSlice(xc + talkX + xw - 10, 11, 0, 90, 9, _talkBackgroundColor);
+ drawPieSlice(xc + talkX + xw - 10, my - 4, 270, 360, 9, _talkBackgroundColor);
+ drawPieSlice(xc + talkX - xw + 10, 11, 90, 180, 9, _talkBackgroundColor);
+ drawPieSlice(xc + talkX - xw + 10, my - 4, 180, 270, 9, _talkBackgroundColor);
+
+ // "Tail" of the speech bubble.
+ drawTriangle(points, _talkBackgroundColor);
+}
+
+/**
+ * Set the background of the text to the desired color.
+ */
+void GraphicManager::wipeChar(int x, int y, Color color) {
+ for (int k = 0; k < 8; k++)
+ *(byte *)_surface.getBasePtr(x + k, y) = color;
+}
+
+void GraphicManager::drawChar(byte ander, int x, int y, Color color) {
+ byte pixel = ander;
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ if (pixelBit)
+ *(byte *)_surface.getBasePtr(x + 7 - bit, y) = color;
+ }
+}
+void GraphicManager::refreshScreen() {
+ // These cycles are for doubling the screen height.
+ for (uint16 y = 0; y < _screen.h / 2; y++) {
+ memcpy(_screen.getBasePtr(0, y * 2), _surface.getBasePtr(0, y), _screen.w);
+ memcpy(_screen.getBasePtr(0, y * 2 + 1), _surface.getBasePtr(0, y), _screen.w);
+ }
+ // Now we copy the stretched picture to the screen.
+ g_system->copyRectToScreen(_screen.getPixels(), _screen.pitch, 0, 0, kScreenWidth, kScreenHeight * 2);
+ g_system->updateScreen();
+}
+
+void GraphicManager::loadBackground(Common::File &file) {
+ _background.free();
+ _background = loadPictureRaw(file, kBackgroundWidth, kBackgroundHeight);
+}
+
+void GraphicManager::refreshBackground() {
+ drawPicture(_surface, _background, 0, 10);
+}
+
+/**
+ * Only used when entering the map.
+ * @remarks Originally called 'zoomout'
+ */
+void GraphicManager::zoomOut(int16 x, int16 y) {
+ //setlinestyle(dottedln, 0, 1); TODO: Implement it with a dotted line style!!!
+
+ saveScreen();
+ for (byte i = 1; i <= 20; i ++) {
+ int16 x1 = x - (x / 20) * i;
+ int16 y1 = y - ((y - 10) / 20) * i;
+ int16 x2 = x + (((639 - x) / 20) * i);
+ int16 y2 = y + (((161 - y) / 20) * i);
+
+ _surface.frameRect(Common::Rect(x1, y1, x2, y2), kColorWhite);
+ refreshScreen();
+ _vm->_system->delayMillis(17);
+
+ restoreScreen();
+ }
+ removeBackup();
+}
+
+void GraphicManager::showScroll() {
+ _surface.copyFrom(_scrolls); // TODO: Rework it using getSubArea !!!!!!!
+}
+
+void GraphicManager::getNaturalPicture(SpriteType &sprite) {
+ sprite._type = kNaturalImage; // We simply read from the screen and later, in drawSprite() we draw it right back.
+ sprite._size = sprite._xl * 8 * sprite._yl + 1;
+ sprite._picture.create(sprite._xl * 8, sprite._yl + 1, Graphics::PixelFormat::createFormatCLUT8());
+ for (uint16 y = 0; y < sprite._yl + 1; y++) {
+ for (uint16 x = 0; x < sprite._xl * 8; x++)
+ *(byte *)sprite._picture.getBasePtr(x, y) = *(byte *)_vm->_graphics->_surface.getBasePtr(sprite._x * 8 + x, sprite._y + y);
+ }
+}
+
+void GraphicManager::saveScreen() {
+ _backup.copyFrom(_surface);
+}
+
+void GraphicManager::removeBackup() {
+ _backup.free();
+}
+
+void GraphicManager::restoreScreen() {
+ _surface.copyFrom(_backup);
+ refreshScreen();
+}
+
+void GraphicManager::setDialogColor(Color bg, Color text) {
+ _talkBackgroundColor = bg;
+ _talkFontColor = text;
+}
+
+// Original name background()
+void GraphicManager::setBackgroundColor(Color x) {
+ warning("STUB: setBackgroundColor()");
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h
new file mode 100644
index 0000000000..4af6d4e8db
--- /dev/null
+++ b/engines/avalanche/graphics.h
@@ -0,0 +1,142 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_GRAPHICS_H
+#define AVALANCHE_GRAPHICS_H
+
+#include "avalanche/enums.h"
+
+#include "common/file.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+class AnimationType;
+struct SpriteType;
+
+typedef byte FontType[256][16];
+typedef byte ManiType[2049];
+typedef byte SilType[51][11]; // 35, 4
+
+struct MouseHotspotType {
+ int16 _horizontal, _vertical;
+};
+
+class GraphicManager {
+public:
+ static const MouseHotspotType kMouseHotSpots[9];
+ Color _talkBackgroundColor, _talkFontColor;
+
+ GraphicManager(AvalancheEngine *vm);
+ ~GraphicManager();
+ void init();
+ void loadDigits();
+ void loadMouse(byte which);
+
+ Common::Point drawScreenArc(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
+ void drawPieSlice(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
+ void drawTriangle(Common::Point *p, Color color);
+ void drawNormalText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
+ void drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
+ void drawDigit(int index, int x, int y);
+ void drawDirection(int index, int x, int y);
+ void drawScrollShadow(int16 x1, int16 y1, int16 x2, int16 y2);
+ void drawShadowBox(int16 x1, int16 y1, int16 x2, int16 y2, Common::String text);
+ void drawScroll(int mx, int lx, int my, int ly);
+ void drawMenuBar(Color color);
+ void drawSpeedBar(int speed);
+ void drawBackgroundSprite(int16 x, int16 y, SpriteType &sprite);
+ void drawMenuBlock(int x1, int y1, int x2, int y2, Color color);
+ void drawMenuItem(int x1, int y1, int x2, int y2);
+ void wipeChar(int x, int y, Color color);
+ void drawChar(byte ander, int x, int y, Color color);
+ void drawDebugLines();
+
+ void clearAlso();
+ void clearTextBar();
+ void setAlsoLine(int x1, int y1, int x2, int y2, Color color);
+ byte getAlsoColor(int x1, int y1, int x2, int y2);
+ byte getScreenColor(Common::Point pos);
+
+ // The caller has to .free() the returned Surfaces!!!
+ // Further information about these two: http://www.shikadi.net/moddingwiki/Raw_EGA_data
+ Graphics::Surface loadPictureRaw(Common::File &file, uint16 width, uint16 height);
+
+ void drawSprite(AnimationType *sprite, byte picnum, int16 x, int16 y);
+ void drawPicture(Graphics::Surface &target, const Graphics::Surface picture, uint16 destX, uint16 destY);
+ void drawThinkPic(Common::String filename, int id);
+ void drawToolbar();
+ void drawCursor(byte pos);
+ void drawReadyLight(Color color);
+ void drawSign(Common::String name, int16 xl, int16 yl, int16 y);
+ void drawIcon(int16 x, int16 y, byte which);
+ void drawScreenLine(int16 x, int16 y, int16 x2, int16 y2, Color color);
+ void prepareBubble(int xc, int xw, int my, Common::Point points[3]);
+ void refreshScreen();
+ void loadBackground(Common::File &file);
+ void refreshBackground();
+ void setBackgroundColor(Color x);
+ void setDialogColor(Color bg, Color text);
+
+ void zoomOut(int16 x, int16 y);
+ void showScroll();
+ void getNaturalPicture(SpriteType &sprite);
+
+ void saveScreen();
+ void removeBackup();
+ void restoreScreen();
+
+private:
+ static const uint16 kBackgroundWidth = kScreenWidth;
+ static const byte kEgaPaletteIndex[16];
+ static const byte kBackgroundHeight = 8 * 12080 / kScreenWidth; // With 640 width it's 151.
+ // The 8 = number of bits in a byte, and 12080 comes from Lucerna::load().
+
+ Graphics::Surface _background;
+ Graphics::Surface _backup;
+ Graphics::Surface _digits[10]; // digitsize and rwlitesize are defined in loadDigits() !!!
+ Graphics::Surface _directions[9]; // Maybe it will be needed to move them to the class itself instead.
+ Graphics::Surface _magics; // Lucerna::draw_also_lines() draws the "magical" lines here. Further information: https://github.com/urukgit/avalot/wiki/Also
+ Graphics::Surface _screen; // Only used in refreshScreen() to make it more optimized. (No recreation of it at every call of the function.)
+ Graphics::Surface _scrolls;
+ Graphics::Surface _surface;
+ byte _egaPalette[64][3];
+
+ AvalancheEngine *_vm;
+
+ Graphics::Surface loadPictureGraphic(Common::File &file); // Reads Graphic-planar EGA data.
+ void drawText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
+ // Taken from Free Pascal's Procedure InternalEllipseDefault. Used to replace Pascal's procedure arc.
+ // Returns the end point of the arc. (Needed in Clock.)
+ // TODO: Make it more accurate later.
+ Common::Point drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_GRAPHICS_H
diff --git a/engines/avalanche/menu.cpp b/engines/avalanche/menu.cpp
new file mode 100644
index 0000000000..c3fa709ee4
--- /dev/null
+++ b/engines/avalanche/menu.cpp
@@ -0,0 +1,844 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: DROPDOWN A customized version of Oopmenu (qv). */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/menu.h"
+
+namespace Avalanche {
+
+void HeadType::init(char trig, char altTrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, Menu *menu) {
+ _trigger = trig;
+ _altTrigger = altTrig;
+ _title = title;
+ _position = pos;
+ _xpos = _position * _menu->kSpacing + _menu->kIndent;
+ _xright = (_position + 1) * _menu->kSpacing + _menu->kIndent;
+ _setupFunc = setupFunc;
+ _chooseFunc = chooseFunc;
+
+ _menu = menu;
+}
+
+void HeadType::draw() {
+ CursorMan.showMouse(false);
+ _menu->drawMenuText(_xpos, 1, _trigger, _title, true, false);
+ CursorMan.showMouse(true);
+}
+
+void HeadType::highlight() {
+ CursorMan.showMouse(false);
+
+ _menu->_vm->_sound->stopSound();
+ _menu->drawMenuText(_xpos, 1, _trigger, _title, true, true);
+
+ _menu->_activeMenuItem._left = _xpos;
+ _menu->_activeMenuItem._activeNow = true;
+ _menu->_activeMenuItem._activeNum = _position;
+ _menu->_menuActive = true;
+
+ // Force reload and redraw of cursor.
+ _menu->_vm->_currentMouse = 177;
+
+}
+
+bool HeadType::parseAltTrigger(char key) {
+ if (key != _altTrigger)
+ return true;
+ return false;
+}
+
+void MenuItem::init(Menu *menu) {
+ _menu = menu;
+
+ _activeNow = false;
+ _activeNum = 1;
+ _menu->_menuActive = false;
+}
+
+void MenuItem::reset() {
+ _optionNum = 0;
+ _width = 0;
+ _firstlix = false;
+ _oldY = 0;
+ _highlightNum = 0;
+}
+
+void MenuItem::setupOption(Common::String title, char trigger, Common::String shortcut, bool valid) {
+ uint16 width = (title + shortcut).size() + 3;
+ if (_width < width)
+ _width = width;
+
+ _options[_optionNum]._title = title;
+ _options[_optionNum]._trigger = trigger;
+ _options[_optionNum]._shortcut = shortcut;
+ _options[_optionNum]._valid = valid;
+ _optionNum++;
+}
+
+void MenuItem::displayOption(byte y, bool highlit) {
+ Common::String text = _options[y]._title;
+ while (text.size() + _options[y]._shortcut.size() < _width)
+ text += ' '; // Pad _options[y] with spaces.
+ text += _options[y]._shortcut;
+
+ Color backgroundColor;
+ if (highlit)
+ backgroundColor = kColorBlack;
+ else
+ backgroundColor = kColorLightgray;
+
+ _menu->_vm->_graphics->drawMenuBlock((_flx1 + 1) * 8, 3 + (y + 1) * 10, (_flx2 + 1) * 8, 13 + (y + 1) * 10, backgroundColor);
+ _menu->drawMenuText(_left, 4 + (y + 1) * 10, _options[y]._trigger, text, _options[y]._valid, highlit);
+}
+
+void MenuItem::display() {
+ CursorMan.showMouse(false);
+
+ _firstlix = true;
+ _flx1 = _left - 2;
+ _flx2 = _left + _width;
+ _fly = 15 + _optionNum * 10;
+ _activeNow = true;
+ _menu->_menuActive = true;
+
+ _menu->_vm->_graphics->drawMenuItem((_flx1 + 1) * 8, 12, (_flx2 + 1) * 8, _fly);
+
+ displayOption(0, true);
+ for (int y = 1; y < _optionNum; y++)
+ displayOption(y, false);
+
+ _menu->_vm->_currentMouse = 177;
+
+ CursorMan.showMouse(true); // 4 = fletch
+}
+
+void MenuItem::wipe() {
+ CursorMan.showMouse(false);
+
+ _menu->drawMenuText(_menu->_menuBar._menuItems[_menu->_activeMenuItem._activeNum]._xpos, 1,
+ _menu->_menuBar._menuItems[_menu->_activeMenuItem._activeNum]._trigger,
+ _menu->_menuBar._menuItems[_menu->_activeMenuItem._activeNum]._title, true, false);
+
+ _activeNow = false;
+ _menu->_menuActive = false;
+ _firstlix = false;
+
+ CursorMan.showMouse(true);
+}
+
+void MenuItem::moveHighlight(int8 inc) {
+ if (inc != 0) {
+ int8 highlightNum = _highlightNum + inc;
+ if ((highlightNum < 0) || (highlightNum >= _optionNum))
+ return;
+ _highlightNum = highlightNum;
+ }
+ CursorMan.showMouse(false);
+ displayOption(_oldY, false);
+ displayOption(_highlightNum, true);
+ _oldY = _highlightNum;
+ CursorMan.showMouse(true);
+}
+
+/**
+ * This makes the menu highlight follow the mouse.
+ * @remarks Originally called 'lightup'
+ */
+void MenuItem::lightUp(Common::Point cursorPos) {
+ if ((cursorPos.x < _flx1 * 8) || (cursorPos.x > _flx2 * 8) || (cursorPos.y <= 25) || (cursorPos.y > ((_fly - 3) * 2 + 1)))
+ return;
+ _highlightNum = (cursorPos.y - 26) / 20;
+ if (_highlightNum == _oldY)
+ return;
+ moveHighlight(0);
+}
+
+void MenuItem::select(byte which) {
+ if (!_options[which]._valid)
+ return;
+
+ _choiceNum = which;
+ wipe();
+
+ if (_choiceNum == _optionNum)
+ _choiceNum--; // Off the bottom.
+ if (_choiceNum > _optionNum)
+ _choiceNum = 0; // Off the top, I suppose.
+
+ (_menu->*_menu->_menuBar._menuItems[_activeNum]._chooseFunc)();
+}
+
+void MenuItem::parseKey(char c) {
+ c = toupper(c);
+ bool found = false;
+ for (int i = 0; i < _optionNum; i++) {
+ if ((toupper(_options[i]._trigger) == c) && _options[i]._valid) {
+ select(i);
+ found = true;
+ }
+ }
+ if (!found)
+ _menu->_vm->_sound->blip();
+}
+
+MenuBar::MenuBar() {
+ _menuNum = 0;
+ _menu = nullptr;
+}
+
+void MenuBar::init(Menu *menu) {
+ _menu = menu;
+ _menuNum = 0;
+}
+
+void MenuBar::createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc) {
+ _menuItems[_menuNum].init(trig, altTrig, title, _menuNum, setupFunc, chooseFunc, _menu);
+ _menuNum++;
+}
+
+void MenuBar::draw() {
+ _menu->_vm->_graphics->drawMenuBar(kMenuBackgroundColor);
+
+ byte savecp = _menu->_vm->_cp;
+ _menu->_vm->_cp = 3;
+
+ for (int i = 0; i < _menuNum; i++)
+ _menuItems[i].draw();
+
+ _menu->_vm->_cp = savecp;
+}
+
+void MenuBar::parseAltTrigger(char c) {
+ byte i = 0;
+ while ((i < _menuNum) && (_menuItems[i].parseAltTrigger(c)))
+ i++;
+ if (i == _menuNum)
+ return;
+ setupMenuItem(i);
+}
+
+void MenuBar::setupMenuItem(byte which) {
+ if (_menu->_activeMenuItem._activeNow) {
+ _menu->_activeMenuItem.wipe(); // Get rid of menu.
+ if (_menu->_activeMenuItem._activeNum == _menuItems[which]._position)
+ return; // Clicked on own highlight.
+ }
+ _menuItems[which].highlight();
+ (_menu->*_menuItems[which]._setupFunc)();
+}
+
+void MenuBar::chooseMenuItem(int16 x) {
+ for (int i = 0; i < _menuNum; i++) {
+ if ((x > _menuItems[i]._xpos * 8) && (x < _menuItems[i]._xright * 8)) {
+ setupMenuItem(i);
+ break;
+ }
+ }
+}
+
+Menu::Menu(AvalancheEngine *vm) {
+ _vm = vm;
+ _activeMenuItem.init(this);
+ _menuBar.init(this);
+
+ _menuActive = false;
+ _lastPerson = kPeopleNone;
+}
+
+void Menu::findWhatYouCanDoWithIt() {
+ switch (_vm->_thinks) {
+ case kObjectWine:
+ case kObjectPotion:
+ case kObjectInk:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeDrink;
+ break;
+ case kObjectBell:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeRing;
+ break;
+ case kObjectChastity:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeWear;
+ break;
+ case kObjectLute:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodePlay;
+ break;
+ case kObjectMushroom:
+ case kObjectOnion:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeEat;
+ break;
+ case kObjectClothes:
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeWear;
+ break;
+ default:
+ _verbStr = kVerbCodeExam; // Anything else.
+ }
+}
+
+void Menu::drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted) {
+ Color fontColor;
+ Color backgroundColor;
+ if (highlighted) {
+ fontColor = kColorWhite;
+ backgroundColor = kColorBlack;
+ } else {
+ fontColor = kColorBlack;
+ backgroundColor = kColorLightgray;
+ }
+
+ byte ander;
+ if (valid)
+ ander = 255;
+ else
+ ander = 170;
+
+ FontType font;
+ for (uint i = 0; i < text.size(); i++) {
+ for (int j = 0; j < 8; j++) {
+ byte idx = text[i];
+ font[idx][j] = _vm->_font[idx][j] & ander; // Set the font.
+ // And set the background of the text to the desired color.
+ _vm->_graphics->wipeChar(x * 8 + i * 8, y + j, backgroundColor);
+ }
+ }
+
+ _vm->_graphics->drawNormalText(text, font, 8, x * 8, y, fontColor);
+
+ // Underline the selected character.
+ if ((trigger == 0) || !text.contains(trigger) )
+ return;
+ else {
+ byte i;
+ for (i = 0; text[i] != trigger; i++)
+ ; // Search for the character in the string.
+
+ _vm->_graphics->drawChar(ander, x * 8 + i * 8, y + 8, fontColor);
+ }
+
+ _vm->_graphics->refreshScreen();
+}
+
+void Menu::bleep() {
+ _vm->_sound->playNote(177, 7);
+}
+
+void Menu::parseKey(char r, char re) {
+#if 0
+ switch (r) {
+ case 0:
+ case 224: {
+ switch (re) {
+ case 'K':
+ if (_activeMenuItem._activeNum > 1) {
+ _activeMenuItem.wipe();
+ _menuBar.setupMenuItem(_activeMenuItem._activeNum - 1);
+ } else {
+ // Get menu on the left-hand side.
+ _activeMenuItem.wipe();
+ _menuBar.chooseMenuItem((_menuBar._menuNum - 1) * kSpacing + kIndent);
+ }
+ break;
+ case 'M':
+ if (_activeMenuItem._activeNum < _menuBar._menuNum) {
+ _activeMenuItem.wipe();
+ _menuBar.setupMenuItem(_activeMenuItem._activeNum + 1);
+ } else {
+ // Get menu on the far right-hand side.
+ _activeMenuItem.wipe();
+ _menuBar.chooseMenuItem(kIndent);
+ }
+ break;
+ case 'H':
+ _activeMenuItem.moveHighlight(-1);
+ break;
+ case 'P':
+ _activeMenuItem.moveHighlight(1);
+ break;
+ default:
+ _menuBar.parseAltTrigger(re);
+ }
+ }
+ break;
+ case 13:
+ _activeMenuItem.select(_activeMenuItem._highlightNum);
+ break;
+ default:
+ if (_activeMenuItem._activeNow)
+ _activeMenuItem.parseKey(r);
+ }
+#endif
+
+ warning("STUB: Dropdown::parseKey()"); // To be implemented properly later! Don't remove the comment above!
+}
+
+Common::String Menu::selectGender(byte x) {
+ if (x < 175)
+ return "im";
+ else
+ return "er";
+}
+
+void Menu::setupMenuGame() {
+ _activeMenuItem.reset();
+ _activeMenuItem.setupOption("Help...", 'H', "f1", true);
+ _activeMenuItem.setupOption("Boss Key", 'B', "alt-B", false);
+ _activeMenuItem.setupOption("Untrash screen", 'U', "ctrl-f7", true);
+ _activeMenuItem.setupOption("Score and rank", 'S', "f9", true);
+ _activeMenuItem.setupOption("About Avvy...", 'A', "shift-f10", true);
+ _activeMenuItem.display();
+}
+
+void Menu::setupMenuFile() {
+ _activeMenuItem.reset();
+ _activeMenuItem.setupOption("New game", 'N', "f4", true);
+ _activeMenuItem.setupOption("Load...", 'L', "^f3", true);
+ _activeMenuItem.setupOption("Save", 'S', "^f2", _vm->_alive);
+ _activeMenuItem.setupOption("Save As...", 'v', "", _vm->_alive);
+ _activeMenuItem.setupOption("DOS Shell", 'D', "alt-1", false);
+ _activeMenuItem.setupOption("Quit", 'Q', "alt-X", true);
+ _activeMenuItem.display();
+}
+
+void Menu::setupMenuAction() {
+ _activeMenuItem.reset();
+
+ Common::String f5Does = _vm->f5Does();
+ for (int i = 0; i < 2; i++)
+ if (!f5Does.empty())
+ f5Does.deleteChar(0);
+ if (f5Does.empty())
+ _activeMenuItem.setupOption("Do something", 'D', "f5", false);
+ else
+ _activeMenuItem.setupOption(f5Does, f5Does[0], "f5", true);
+ _activeMenuItem.setupOption("Pause game", 'P', "f6", true);
+ if (_vm->_room == kRoomMap)
+ _activeMenuItem.setupOption("Journey thither", 'J', "f7", _vm->_animation->nearDoor());
+ else
+ _activeMenuItem.setupOption("Open the door", 'O', "f7", _vm->_animation->nearDoor());
+ _activeMenuItem.setupOption("Look around", 'L', "f8", true);
+ _activeMenuItem.setupOption("Inventory", 'I', "Tab", true);
+ if (_vm->_animation->_sprites[0]->_speedX == kWalk)
+ _activeMenuItem.setupOption("Run fast", 'R', "^R", true);
+ else
+ _activeMenuItem.setupOption("Walk slowly", 'W', "^W", true);
+
+ _activeMenuItem.display();
+}
+
+void Menu::setupMenuPeople() {
+ if (!people.empty())
+ people.clear();
+
+ _activeMenuItem.reset();
+
+ for (int i = kPeopleAvalot; i <= kPeopleWisewoman; i++) {
+ if (_vm->getRoom((People)i) == _vm->_room) {
+ _activeMenuItem.setupOption(_vm->getName((People)i), getNameChar((People)i), "", true);
+ people += i;
+ }
+ }
+
+ _activeMenuItem.display();
+}
+
+void Menu::setupMenuObjects() {
+ _activeMenuItem.reset();
+ for (int i = 0; i < kObjectNum; i++) {
+ if (_vm->_objects[i])
+ _activeMenuItem.setupOption(getThing(i + 1), getThingChar(i + 1), "", true);
+ }
+ _activeMenuItem.display();
+}
+
+void Menu::setupMenuWith() {
+ _activeMenuItem.reset();
+
+ if (_vm->_thinkThing) {
+ findWhatYouCanDoWithIt();
+
+ for (uint i = 0; i < _verbStr.size(); i++) {
+ char vbchar;
+ Common::String verb;
+
+ _vm->_parser->verbOpt(_verbStr[i], verb, vbchar);
+ _activeMenuItem.setupOption(verb, vbchar, "", true);
+ }
+
+ // We disable the "give" option if: (a), you haven't selected anybody, (b), the _person you've selected isn't in the room,
+ // or (c), the _person you've selected is YOU!
+
+ if ((_lastPerson == kPeopleAvalot) || (_lastPerson == _vm->_parser->kNothing)
+ || (_vm->getRoom(_lastPerson) != _vm->_room))
+ _activeMenuItem.setupOption("Give to...", 'G', "", false); // Not here.
+ else {
+ _activeMenuItem.setupOption(Common::String("Give to ") + _vm->getName(_lastPerson), 'G', "", true);
+ _verbStr = _verbStr + kVerbCodeGive;
+ }
+ } else {
+ _activeMenuItem.setupOption("Examine", 'x', "", true);
+ _activeMenuItem.setupOption(Common::String("Talk to h") + selectGender(_vm->_thinks), 'T', "", true);
+ _verbStr = Common::String(kVerbCodeExam) + kVerbCodeTalk;
+ switch (_vm->_thinks) {
+ case kPeopleGeida:
+ case kPeopleArkata:
+ _activeMenuItem.setupOption("Kiss her", 'K', "", true);
+ _verbStr = _verbStr + kVerbCodeKiss;
+ break;
+ case kPeopleDogfood:
+ _activeMenuItem.setupOption("Play his game", 'P', "", !_vm->_wonNim); // True if you HAVEN'T won.
+ _verbStr = _verbStr + kVerbCodePlay;
+ break;
+ case kPeopleMalagauche: {
+ bool isSober = !_vm->_teetotal;
+ _activeMenuItem.setupOption("Buy some wine", 'w', "", !_vm->_objects[kObjectWine - 1]);
+ _activeMenuItem.setupOption("Buy some beer", 'b', "", isSober);
+ _activeMenuItem.setupOption("Buy some whisky", 'h', "", isSober);
+ _activeMenuItem.setupOption("Buy some cider", 'c', "", isSober);
+ _activeMenuItem.setupOption("Buy some mead", 'm', "", isSober);
+ _verbStr = _verbStr + 101 + 100 + 102 + 103 + 104;
+ }
+ break;
+ case kPeopleTrader:
+ _activeMenuItem.setupOption("Buy an onion", 'o', "", !_vm->_objects[kObjectOnion - 1]);
+ _verbStr = _verbStr + 105;
+ break;
+ }
+ }
+ _activeMenuItem.display();
+}
+
+void Menu::runMenuGame() {
+ // Help, boss, untrash screen.
+ switch (_activeMenuItem._choiceNum) {
+ case 0:
+ _vm->callVerb(kVerbCodeHelp);
+ break;
+ case 1:
+ _vm->callVerb(kVerbCodeBoss);
+ break;
+ case 2:
+ _vm->majorRedraw();
+ break;
+ case 3:
+ _vm->callVerb(kVerbCodeScore);
+ break;
+ case 4:
+ _vm->callVerb(kVerbCodeInfo);
+ break;
+ }
+}
+
+void Menu::runMenuFile() {
+ // New game, load, save, save as, DOS shell, about, quit.
+ switch (_activeMenuItem._choiceNum) {
+ case 0:
+ _vm->callVerb(kVerbCodeRestart);
+ break;
+ case 1:
+ if (!_vm->_parser->_realWords[1].empty())
+ _vm->_parser->_realWords[1].clear();
+ _vm->callVerb(kVerbCodeLoad);
+ break;
+ // Case 2 is 'Save', Case 3 is 'Save As'. Both triggers ScummVM save screen.
+ case 2:
+ case 3:
+ if (!_vm->_parser->_realWords[1].empty())
+ _vm->_parser->_realWords[1].clear();
+ _vm->callVerb(kVerbCodeSave);
+ break;
+ case 4:
+ // Command Prompt, disabled
+ break;
+ case 5:
+ _vm->callVerb(kVerbCodeQuit);
+ break;
+ }
+}
+
+void Menu::runMenuAction() {
+ // Get up, pause game, open door, look, inventory, walk/run.
+ switch (_activeMenuItem._choiceNum) {
+ case 0: {
+ _vm->_parser->_person = kPeoplePardon;
+ _vm->_parser->_thing = _vm->_parser->kPardon;
+ Common::String f5Does = _vm->f5Does();
+ VerbCode verb = (VerbCode)(byte)f5Does[0];
+ _vm->callVerb(verb);
+ }
+ break;
+ case 1:
+ _vm->_parser->_thing = _vm->_parser->kPardon;
+ _vm->callVerb(kVerbCodePause);
+ break;
+ case 2:
+ _vm->callVerb(kVerbCodeOpen);
+ break;
+ case 3:
+ _vm->_parser->_thing = _vm->_parser->kPardon;
+ _vm->callVerb(kVerbCodeLook);
+ break;
+ case 4:
+ _vm->callVerb(kVerbCodeInv);
+ break;
+ case 5: {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ if (avvy->_speedX == kWalk)
+ avvy->_speedX = kRun;
+ else
+ avvy->_speedX = kWalk;
+ _vm->_animation->updateSpeed();
+ }
+ break;
+ }
+}
+
+void Menu::runMenuObjects() {
+ _vm->thinkAbout(_vm->_objectList[_activeMenuItem._choiceNum], AvalancheEngine::kThing);
+}
+
+void Menu::runMenuPeople() {
+ _vm->thinkAbout(people[_activeMenuItem._choiceNum], AvalancheEngine::kPerson);
+ _lastPerson = (People)people[_activeMenuItem._choiceNum];
+}
+
+void Menu::runMenuWith() {
+ _vm->_parser->_thing = _vm->_thinks;
+
+ if (_vm->_thinkThing) {
+ _vm->_parser->_thing += 49;
+
+ if (_verbStr[_activeMenuItem._choiceNum] == kVerbCodeGive)
+ _vm->_parser->_person = _lastPerson;
+ else
+ _vm->_parser->_person = kPeoplePardon;
+ } else {
+ switch (_verbStr[_activeMenuItem._choiceNum]) {
+ case 100: // Beer
+ case 102: // Whisky
+ case 103: // Cider
+ _vm->_parser->_thing = _verbStr[_activeMenuItem._choiceNum];
+ _vm->callVerb(kVerbCodeBuy);
+ return;
+ case 101: // Wine
+ _vm->_parser->_thing = 50;
+ _vm->callVerb(kVerbCodeBuy);
+ return;
+ case 104: // Mead
+ _vm->_parser->_thing = 107;
+ _vm->callVerb(kVerbCodeBuy);
+ return;
+ case 105: // Onion (trader)
+ _vm->_parser->_thing = 67;
+ _vm->callVerb(kVerbCodeBuy);
+ return;
+ default:
+ _vm->_parser->_person = (People)_vm->_parser->_thing;
+ _vm->_parser->_thing = Parser::kPardon;
+ _vm->_subjectNum = 0;
+ }
+ }
+ _vm->callVerb((VerbCode)(byte)_verbStr[_activeMenuItem._choiceNum]);
+}
+
+void Menu::setup() {
+ _menuBar.init(this);
+ _activeMenuItem.init(this);
+
+ _menuBar.createMenuItem('F', "File", '!', &Avalanche::Menu::setupMenuFile, &Avalanche::Menu::runMenuFile);
+ _menuBar.createMenuItem('G', "Game", 34, &Avalanche::Menu::setupMenuGame, &Avalanche::Menu::runMenuGame);
+ _menuBar.createMenuItem('A', "Action", 30, &Avalanche::Menu::setupMenuAction, &Avalanche::Menu::runMenuAction);
+ _menuBar.createMenuItem('O', "Objects", 24, &Avalanche::Menu::setupMenuObjects, &Avalanche::Menu::runMenuObjects);
+ _menuBar.createMenuItem('P', "People", 25, &Avalanche::Menu::setupMenuPeople, &Avalanche::Menu::runMenuPeople);
+ _menuBar.createMenuItem('W', "With", 17, &Avalanche::Menu::setupMenuWith, &Avalanche::Menu::runMenuWith);
+
+ _menuBar.draw();
+}
+
+void Menu::update() { // TODO: Optimize it ASAP!!! It really needs it...
+ _vm->_graphics->saveScreen();
+
+ Common::Point cursorPos = _vm->getMousePos();
+ while (!_activeMenuItem._activeNow && (cursorPos.y <= 21) && _vm->_holdLeftMouse) {
+ _menuBar.chooseMenuItem(cursorPos.x);
+ do
+ _vm->updateEvents();
+ while (_vm->_holdLeftMouse && !_vm->shouldQuit());
+
+ while (!_vm->shouldQuit()) {
+ do {
+ _vm->updateEvents();
+
+ // We update the cursor's picture.
+ cursorPos = _vm->getMousePos();
+ // Change arrow...
+ if ((0 <= cursorPos.y) && (cursorPos.y <= 21))
+ _vm->_graphics->loadMouse(kCurUpArrow); // Up arrow
+ else if ((22 <= cursorPos.y) && (cursorPos.y <= 339)) {
+ if ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) && (cursorPos.y > 21) && (cursorPos.y <= _activeMenuItem._fly * 2 + 1))
+ _vm->_graphics->loadMouse(kCurRightArrow); // Right-arrow
+ else
+ _vm->_graphics->loadMouse(kCurFletch); // Fletch
+ } else if ((340 <= cursorPos.y) && (cursorPos.y <= 399))
+ _vm->_graphics->loadMouse(kCurScrewDriver); // Screwdriver
+
+ _activeMenuItem.lightUp(cursorPos);
+
+ _vm->_graphics->refreshScreen();
+ } while (!_vm->_holdLeftMouse && !_vm->shouldQuit());
+
+ if (_vm->_holdLeftMouse) {
+ if (cursorPos.y > 21) {
+ if (!((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8)
+ && (cursorPos.y >= 24) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1))))) {
+ // Clicked OUTSIDE the menu.
+ if (_activeMenuItem._activeNow) {
+ _activeMenuItem.wipe();
+ _vm->_holdLeftMouse = false;
+ _vm->_graphics->removeBackup();
+ return;
+ } // No "else"- clicking on menu has no effect (only releasing).
+ }
+ } else {
+ // Clicked on menu bar.
+ if (_activeMenuItem._activeNow) {
+ _activeMenuItem.wipe();
+ _vm->_graphics->restoreScreen();
+
+ if (((_activeMenuItem._left * 8) <= cursorPos.x) && (cursorPos.x <= (_activeMenuItem._left * 8 + 80))) { // 80: the width of one menu item on the bar in pixels.
+ // If we clicked on the same menu item (the one that is already active) on the bar...
+ _vm->_holdLeftMouse = false;
+ _vm->_graphics->removeBackup();
+ return;
+ } else {
+ _vm->_holdLeftMouse = true;
+ break;
+ }
+ }
+ }
+
+ // NOT clicked button...
+ if ((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8)
+ && (cursorPos.y >= 12) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1)))) {
+
+ // We act only if the button is released over a menu item.
+ while (!_vm->shouldQuit()) {
+ cursorPos = _vm->getMousePos();
+ _activeMenuItem.lightUp(cursorPos);
+ _vm->_graphics->refreshScreen();
+
+ _vm->updateEvents();
+ if (!_vm->_holdLeftMouse)
+ break;
+ }
+
+ uint16 which = (cursorPos.y - 26) / 20;
+ _activeMenuItem.select(which);
+ if (_activeMenuItem._options[which]._valid) { // If the menu item wasn't active, we do nothing.
+ _vm->_graphics->removeBackup();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ _vm->_graphics->removeBackup();
+}
+
+char Menu::getThingChar(byte which) {
+ static const char thingsChar[] = "WMBParCLguKeSnIohn"; // V=Vinegar
+
+ char result;
+ switch (which) {
+ case kObjectWine:
+ if (_vm->_wineState == 3)
+ result = 'V'; // Vinegar
+ else
+ result = thingsChar[which - 1];
+ break;
+ default:
+ result = thingsChar[which - 1];
+ }
+ return result;
+}
+
+byte Menu::getNameChar(People whose) {
+ static const char ladChar[] = "ASCDMTRwLfgeIyPu";
+ static const char lassChar[] = "kG\0xB1o";
+
+ if (whose <= kPeopleJacques)
+ return ladChar[whose - kPeopleAvalot];
+ else if ((whose >= kPeopleArkata) && (whose <= kPeopleWisewoman))
+ return lassChar[whose - kPeopleArkata];
+ else
+ error("getName() - Unexpected character id %d", (byte) whose);
+}
+
+Common::String Menu::getThing(byte which) {
+ static const char things[kObjectNum][20] = {
+ "Wine", "Money-bag", "Bodkin", "Potion", "Chastity belt",
+ "Crossbow bolt", "Crossbow", "Lute", "Pilgrim's badge", "Mushroom", "Key",
+ "Bell", "Scroll", "Pen", "Ink", "Clothes", "Habit", "Onion"
+ };
+
+ Common::String result;
+ switch (which) {
+ case kObjectWine:
+ switch (_vm->_wineState) {
+ case 1:
+ case 4:
+ result = Common::String(things[which - 1]);
+ break;
+ case 3:
+ result = "Vinegar";
+ break;
+ }
+ break;
+ case kObjectOnion:
+ if (_vm->_rottenOnion)
+ result = Common::String("rotten onion");
+ else
+ result = Common::String(things[which - 1]);
+ break;
+ default:
+ result = Common::String(things[which - 1]);
+ }
+ return result;
+}
+
+bool Menu::isActive() {
+ return _menuActive;
+}
+
+void Menu::init() {
+ _menuActive = false;
+}
+
+void Menu::resetVariables() {
+ _lastPerson = kPeoplePardon;
+}
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/menu.h b/engines/avalanche/menu.h
new file mode 100644
index 0000000000..b7674fbb9d
--- /dev/null
+++ b/engines/avalanche/menu.h
@@ -0,0 +1,182 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: DROPDOWN A customized version of Oopmenu (qv). */
+
+#ifndef AVALANCHE_MENU_H
+#define AVALANCHE_MENU_H
+
+#include "common/str.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Menu;
+
+typedef void (Menu::*MenuFunc)();
+static const Color kMenuBackgroundColor = kColorLightgray;
+static const Color kMenuBorderColor = kColorBlack;
+
+class HeadType {
+public:
+ Common::String _title;
+ char _trigger, _altTrigger;
+ byte _position;
+ int16 _xpos, _xright;
+ MenuFunc _setupFunc, _chooseFunc;
+
+ void init(char trig, char alTtrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, Menu *menu);
+ void draw();
+ void highlight();
+ bool parseAltTrigger(char key);
+
+private:
+ Menu *_menu;
+};
+
+struct OptionType {
+ Common::String _title;
+ byte _trigger;
+ Common::String _shortcut;
+ bool _valid;
+};
+
+class MenuItem {
+public:
+ OptionType _options[12];
+ uint16 _width, _left;
+ bool _firstlix;
+ int16 _flx1, _flx2, _fly;
+ bool _activeNow; // Is there an active option now?
+ byte _activeNum; // And if so, which is it?
+ byte _choiceNum; // Your choice?
+
+ void init(Menu *menu);
+ void reset();
+ void setupOption(Common::String title, char trigger, Common::String shortcut, bool valid);
+ void display();
+ void wipe();
+ void lightUp(Common::Point cursorPos);
+ void select(byte which);
+
+private:
+ byte _oldY; // used by lightUp
+ byte _optionNum;
+ byte _highlightNum;
+
+ Menu *_menu;
+
+ void displayOption(byte y, bool highlit);
+ void moveHighlight(int8 inc);
+
+ // CHECKME: Useless function?
+ void parseKey(char c);
+};
+
+class MenuBar {
+public:
+ HeadType _menuItems[8];
+ byte _menuNum;
+
+ MenuBar();
+ void init(Menu *menu);
+ void createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc);
+ void draw();
+ void chooseMenuItem(int16 x);
+
+private:
+ Menu *_menu;
+
+ void setupMenuItem(byte which);
+ // CHECKME: Useless function
+ void parseAltTrigger(char c);
+};
+
+class Menu {
+public:
+ friend class HeadType;
+ friend class MenuItem;
+ friend class MenuBar;
+
+ MenuItem _activeMenuItem;
+ MenuBar _menuBar;
+
+ Menu(AvalancheEngine *vm);
+
+ void update();
+ void setup(); // Standard menu bar.
+ bool isActive();
+ void init();
+ void resetVariables();
+
+private:
+ static const byte kIndent = 5;
+ static const byte kSpacing = 10;
+
+// Checkme: Useless constants?
+// static const Color kMenuFontColor = kColorBlack;
+// static const Color kHighlightBackgroundColor = kColorBlack;
+// static const Color kHighlightFontColor = kColorWhite;
+// static const Color kDisabledColor = kColorDarkgray;
+
+ Common::String people;
+ Common::String _verbStr; // what you can do with your object. :-)
+ bool _menuActive; // Kludge so we don't have to keep referring to the menu.
+ People _lastPerson; // Last person to have been selected using the People menu.
+
+ AvalancheEngine *_vm;
+
+ Common::String selectGender(byte x); // Returns "im" for boys, and "er" for girls.
+ void findWhatYouCanDoWithIt();
+ void drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted);
+ void bleep();
+
+ char getThingChar(byte which);
+ byte getNameChar(People whose);
+ Common::String getThing(byte which);
+
+ void setupMenuGame();
+ void setupMenuFile();
+ void setupMenuAction();
+ void setupMenuPeople();
+ void setupMenuObjects();
+ void setupMenuWith();
+
+ void runMenuGame();
+ void runMenuFile();
+ void runMenuAction();
+ void runMenuObjects();
+ void runMenuPeople();
+ void runMenuWith();
+
+ // CHECKME: Useless function?
+ void parseKey(char r, char re);
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_MENU_H
diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk
new file mode 100644
index 0000000000..0f66bb8213
--- /dev/null
+++ b/engines/avalanche/module.mk
@@ -0,0 +1,27 @@
+MODULE := engines/avalanche
+
+MODULE_OBJS = \
+ animation.o \
+ avalanche.o \
+ avalot.o \
+ background.o \
+ closing.o \
+ console.o \
+ detection.o \
+ graphics.o \
+ menu.o \
+ parser.o \
+ pingo.o \
+ dialogs.o \
+ sequence.o \
+ sound.o \
+ timer.o \
+ nim.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/avalanche/nim.cpp b/engines/avalanche/nim.cpp
new file mode 100644
index 0000000000..a2572f1fa5
--- /dev/null
+++ b/engines/avalanche/nim.cpp
@@ -0,0 +1,177 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/nim.h"
+
+namespace Avalanche {
+
+const char * const Nim::kNames[2] = {"Avalot", "Dogfood"};
+
+Nim::Nim(AvalancheEngine *vm) {
+ _vm = vm;
+
+ _playedNim = 0;
+}
+
+void Nim::resetVariables() {
+ _playedNim = 0;
+}
+
+void Nim::synchronize(Common::Serializer &sz) {
+ if (sz.isLoading() && sz.getVersion() < 2)
+ return;
+
+ sz.syncAsByte(_playedNim);
+}
+
+void Nim::playNim() {
+ if (_vm->_wonNim) { // Already won the game.
+ _vm->_dialogs->displayScrollChain('Q', 6);
+ return;
+ }
+
+ if (!_vm->_askedDogfoodAboutNim) {
+ _vm->_dialogs->displayScrollChain('Q', 84);
+ return;
+ }
+
+ _vm->_dialogs->displayScrollChain('Q', 3);
+ _playedNim++;
+ _vm->fadeOut();
+
+ _vm->_graphics->saveScreen();
+
+ CursorMan.showMouse(false);
+ setup();
+ board();
+ CursorMan.showMouse(true);
+
+ do {
+ startMove();
+ if (_dogfoodsTurn)
+ dogFood();
+ else
+ takeSome();
+ _stones[_row] -= _number;
+ showChanges();
+ } while (_stonesLeft != 0);
+
+ endOfGame(); // Winning sequence is A1, B3, B1, C1, C1, btw.
+
+ _vm->fadeOut();
+ CursorMan.showMouse(false);
+
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+
+ CursorMan.showMouse(true);
+ _vm->fadeIn();
+
+ if (_dogfoodsTurn) {
+ // Dogfood won - as usual.
+ if (_playedNim == 1) // Your first game.
+ _vm->_dialogs->displayScrollChain('Q', 4); // Goody! Play me again?
+ else
+ _vm->_dialogs->displayScrollChain('Q', 5); // Oh, look at that! I've won again!
+ _vm->decreaseMoney(4); // And you've just lost 4d!
+ } else {
+ // You won - strange!
+ _vm->_dialogs->displayScrollChain('Q', 7);
+ _vm->_objects[kObjectLute - 1] = true;
+ _vm->refreshObjectList();
+ _vm->_wonNim = true;
+ _vm->_background->draw(-1, -1, 0); // Show the settle with no lute on it.
+
+ // 7 points for winning!
+ _vm->incScore(7);
+ }
+
+ if (_playedNim == 1) {
+ // 3 points for playing your 1st game.
+ _vm->incScore(3);
+ }
+}
+
+void Nim::chalk(int x,int y, Common::String z) {
+ warning("STUB: Nim::chalk()");
+}
+
+void Nim::setup() {
+ warning("STUB: Nim::setup()");
+}
+
+void Nim::plotStone(byte x,byte y) {
+ warning("STUB: Nim::plotStone()");
+}
+
+void Nim::board() {
+ warning("STUB: Nim::board()");
+}
+
+void Nim::startMove() {
+ warning("STUB: Nim::startMove()");
+}
+
+void Nim::showChanges() {
+ warning("STUB: Nim::showChanges()");
+}
+
+void Nim::blip() {
+ warning("STUB: Nim::blip()");
+}
+
+void Nim::checkMouse() {
+ warning("STUB: Nim::checkMouse()");
+}
+
+void Nim::less() {
+ warning("STUB: Nim::less()");
+}
+
+void Nim::takeSome() {
+ warning("STUB: Nim::takeSome()");
+}
+
+void Nim::endOfGame() {
+ warning("STUB: Nim::endOfGame()");
+}
+
+void Nim::dogFood() {
+ warning("STUB: Nim::dogFood()");
+}
+
+bool Nim::find(byte x) {
+ warning("STUB: Nim::find()");
+ return true;
+}
+
+void Nim::findAp(byte start,byte stepsize) {
+ warning("STUB: Nim::findAp()");
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/nim.h b/engines/avalanche/nim.h
new file mode 100644
index 0000000000..a76afcfe22
--- /dev/null
+++ b/engines/avalanche/nim.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_NIM_H
+#define AVALANCHE_NIM_H
+
+namespace Avalanche {
+
+class Nim {
+public:
+ Nim(AvalancheEngine *vm);
+ void resetVariables();
+ void synchronize(Common::Serializer &sz);
+ void playNim();
+
+private:
+ AvalancheEngine *_vm;
+
+ static const char * const kNames[2];
+
+ byte _old[3];
+ byte _stones[3];
+ byte _stonePic[4][23][7]; // Picture of Nimstone.
+ byte _turns;
+ bool _dogfoodsTurn;
+ byte _stonesLeft;
+ bool _clicked;
+ byte _row;
+ byte _number;
+ bool _squeak;
+ int8 _mNum, _mRow;
+ byte _playedNim; // How many times you've played Nim.
+
+ void chalk(int x,int y, Common::String z);
+ void setup();
+ void plotStone(byte x,byte y);
+ void board();
+ void startMove();
+ void showChanges();
+ void blip();
+ void checkMouse();
+ void less();
+ void takeSome();
+ void endOfGame();
+ void dogFood();
+ bool find(byte x);
+ void findAp(byte start,byte stepsize);
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_NIM_H
diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp
new file mode 100644
index 0000000000..811e71ee1d
--- /dev/null
+++ b/engines/avalanche/parser.cpp
@@ -0,0 +1,2481 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/parser.h"
+#include "avalanche/nim.h"
+
+#include "gui/saveload.h"
+
+namespace Avalanche {
+
+const char *Parser::kCopyright = "1995";
+const char *Parser::kVersionNum = "1.30";
+
+Parser::Parser(AvalancheEngine *vm) {
+ _vm = vm;
+
+ _verb = kVerbCodePardon;
+ _thing = kPardon;
+ _person = kPeopleNone;
+ _polite = false;
+ _inputTextPos = 0;
+ _quote = false;
+ _cursorState = false;
+ _weirdWord = false;
+ _wearing = kNothing;
+ _thing2 = 0;
+ _sworeNum = 0;
+ _alcoholLevel = 0;
+
+ _boughtOnion = false;
+}
+
+void Parser::init() {
+ if (!_inputText.empty())
+ _inputText.clear();
+ _inputTextPos = 0;
+
+ _weirdWord = false;
+
+ // Initailaze the vocabulary.
+ // Verbs: 1-49
+ _vocabulary[0].init(1, "EXAMINE");
+ _vocabulary[1].init(1, "READ");
+ _vocabulary[2].init(1, "XAM");
+ _vocabulary[3].init(2, "OPEN");
+ _vocabulary[4].init(2, "LEAVE");
+ _vocabulary[5].init(2, "UNLOCK");
+ _vocabulary[6].init(3, "PAUSE");
+ _vocabulary[7].init(47, "TA"); // Early to avoid Take and Talk.
+ _vocabulary[8].init(4, "TAKE");
+ _vocabulary[9].init(4, "GET");
+ _vocabulary[10].init(4, "PICK");
+ _vocabulary[11].init(5, "DROP");
+ _vocabulary[12].init(6, "INVENTORY");
+ _vocabulary[13].init(7, "TALK");
+ _vocabulary[14].init(7, "SAY");
+ _vocabulary[15].init(7, "ASK");
+ _vocabulary[16].init(8, "GIVE");
+ _vocabulary[17].init(9, "DRINK");
+ _vocabulary[18].init(9, "IMBIBE");
+ _vocabulary[19].init(9, "DRAIN");
+ _vocabulary[20].init(10, "LOAD");
+ _vocabulary[21].init(10, "RESTORE");
+ _vocabulary[22].init(11, "SAVE");
+ _vocabulary[23].init(12, "BRIBE");
+ _vocabulary[24].init(12, "PAY");
+ _vocabulary[25].init(13, "LOOK");
+ _vocabulary[26].init(14, "BREAK");
+ _vocabulary[27].init(15, "QUIT");
+ _vocabulary[28].init(15, "EXIT");
+ _vocabulary[29].init(16, "SIT");
+ _vocabulary[30].init(16, "SLEEP");
+ _vocabulary[31].init(17, "STAND");
+
+ _vocabulary[32].init(18, "GO");
+ _vocabulary[33].init(19, "INFO");
+ _vocabulary[34].init(20, "UNDRESS");
+ _vocabulary[35].init(20, "DOFF");
+ _vocabulary[36].init(21, "DRESS");
+ _vocabulary[37].init(21, "WEAR");
+ _vocabulary[38].init(21, "DON");
+ _vocabulary[39].init(22, "PLAY");
+ _vocabulary[40].init(22, "STRUM");
+ _vocabulary[41].init(23, "RING");
+ _vocabulary[42].init(24, "HELP");
+ _vocabulary[43].init(25, "KENDAL");
+ _vocabulary[44].init(26, "CAPYBARA");
+ _vocabulary[45].init(27, "BOSS");
+ _vocabulary[46].init(255, "NINET"); // block for NINETY
+ _vocabulary[47].init(28, "URINATE");
+ _vocabulary[48].init(28, "MINGITE");
+ _vocabulary[49].init(29, "NINETY");
+ _vocabulary[50].init(30, "ABRACADABRA");
+ _vocabulary[51].init(30, "PLUGH");
+ _vocabulary[52].init(30, "XYZZY");
+ _vocabulary[53].init(30, "HOCUS");
+ _vocabulary[54].init(30, "POCUS");
+ _vocabulary[55].init(30, "IZZY");
+ _vocabulary[56].init(30, "WIZZY");
+ _vocabulary[57].init(30, "PLOVER");
+ _vocabulary[58].init(30, "MELENKURION");
+ _vocabulary[59].init(30, "ZORTON");
+ _vocabulary[60].init(30, "BLERBI");
+ _vocabulary[61].init(30, "THURB");
+ _vocabulary[62].init(30, "SNOEZE");
+ _vocabulary[63].init(30, "SAMOHT");
+ _vocabulary[64].init(30, "NOSIDE");
+ _vocabulary[65].init(30, "PHUGGG");
+ _vocabulary[66].init(30, "KNERL");
+ _vocabulary[67].init(30, "MAGIC");
+ _vocabulary[68].init(30, "KLAETU");
+ _vocabulary[69].init(30, "VODEL");
+ _vocabulary[70].init(30, "BONESCROLLS");
+ _vocabulary[71].init(30, "RADOF");
+
+ _vocabulary[72].init(31, "RESTART");
+ _vocabulary[73].init(32, "SWALLOW");
+ _vocabulary[74].init(32, "EAT");
+ _vocabulary[75].init(33, "LISTEN");
+ _vocabulary[76].init(33, "HEAR");
+ _vocabulary[77].init(34, "BUY");
+ _vocabulary[78].init(34, "PURCHASE");
+ _vocabulary[79].init(34, "ORDER");
+ _vocabulary[80].init(34, "DEMAND");
+ _vocabulary[81].init(35, "ATTACK");
+ _vocabulary[82].init(35, "HIT");
+ _vocabulary[83].init(35, "KILL");
+ _vocabulary[84].init(35, "PUNCH");
+ _vocabulary[85].init(35, "KICK");
+ _vocabulary[86].init(35, "SHOOT");
+ _vocabulary[87].init(35, "FIRE");
+
+ // Passwords: 36
+ _vocabulary[88].init(36, "TIROS");
+ _vocabulary[89].init(36, "WORDY");
+ _vocabulary[90].init(36, "STACK");
+ _vocabulary[91].init(36, "SHADOW");
+ _vocabulary[92].init(36, "OWL");
+ _vocabulary[93].init(36, "ACORN");
+ _vocabulary[94].init(36, "DOMESDAY");
+ _vocabulary[95].init(36, "FLOPPY");
+ _vocabulary[96].init(36, "DIODE");
+ _vocabulary[97].init(36, "FIELD");
+ _vocabulary[98].init(36, "COWSLIP");
+ _vocabulary[99].init(36, "OSBYTE");
+ _vocabulary[100].init(36, "OSCLI");
+ _vocabulary[101].init(36, "TIMBER");
+ _vocabulary[102].init(36, "ADVAL");
+ _vocabulary[103].init(36, "NEUTRON");
+ _vocabulary[104].init(36, "POSITRON");
+ _vocabulary[105].init(36, "ELECTRON");
+ _vocabulary[106].init(36, "CIRCUIT");
+ _vocabulary[107].init(36, "AURUM");
+ _vocabulary[108].init(36, "PETRIFY");
+ _vocabulary[109].init(36, "EBBY");
+ _vocabulary[110].init(36, "CATAPULT");
+ _vocabulary[111].init(36, "GAMERS");
+ _vocabulary[112].init(36, "FUDGE");
+ _vocabulary[113].init(36, "CANDLE");
+ _vocabulary[114].init(36, "BEEB");
+ _vocabulary[115].init(36, "MICRO");
+ _vocabulary[116].init(36, "SESAME");
+ _vocabulary[117].init(36, "LORDSHIP");
+
+ _vocabulary[118].init(37, "DIR");
+ _vocabulary[119].init(37, "LS");
+ _vocabulary[120].init(38, "DIE");
+ _vocabulary[121].init(39, "SCORE");
+ _vocabulary[122].init(40, "PUT");
+ _vocabulary[123].init(40, "INSERT");
+ _vocabulary[124].init(41, "KISS");
+ _vocabulary[125].init(41, "SNOG");
+ _vocabulary[126].init(41, "CUDDLE");
+ _vocabulary[127].init(42, "CLIMB");
+ _vocabulary[128].init(42, "CLAMBER");
+ _vocabulary[129].init(43, "JUMP");
+ _vocabulary[130].init(44, "HIGHSCORES");
+ _vocabulary[131].init(44, "HISCORES");
+ _vocabulary[132].init(45, "WAKEN");
+ _vocabulary[133].init(45, "AWAKEN");
+ _vocabulary[134].init(46, "HELLO");
+ _vocabulary[135].init(46, "HI");
+ _vocabulary[136].init(46, "YO");
+ _vocabulary[137].init(47, "THANKS"); // = 47, "ta", which was defined earlier.
+
+ // Nouns - Objects: 50-100
+ _vocabulary[138].init(50, "WINE");
+ _vocabulary[139].init(50, "BOOZE");
+ _vocabulary[140].init(50, "NASTY");
+ _vocabulary[141].init(50, "VINEGAR");
+ _vocabulary[142].init(51, "MONEYBAG");
+ _vocabulary[143].init(51, "BAG");
+ _vocabulary[144].init(51, "CASH");
+ _vocabulary[145].init(51, "DOSH");
+ _vocabulary[146].init(51, "WALLET");
+ _vocabulary[147].init(52, "BODKIN");
+ _vocabulary[148].init(52, "DAGGER");
+ _vocabulary[149].init(53, "POTION");
+ _vocabulary[150].init(54, "CHASTITY");
+ _vocabulary[151].init(54, "BELT");
+ _vocabulary[152].init(55, "BOLT");
+ _vocabulary[153].init(55, "ARROW");
+ _vocabulary[154].init(55, "DART");
+ _vocabulary[155].init(56, "CROSSBOW");
+ _vocabulary[156].init(56, "BOW");
+ _vocabulary[157].init(57, "LUTE");
+ _vocabulary[158].init(58, "PILGRIM");
+ _vocabulary[159].init(58, "BADGE");
+ _vocabulary[160].init(59, "MUSHROOMS");
+ _vocabulary[161].init(59, "TOADSTOOLS");
+ _vocabulary[162].init(60, "KEY");
+ _vocabulary[163].init(61, "BELL");
+ _vocabulary[164].init(62, "PRESCRIPT");
+ _vocabulary[165].init(62, "SCROLL");
+ _vocabulary[166].init(62, "MESSAGE");
+ _vocabulary[167].init(63, "PEN");
+ _vocabulary[168].init(63, "QUILL");
+ _vocabulary[169].init(64, "INK");
+ _vocabulary[170].init(64, "INKPOT");
+ _vocabulary[171].init(65, "CLOTHES");
+ _vocabulary[172].init(66, "HABIT");
+ _vocabulary[173].init(66, "DISGUISE");
+ _vocabulary[174].init(67, "ONION");
+
+ _vocabulary[175].init(99, "PASSWORD");
+
+ // Objects from Also are placed between 101 and 131.
+ // Nouns - People - Male: 150-174
+ _vocabulary[176].init(150, "AVVY");
+ _vocabulary[177].init(150, "AVALOT");
+ _vocabulary[178].init(150, "YOURSELF");
+ _vocabulary[179].init(150, "ME");
+ _vocabulary[180].init(150, "MYSELF");
+ _vocabulary[181].init(151, "SPLUDWICK");
+ _vocabulary[182].init(151, "THOMAS");
+ _vocabulary[183].init(151, "ALCHEMIST");
+ _vocabulary[184].init(151, "CHEMIST");
+ _vocabulary[185].init(152, "CRAPULUS");
+ _vocabulary[186].init(152, "SERF");
+ _vocabulary[187].init(152, "SLAVE");
+ _vocabulary[188].init(158, "DU"); // Put in early for Baron DU Lustie to save confusion with Duck & Duke.
+ _vocabulary[189].init(152, "CRAPPY");
+ _vocabulary[190].init(153, "DUCK");
+ _vocabulary[191].init(153, "DOCTOR");
+ _vocabulary[192].init(154, "MALAGAUCHE");
+ _vocabulary[193].init(155, "FRIAR");
+ _vocabulary[194].init(155, "TUCK");
+ _vocabulary[195].init(156, "ROBIN");
+ _vocabulary[196].init(156, "HOOD");
+ _vocabulary[197].init(157, "CWYTALOT");
+ _vocabulary[198].init(157, "GUARD");
+ _vocabulary[199].init(157, "BRIDGEKEEP");
+ _vocabulary[200].init(158, "BARON");
+ _vocabulary[201].init(158, "LUSTIE");
+ _vocabulary[202].init(159, "DUKE");
+ _vocabulary[203].init(159, "GRACE");
+ _vocabulary[204].init(160, "DOGFOOD");
+ _vocabulary[205].init(160, "MINSTREL");
+ _vocabulary[206].init(161, "TRADER");
+ _vocabulary[207].init(161, "SHOPKEEPER");
+ _vocabulary[208].init(161, "STALLHOLDER");
+ _vocabulary[209].init(162, "PILGRIM");
+ _vocabulary[210].init(162, "IBYTHNETH");
+ _vocabulary[211].init(163, "ABBOT");
+ _vocabulary[212].init(163, "AYLES");
+ _vocabulary[213].init(164, "PORT");
+ _vocabulary[214].init(165, "SPURGE");
+ _vocabulary[215].init(166, "JACQUES");
+ _vocabulary[216].init(166, "SLEEPER");
+ _vocabulary[217].init(166, "RINGER");
+
+ // Nouns - People - Female: 175-199
+ _vocabulary[218].init(175, "WIFE");
+ _vocabulary[219].init(175, "ARKATA");
+ _vocabulary[220].init(176, "GEDALODAVA");
+ _vocabulary[221].init(176, "GEIDA");
+ _vocabulary[222].init(176, "PRINCESS");
+ _vocabulary[223].init(178, "WISE");
+ _vocabulary[224].init(178, "WITCH");
+
+ // Pronouns: 200-224
+ _vocabulary[225].init(200, "HIM");
+ _vocabulary[226].init(200, "MAN");
+ _vocabulary[227].init(200, "GUY");
+ _vocabulary[228].init(200, "DUDE");
+ _vocabulary[229].init(200, "CHAP");
+ _vocabulary[230].init(200, "FELLOW");
+ _vocabulary[231].init(201, "HER");
+ _vocabulary[232].init(201, "GIRL");
+ _vocabulary[233].init(201, "WOMAN");
+ _vocabulary[234].init(202, "IT");
+ _vocabulary[235].init(202, "THING");
+ _vocabulary[236].init(203, "MONK");
+ _vocabulary[237].init(204, "BARMAN");
+ _vocabulary[238].init(204, "BARTENDER");
+
+ // Prepositions: 225-249
+ _vocabulary[239].init(225, "TO");
+ _vocabulary[240].init(226, "AT");
+ _vocabulary[241].init(227, "UP");
+ _vocabulary[242].init(228, "INTO");
+ _vocabulary[243].init(228, "INSIDE");
+ _vocabulary[244].init(229, "OFF");
+ _vocabulary[245].init(230, "UP");
+ _vocabulary[246].init(231, "DOWN");
+ _vocabulary[247].init(232, "ON");
+
+ // Please: 251
+ _vocabulary[248].init(251, "PLEASE");
+
+ // About: 252
+ _vocabulary[249].init(252, "ABOUT");
+ _vocabulary[250].init(252, "CONCERNING");
+
+ // Swear words: 253
+ /* I M P O R T A N T M E S S A G E
+
+ DO *NOT* READ THE LINES BELOW IF YOU ARE OF A SENSITIVE
+ DISPOSITION. THOMAS IS *NOT* RESPONSIBLE FOR THEM.
+ GOODNESS KNOWS WHO WROTE THEM.
+ READ THEM AT YOUR OWN RISK. BETTER STILL, DON'T READ THEM.
+ WHY ARE YOU SNOOPING AROUND IN MY PROGRAM, ANYWAY? */
+ _vocabulary[251].init(253, "SHIT");
+ _vocabulary[252].init(28 , "PISS");
+ _vocabulary[253].init(28 , "PEE");
+ _vocabulary[254].init(253, "FART");
+ _vocabulary[255].init(253, "FUCK");
+ _vocabulary[256].init(253, "BALLS");
+ _vocabulary[257].init(253, "BLAST");
+ _vocabulary[258].init(253, "BUGGER");
+ _vocabulary[259].init(253, "KNICKERS");
+ _vocabulary[260].init(253, "BLOODY");
+ _vocabulary[261].init(253, "HELL");
+ _vocabulary[262].init(253, "DAMN");
+ _vocabulary[263].init(253, "SMEG");
+ // ...and other even ruder words. You didn't read them, did you? Good.
+
+ // Answer-back smart-alec words: 249
+ _vocabulary[264].init(249, "YES");
+ _vocabulary[265].init(249, "NO");
+ _vocabulary[266].init(249, "BECAUSE");
+
+ // Noise words: 255
+ _vocabulary[267].init(255, "THE");
+ _vocabulary[268].init(255, "A");
+ _vocabulary[269].init(255, "NOW");
+ _vocabulary[270].init(255, "SOME");
+ _vocabulary[271].init(255, "AND");
+ _vocabulary[272].init(255, "THAT");
+ _vocabulary[273].init(255, "POCUS");
+ _vocabulary[274].init(255, "HIS");
+ _vocabulary[275].init(255, "THIS");
+ _vocabulary[276].init(255, "SENTINEL"); // for "Ken SENT Me"
+}
+
+void Parser::handleInputText(const Common::Event &event) {
+ byte inChar = event.kbd.ascii;
+ warning("STUB: Parser::handleInputText()");
+// if (_vm->_menu->_activeMenuItem._activeNow) {
+// _vm->_menu->parseKey(inChar, _vm->_enhanced->extd);
+// } else {
+ if (_inputText.size() < 76) {
+ if ((inChar == '"') || (inChar == '`')) {
+ if (_quote)
+ inChar = '`';
+ else
+ inChar = '"';
+ _quote = !_quote; // quote - unquote
+ }
+
+ _inputText.insertChar(inChar, _inputTextPos);
+ _inputTextPos++;
+ plotText();
+ } else
+ _vm->_sound->blip();
+// }
+}
+
+void Parser::handleBackspace() {
+ if (_vm->_menu->_activeMenuItem._activeNow)
+ return;
+
+ if (_inputTextPos > 0) {
+ _inputTextPos--;
+ if ((_inputText[_inputTextPos] == '"') || (_inputText[_inputTextPos] == '`'))
+ _quote = !_quote;
+ _inputText.deleteChar(_inputTextPos);
+ plotText();
+ } else
+ _vm->_sound->blip();
+}
+
+void Parser::handleReturn() {
+ if (_vm->_menu->_activeMenuItem._activeNow)
+ tryDropdown();
+ else if (!_inputText.empty()) {
+ _inputTextBackup = _inputText;
+ parse();
+ doThat();
+ _inputText.clear();
+ wipeText();
+ }
+}
+
+void Parser::handleFunctionKey(const Common::Event &event) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F1:
+ _vm->callVerb(kVerbCodeHelp);
+ break;
+ case Common::KEYCODE_F2:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ clearWords();
+ _vm->callVerb(kVerbCodeSave);
+ } else
+ _vm->_sound->toggleSound();
+ break;
+ case Common::KEYCODE_F3:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ clearWords();
+ _vm->callVerb(kVerbCodeLoad);
+ } else if (_inputText.size() < _inputTextBackup.size()) {
+ _inputText = _inputText + &(_inputTextBackup.c_str()[_inputText.size()]);
+ _inputTextPos = _inputText.size();
+ plotText();
+ }
+ break;
+ case Common::KEYCODE_F4:
+ if (event.kbd.flags & Common::KBD_ALT)
+ _vm->callVerb(kVerbCodeQuit);
+ else
+ _vm->callVerb(kVerbCodeRestart);
+ break;
+ case Common::KEYCODE_F5: {
+ _person = kPeoplePardon;
+ _thing = kPardon;
+ Common::String f5does = _vm->f5Does();
+ VerbCode verb = (VerbCode)(byte)f5does[0];
+ _vm->callVerb(verb);
+ }
+ break;
+ case Common::KEYCODE_F6:
+ _vm->callVerb(kVerbCodePause);
+ break;
+ case Common::KEYCODE_F7:
+ if (event.kbd.flags & Common::KBD_CTRL)
+ _vm->majorRedraw();
+ else
+ _vm->callVerb(kVerbCodeOpen);
+ break;
+ case Common::KEYCODE_F8:
+ _vm->callVerb(kVerbCodeLook);
+ break;
+ case Common::KEYCODE_F9:
+ _vm->callVerb(kVerbCodeScore);
+ break;
+ case Common::KEYCODE_F10:
+ if (event.kbd.flags & Common::KBD_SHIFT)
+ _vm->callVerb(kVerbCodeInfo);
+ else
+ _vm->callVerb(kVerbCodeQuit);
+ break;
+ case Common::KEYCODE_F11:
+ clearWords();
+ _vm->callVerb(kVerbCodeSave);
+ break;
+ case Common::KEYCODE_F12:
+ clearWords();
+ _vm->callVerb(kVerbCodeLoad);
+ break;
+ default:
+ break;
+ }
+}
+
+void Parser::plotText() {
+ CursorMan.showMouse(false);
+ cursorOff();
+
+ _vm->_graphics->clearTextBar();
+ _vm->_graphics->drawNormalText(_inputText, _vm->_font, 8, 24, 161, kColorWhite);
+
+ cursorOn();
+ CursorMan.showMouse(true);
+}
+
+void Parser::cursorOn() {
+ if (_cursorState == true)
+ return;
+ _vm->_graphics->drawCursor(_inputTextPos);
+ _cursorState = true;
+}
+
+void Parser::cursorOff() {
+ if (_cursorState == false)
+ return;
+ _vm->_graphics->drawCursor(_inputTextPos);
+ _cursorState = false;
+}
+
+/**
+ * Asks the parsekey proc in Dropdown if it knows it.
+ */
+void Parser::tryDropdown() {
+ // TODO: Implement at the same time with Dropdown's keyboard handling.
+ warning("STUB: Parser::tryDropdown()");
+}
+
+/**
+ * Returns the index of the first appearance of crit in src.
+ */
+int16 Parser::getPos(const Common::String &crit, const Common::String &src) {
+ if (src.contains(crit))
+ return strstr(src.c_str(),crit.c_str()) - src.c_str();
+ else
+ return -1;
+}
+
+void Parser::wipeText() {
+ CursorMan.showMouse(false);
+ cursorOff();
+
+ _vm->_graphics->clearTextBar();
+
+ _quote = true;
+ _inputTextPos = 0;
+
+ cursorOn();
+ CursorMan.showMouse(true);
+}
+
+void Parser::clearWords() {
+ for (int i = 0; i < 11; i++) {
+ if (!_realWords[i].empty())
+ _realWords[i].clear();
+ }
+}
+
+byte Parser::wordNum(Common::String word) {
+ if (word.empty())
+ return 0;
+
+ for (int32 i = kParserWordsNum - 1; i >= 0; i--) {
+ if (_vocabulary[i]._word == word)
+ return _vocabulary[i]._number;
+ }
+
+ // If not found as a whole, we look for it as a substring.
+ for (int32 i = kParserWordsNum - 1; i >= 0; i--) {
+ if (Common::String(_vocabulary[i]._word.c_str(), word.size()) == word)
+ return _vocabulary[i]._number;
+ }
+
+ return kPardon;
+}
+
+void Parser::replace(Common::String oldChars, byte newChar) {
+ int16 pos = getPos(oldChars, _thats);
+ while (pos != -1) {
+ if (newChar == 0)
+ _thats.deleteChar(pos);
+ else {
+ for (uint i = pos; i < pos + oldChars.size(); i++)
+ _thats.deleteChar(pos);
+ _thats.insertChar(newChar, pos);
+ }
+ pos = getPos(oldChars, _thats);
+ }
+}
+
+Common::String Parser::rank() {
+ static const RankType ranks[9] = {
+ {0, "Beginner"}, {10, "Novice"},
+ {20, "Improving"}, {35, "Not bad"},
+ {50, "Passable"}, {65, "Good"},
+ {80, "Experienced"}, {108, "The BEST!"},
+ {32767, "copyright'93"}
+ };
+
+ for (int i = 0; i < 8; i++) {
+ if ((_vm->_dnascore >= ranks[i]._score) && (_vm->_dnascore < ranks[i + 1]._score))
+ return Common::String(ranks[i]._title);
+ }
+ return "";
+}
+
+Common::String Parser::totalTime() {
+ uint16 h, m, s;
+
+ uint32 curTime = _vm->getTimeInSeconds() - _vm->_startTime;
+ if (_vm->_isLoaded)
+ curTime += _vm->_totalTime;
+
+ h = (uint16)(curTime / 3600);
+ s = (uint16)(curTime % 3600);
+ m = s / 60;
+ s = s % 60;
+
+ Common::String result = "You've been playing for ";
+ if (h > 0)
+ result += Common::String::format("%d hours, ", h);
+ if ((m > 0) || (h != 0))
+ result += Common::String::format("%d minutes and ", m);
+ return result + Common::String::format("%d seconds", s);
+}
+
+void Parser::cheatParse(Common::String codes) {
+ warning("STUB: Parser::cheatParse()");
+}
+
+/**
+ * Strips punctuation from word.
+ */
+void Parser::stripPunctuation(Common::String &word) {
+ const char punct[] = "~`!@#$%^&*()_+-={}[]:\"|;'\\,./<>?";
+
+ for (int i = 0; i < 32; i++) {
+ for (;;) {
+ int16 pos = getPos(Common::String(punct[i]), word);
+ if (pos == -1)
+ break;
+ word.deleteChar(pos);
+ }
+ }
+}
+
+void Parser::displayWhat(byte target, bool animate, bool &ambiguous) {
+ if (target == kPardon) {
+ ambiguous = true;
+ if (animate)
+ _vm->_dialogs->displayText("Whom?");
+ else
+ _vm->_dialogs->displayText("What?");
+ } else {
+ if (animate) {
+ Common::String tmpStr = Common::String::format("{ %s }", _vm->getName((People)target).c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ } else {
+ Common::String z = _vm->getItem(target);
+ if (z != "") {
+ Common::String tmpStr = Common::String::format("{ %s }", z.c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ }
+ }
+}
+
+bool Parser::doPronouns() {
+ bool ambiguous = false;
+
+ for (uint i = 0; i < _thats.size(); i++) {
+ byte wordCode = _thats[i];
+ switch (wordCode) {
+ case 200:
+ displayWhat(_vm->_him, true, ambiguous);
+ _thats.setChar(_vm->_him, i);
+ break;
+ case 201:
+ displayWhat(_vm->_her, true, ambiguous);
+ _thats.setChar(_vm->_her, i);
+ break;
+ case 202:
+ displayWhat(_vm->_it, false, ambiguous);
+ _thats.setChar(_vm->_it, i);
+ break;
+ }
+ }
+
+ return ambiguous;
+}
+
+void Parser::properNouns() {
+ _inputText.toLowercase();
+
+ // We set every word's first character to uppercase.
+ for (uint i = 1; i < (_inputText.size() - 1); i++) {
+ if (_inputText[i] == ' ')
+ _inputText.setChar(toupper(_inputText[i + 1]), i + 1);
+ }
+
+ // And the first character as well.
+ _inputText.setChar(toupper(_inputText[0]), 0);
+}
+
+void Parser::storeInterrogation(byte interrogation) {
+ if (_inputText.empty())
+ return;
+
+ // Strip _inputText:
+ while ((_inputText[0] == ' ') && (!_inputText.empty()))
+ _inputText.deleteChar(0);
+ while ((_inputText.lastChar() == ' ') && (!_inputText.empty()))
+ _inputText.deleteLastChar();
+
+ _vm->_timer->loseTimer(Timer::kReasonCardiffsurvey); // If you want to use any other timer, put this into the case statement.
+
+ switch (interrogation) {
+ case 1:
+ _inputText.toLowercase();
+ _vm->_dialogs->sayIt(_inputText);
+ _vm->_favoriteDrink = _inputText;
+ _vm->_cardiffQuestionNum = 2;
+ break;
+ case 2:
+ properNouns();
+ _vm->_dialogs->sayIt(_inputText);
+ _vm->_favoriteSong = _inputText;
+ _vm->_cardiffQuestionNum = 3;
+ break;
+ case 3:
+ properNouns();
+ _vm->_dialogs->sayIt(_inputText);
+ _vm->_worstPlaceOnEarth = _inputText;
+ _vm->_cardiffQuestionNum = 4;
+ break;
+ case 4:
+ _inputText.toLowercase();
+ _vm->_dialogs->sayIt(_inputText);
+ if (!_vm->_spareEvening.empty())
+ _vm->_spareEvening.clear();
+ _vm->_spareEvening = _inputText;
+ _vm->_dialogs->displayScrollChain('Z', 5); // His closing statement...
+ _vm->_animation->_sprites[1]->walkTo(3); // The end of the drawbridge
+ _vm->_animation->_sprites[1]->_vanishIfStill = true; // Then go away!
+ _vm->_magics[1]._operation = kMagicNothing;
+ _vm->_cardiffQuestionNum = 5;
+ break;
+ case 99:
+ //store_high(_inputText);
+ warning("STUB: Parser::store_interrogation()");
+ break;
+ }
+
+ if (interrogation < 4)
+ _vm->_timer->cardiffSurvey();
+}
+
+void Parser::parse() {
+ // First parsing - word identification
+ if (!_thats.empty())
+ _thats.clear();
+
+ _polite = false;
+ _verb = kVerbCodePardon;
+ _thing = kPardon;
+ _thing2 = kPardon;
+ _person = kPeoplePardon;
+ clearWords();
+
+ // A cheat mode attempt.
+ if (_inputText[0] == '.') {
+ cheatParse(_inputText);
+ _thats = kNothing;
+ return;
+ }
+
+ // Are we being interrogated right now?
+ if (_vm->_interrogation > 0) {
+ storeInterrogation(_vm->_interrogation);
+ _weirdWord = true;
+ return;
+ }
+
+ // Actually process the command.
+ Common::String inputText = _inputText + ' ';
+ Common::String inputTextUpper = inputText;
+ byte n = 0;
+ inputTextUpper.toUppercase();
+ while (!inputTextUpper.empty()) {
+ while ((!inputTextUpper.empty()) && (inputTextUpper[0] == ' ')) {
+ inputTextUpper.deleteChar(0);
+ inputText.deleteChar(0);
+ }
+ if (inputTextUpper.empty())
+ break;
+
+ // Get the following word of the strings.
+ byte size = getPos(Common::String(' '), inputTextUpper) + 1;
+ char *subStr = new char[size];
+ Common::strlcpy(subStr, inputTextUpper.c_str(), size);
+ Common::String thisword = subStr;
+ Common::strlcpy(subStr, inputText.c_str(), size);
+ _realWords[n] = subStr;
+ delete[] subStr;
+
+ stripPunctuation(inputTextUpper);
+
+ bool notfound = true;
+
+ // Check also[] first, which contains words about the actual room.
+ if (!thisword.empty()) {
+ for (int i = 0; i < 31; i++) {
+ if ((_vm->_also[i][0]) && (getPos(',' + thisword, *_vm->_also[i][0]) > -1)) {
+ _thats += Common::String(99 + i);
+ notfound = false;
+ }
+ }
+ }
+
+ // Check Accis's own table (words[]) for "global" commands.
+ if (notfound) {
+ byte answer = wordNum(thisword);
+ if (answer == kPardon) {
+ notfound = true;
+ _thats = _thats + kPardon;
+ } else
+ _thats = _thats + answer;
+ n++;
+ }
+
+ // Delete words we already processed.
+ int16 spacePos = getPos(Common::String(' '), inputTextUpper);
+ if (spacePos > -1) {
+ for (int i = 0; i <= spacePos; i++)
+ inputTextUpper.deleteChar(0);
+ }
+
+ spacePos = getPos(Common::String(' '), inputText);
+ if (spacePos > -1) {
+ for (int i = 0; i <= spacePos; i++)
+ inputText.deleteChar(0);
+ }
+ }
+
+ Common::String unkString;
+ int16 pos = getPos(Common::String('\xFE'), _thats);
+ if (pos > -1)
+ unkString = _realWords[pos];
+ else
+ unkString.clear();
+
+ // Replace words' codes that mean the same.
+ replace(Common::String("\xFF"), 0); // zap noise words
+ replace(Common::String("\xD\xE2"), 1); // "look at" = "examine"
+ replace(Common::String("\xD\xE4"), 1); // "look in" = "examine"
+ replace(Common::String("\x4\xE6"), 17); // "get up" = "stand"
+ replace(Common::String("\x4\xE7"), 17); // "get down" = "stand"... well, why not?
+ replace(Common::String("\x12\xE4"), 2); // "go in" = "open [door]"
+ replace(Common::String("\x1C\xE5"), 253); // "P' off" is a swear word
+ replace(Common::String("\x4\x6"), 6); // "Take inventory" (remember Colossal Adventure?)
+ replace(Common::String("\x28\xE8"), 21); // "put on" = "don"
+ replace(Common::String("\x4\xE5"), 20); // "take off" = "doff"
+
+ // Words that could mean more than one _person
+ if (_vm->_room == kRoomNottsPub)
+ replace(Common::String('\xCC'), 164); // Barman = Port
+ else
+ replace(Common::String('\xCC'), 154); // Barman = Malagauche
+
+ switch (_vm->_room) {
+ case kRoomAylesOffice:
+ replace(Common::String('\xCB'), 163); // Monk = Ayles
+ break;
+ case kRoomMusicRoom:
+ replace(Common::String('\xCB'), 166); // Monk = Jacques
+ break;
+ default:
+ replace(Common::String('\xCB'), 162); // Monk = Ibythneth
+ }
+
+ if (doPronouns()) {
+ _weirdWord = true;
+ _thats = kNothing;
+ return;
+ }
+
+ // Second parsing.
+ _vm->_subjectNum = 0; // Find subject of conversation.
+
+ for (int i = 0; (i < 11) && !_realWords[i].empty(); i++) {
+ if ((_realWords[i][0] == '\'') || (_realWords[i][0] == '\"')) {
+ _vm->_subjectNum = (byte)_thats[i];
+ _thats.setChar(kMoved, i);
+ break;
+ }
+ }
+
+ if ((_vm->_subjectNum == 0) && !_thats.empty()) { // Still not found.
+ for (uint16 i = 0; i < _thats.size() - 1; i++) {
+ if ((byte)_thats[i] == 252) { // The word is "about", or something similar.
+ _vm->_subjectNum = (byte)_thats[i + 1];
+ _thats.setChar(0, i + 1);
+ break;
+ }
+ }
+ }
+
+ if ((_vm->_subjectNum == 0) && !_thats.empty()) { // STILL not found! Must be the word after "say".
+ for (uint16 i = 0; i < _thats.size() - 1; i++) {
+ if (((byte)_thats[i] == 7) && ((byte)_thats[i + 1] != 0) && !((225 <= (byte)_thats[i + 1]) && ((byte)_thats[i + 1] <= 229))) {
+ // SAY not followed by a preposition
+ _vm->_subjectNum = (byte)_thats[i + 1];
+ _thats.setChar(0, i + 1);
+ break;
+ }
+ }
+ }
+
+ for (int16 i = _thats.size() - 1; i >= 0; i--) { // Reverse order, so first will be used.
+ byte curChar = (byte)_thats[i];
+ if ((curChar == 253) || (curChar == 249) || ((1 <= curChar) && (curChar <= 49)))
+ _verb = (VerbCode)curChar;
+ else if ((50 <= curChar) && (curChar <= 149)) {
+ _thing2 = _thing;
+ _thing = curChar;
+ } else if ((150 <= curChar) && (curChar <= 199))
+ _person = (People)curChar;
+ else if (curChar == 251)
+ _polite = true;
+ }
+
+ if ((!unkString.empty()) && (_verb != kVerbCodeExam) && (_verb != kVerbCodeTalk) &&
+ (_verb != kVerbCodeSave) && (_verb != kVerbCodeLoad) && (_verb != kVerbCodeDir)) {
+ Common::String tmpStr = Common::String::format("Sorry, but I have no idea what \"%s\" means. Can you rephrase it?", unkString.c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ _weirdWord = true;
+ } else
+ _weirdWord = false;
+
+ if (_thats.empty())
+ _thats = kNothing;
+
+ if (_thing != kPardon)
+ _vm->_it = _thing;
+
+ if (_person != kPardon) {
+ if (_person < kPeopleArkata)
+ _vm->_him = _person;
+ else
+ _vm->_her = _person;
+ }
+}
+
+/**
+ * Examine a standard object-thing
+ */
+void Parser::examineObject() {
+ if (_thing != _vm->_thinks)
+ _vm->thinkAbout(_thing, AvalancheEngine::kThing);
+ switch (_thing) {
+ case kObjectWine :
+ // 4 is perfect wine. 0 is not holding the wine.
+ switch (_vm->_wineState) {
+ case 1:
+ // Normal examine wine scroll
+ _vm->_dialogs->displayScrollChain('T', 1);
+ break;
+ case 2:
+ // Bad wine
+ _vm->_dialogs->displayScrollChain('D', 6);
+ break;
+ case 3:
+ // Vinegar
+ _vm->_dialogs->displayScrollChain('D', 7);
+ break;
+ }
+ break;
+ case kObjectOnion:
+ if (_vm->_rottenOnion)
+ // Yucky onion
+ _vm->_dialogs->displayScrollChain('Q', 21);
+ else
+ // Normal onion
+ _vm->_dialogs->displayScrollChain('T', 18);
+ break;
+ default:
+ // Ordinarily
+ _vm->_dialogs->displayScrollChain('T', _thing);
+ }
+}
+
+bool Parser::isPersonHere() {
+ // Person equivalent of "isHolding".
+ if ((_person == kPeoplePardon) || (_person == kPeopleNone) || (_vm->getRoom(_person) == _vm->_room))
+ return true;
+ else {
+ Common::String tmpStr;
+ if (_person < kPeopleArkata)
+ tmpStr = "He isn't around at the moment.";
+ else
+ tmpStr = "She isn't around at the moment.";
+ _vm->_dialogs->displayText(tmpStr);
+ return false;
+ }
+}
+
+void Parser::exampers() {
+ if (isPersonHere()) {
+ if (_thing != _vm->_thinks)
+ _vm->thinkAbout(_person, AvalancheEngine::kPerson);
+
+ byte newPerson = _person - 149;
+
+ if ((_person == kPeopleDogfood) && _vm->_wonNim)
+ // "I'm Not Playing!"
+ _vm->_dialogs->displayScrollChain('Q', 8);
+ else if ((_person == kPeopleDuLustie) && _vm->_lustieIsAsleep)
+ // He's asleep.
+ _vm->_dialogs->displayScrollChain('Q', 65);
+ else
+ _vm->_dialogs->displayScrollChain('P', newPerson);
+
+ if ((_person == kPeopleAyles) && !_vm->_aylesIsAwake)
+ _vm->_dialogs->displayScrollChain('Q', 13);
+
+ // CHECKME: Present in the original, but it doesn't make sense.
+ // _person = newPerson;
+ }
+}
+
+/**
+ * Return whether Avvy is holding an object or not
+ * @remarks Originally called 'holding'
+ */
+bool Parser::isHolding() {
+ // Also object
+ if ((51 <= _thing) && (_thing <= 99))
+ return true;
+
+ bool holdingResult = false;
+
+ if (_thing >= 100)
+ _vm->_dialogs->displayText("Be reasonable!");
+ else if (_thing <= kObjectNum) {
+ if (!_vm->_objects[_thing - 1])
+ // Verbs that need "_thing" to be in the inventory.
+ _vm->_dialogs->displayText("You're not holding it, Avvy.");
+ else
+ holdingResult = true;
+ } else
+ holdingResult = true;
+
+ return holdingResult;
+}
+
+void Parser::openBox(bool isOpening) {
+ if ((_vm->_room == kRoomYours) && (_thing == 54)) {
+ _vm->_background->draw(-1, -1, 4);
+
+ _vm->_background->update();
+ _vm->_animation->animLink();
+ _vm->_graphics->refreshScreen();
+
+ _vm->_system->delayMillis(55);
+
+ if (!isOpening) {
+ _vm->_background->draw(-1, -1, 5);
+ _vm->_background->update();
+ _vm->_animation->animLink();
+ _vm->_graphics->refreshScreen();
+ }
+ }
+}
+
+void Parser::examine() {
+ // EITHER it's an object OR it's an Also OR it's a _person OR it's something else.
+ if ((_person == kPeoplePardon) && (_thing != kPardon)) {
+ if (isHolding()) {
+ // Remember: it's been slipped! Ie subtract 49.
+ if ((1 <= _thing) && (_thing <= 49))
+ // Standard object
+ examineObject();
+ else if ((50 <= _thing) && (_thing <= 100)) {
+ // Also _thing
+ int id = _thing - 50;
+ assert(id < 31);
+ openBox(true);
+ _vm->_dialogs->displayText(*_vm->_also[id][1]);
+ openBox(false);
+ }
+ }
+ } else if (_person != kPardon)
+ exampers();
+ else
+ // Don't know: guess.
+ _vm->_dialogs->displayText("It's just as it looks on the picture.");
+}
+
+void Parser::inventory() {
+ byte itemNum = 0;
+ Common::String tmpStr = Common::String("You're carrying ");
+
+ for (int i = 0; i < kObjectNum; i++) {
+ if (_vm->_objects[i]) {
+ itemNum++;
+ if (itemNum == _vm->_carryNum)
+ tmpStr += "and ";
+
+ tmpStr += _vm->getItem(i + 1);
+
+ if ((i + 1) == _wearing)
+ tmpStr += ", which you're wearing";
+
+ if (itemNum < _vm->_carryNum)
+ tmpStr += ", ";
+ }
+ }
+
+ if (_wearing == kNothing)
+ tmpStr += Common::String::format("...%c%c...and you're stark naked!", kControlNewLine, kControlNewLine);
+ else
+ tmpStr += '.';
+
+ _vm->_dialogs->displayText(tmpStr);
+}
+
+/**
+ * Eat something.
+ */
+void Parser::swallow() {
+ switch (_thing) {
+ case kObjectWine:
+ // _wineState == 4 for perfect wine
+ switch (_vm->_wineState) {
+ case 1:
+ if (_vm->_teetotal) {
+ _vm->_dialogs->displayScrollChain('D', 6);
+ return;
+ }
+ _vm->_dialogs->displayScrollChain('U', 1);
+ _vm->_pingo->wobble();
+ _vm->_dialogs->displayScrollChain('U', 2);
+ _vm->_objects[kObjectWine - 1] = false;
+ _vm->refreshObjectList();
+ drink();
+ break;
+ case 2:
+ case 3:
+ // You can't drink it!
+ _vm->_dialogs->displayScrollChain('D', 8);
+ break;
+ }
+ break;
+ case kObjectPotion:
+ _vm->_graphics->setBackgroundColor(kColorRed);
+ _vm->_dialogs->displayScrollChain('U', 3);
+ _vm->gameOver();
+ _vm->_graphics->setBackgroundColor(kColorBlack);
+ break;
+ case kObjectInk:
+ _vm->_dialogs->displayScrollChain('U', 4);
+ break;
+ case kObjectChastity:
+ _vm->_dialogs->displayScrollChain('U', 5);
+ break;
+ case kObjectMushroom:
+ _vm->_dialogs->displayScrollChain('U', 6);
+ _vm->gameOver();
+ break;
+ case kObjectOnion:
+ if (_vm->_rottenOnion)
+ _vm->_dialogs->displayScrollChain('U', 11);
+ else {
+ _vm->_dialogs->displayScrollChain('U', 8);
+ _vm->_objects[kObjectOnion - 1] = false;
+ _vm->refreshObjectList();
+ }
+ break;
+ default:
+ if ((_vm->_room == kRoomArgentPub) || (_vm->_room == kRoomNottsPub))
+ _vm->_dialogs->displayText("Try BUYing things before you drink them!");
+ else
+ _vm->_dialogs->displayText("The taste of it makes you retch!");
+ }
+}
+
+/**
+ * this lists the other people in the room.
+ */
+void Parser::peopleInRoom() {
+ // First compute the number of people in the room.
+ byte numPeople = 0;
+ for (int i = 151; i < 179; i++) { // Start at 1 so we don't list Avvy himself!
+ if (_vm->getRoom((People)i) == _vm->_room)
+ numPeople++;
+ }
+
+ // If nobody's here, we can cut out straight away.
+ if (numPeople == 0)
+ return;
+
+ Common::String tmpStr;
+ byte actPerson = 0;
+ for (int i = 151; i < 179; i++) {
+ if (_vm->getRoom((People)i) == _vm->_room) {
+ actPerson++;
+ if (actPerson == 1)
+ // Display first name on the list.
+ tmpStr = _vm->getName((People)i);
+ else if (actPerson < numPeople)
+ // Display one the names in the middle of the list
+ tmpStr += ", " + _vm->getName((People)i);
+ else
+ // Display the last name of the list
+ tmpStr += " and " + _vm->getName((People)i);
+ }
+ }
+
+ if (numPeople == 1)
+ tmpStr += " is";
+ else
+ tmpStr += " are";
+
+ _vm->_dialogs->displayText(tmpStr + " here.");
+}
+
+/**
+ * This is called when you say "look".
+ */
+void Parser::lookAround() {
+ _vm->_dialogs->displayText(*_vm->_also[0][1]);
+ switch (_vm->_room) {
+ case kRoomSpludwicks:
+ if (_vm->_avariciusTalk > 0)
+ _vm->_dialogs->displayScrollChain('Q', 23);
+ else
+ peopleInRoom();
+ break;
+ case kRoomRobins:
+ if (_vm->_tiedUp)
+ _vm->_dialogs->displayScrollChain('Q', 38);
+ if (_vm->_mushroomGrowing)
+ _vm->_dialogs->displayScrollChain('Q', 55);
+ break;
+ case kRoomInsideCardiffCastle:
+ if (!_vm->_takenPen)
+ _vm->_dialogs->displayScrollChain('Q', 49);
+ break;
+ case kRoomLustiesRoom:
+ if (_vm->_lustieIsAsleep)
+ _vm->_dialogs->displayScrollChain('Q', 65);
+ break;
+ case kRoomCatacombs:
+ switch (_vm->_catacombY * 256 + _vm->_catacombX) {
+ case 258 :
+ // Inside art gallery.
+ _vm->_dialogs->displayScrollChain('Q', 80);
+ break;
+ case 514 :
+ // Outside ditto.
+ _vm->_dialogs->displayScrollChain('Q', 81);
+ break;
+ case 260 :
+ // Outside Geida's room.
+ _vm->_dialogs->displayScrollChain('Q', 82);
+ break;
+ }
+ break;
+ default:
+ peopleInRoom();
+ }
+}
+
+void Parser::openDoor() {
+ // Special cases.
+ switch (_vm->_room) {
+ case kRoomYours:
+ if (_vm->_animation->inField(1)) {
+ // Opening the box.
+ _thing = 54; // The box.
+ _person = kPeoplePardon;
+ examine();
+ return;
+ }
+ break;
+ case kRoomSpludwicks:
+ if (_thing == 61) {
+ _vm->_dialogs->displayScrollChain('Q', 85);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ((!_vm->_userMovesAvvy) && (_vm->_room != kRoomLusties))
+ // No doors can open if you can't move Avvy.
+ return;
+
+ for (int i = 0; i < 7; i++) {
+ if (_vm->_animation->inField(i + 8)) {
+ MagicType *portal = &_vm->_portals[i];
+ switch (portal->_operation) {
+ case kMagicExclaim:
+ _vm->_animation->_sprites[0]->bounce();
+ _vm->_dialogs->displayScrollChain('X', portal->_data);
+ break;
+ case kMagicTransport:
+ _vm->flipRoom((Room)((portal->_data) >> 8), portal->_data & 0x0F);
+ break;
+ case kMagicUnfinished:
+ _vm->_animation->_sprites[0]->bounce();
+ _vm->_dialogs->displayText("Sorry. This place is not available yet!");
+ break;
+ case kMagicSpecial:
+ _vm->_animation->callSpecial(portal->_data);
+ break;
+ case kMagicOpenDoor:
+ _vm->openDoor((Room)(portal->_data >> 8), portal->_data & 0x0F, i + 9);
+ break;
+ }
+
+ return;
+ }
+ }
+
+ if (_vm->_room == kRoomMap)
+ _vm->_dialogs->displayText("Avvy, you can complete the whole game without ever going " \
+ "to anywhere other than Argent, Birmingham, Cardiff, Nottingham and Norwich.");
+ else
+ _vm->_dialogs->displayText("Door? What door?");
+}
+
+/**
+ * Called when you call kVerbCodeput.
+ */
+void Parser::putProc() {
+ if (!isHolding())
+ return;
+
+ // Slip the second object.
+ _thing2 -= 49;
+ char temp = _thing;
+ _thing = _thing2;
+ if (!isHolding())
+ return;
+ _thing = temp;
+
+ // Thing is the _thing which you're putting in. _thing2 is where you're putting it.
+ switch (_thing2) {
+ case kObjectWine:
+ if (_thing == kObjectOnion) {
+ if (_vm->_rottenOnion)
+ _vm->_dialogs->displayText("That's a bit like shutting the stable door after the horse has bolted!");
+ else {
+ // Put onion into wine?
+ if (_vm->_wineState != 3) {
+ Common::String tmpStr = Common::String::format("%cOignon au vin%c is a bit too strong for your tastes!",
+ kControlItalic, kControlRoman);
+ _vm->_dialogs->displayText(tmpStr);
+ } else {
+ // Put onion into vinegar! Yes!
+ _vm->_onionInVinegar = true;
+ _vm->incScore(7);
+ _vm->_dialogs->displayScrollChain('U', 9);
+ }
+ }
+ } else
+ _vm->_dialogs->saySilly();
+ break;
+
+ case 54:
+ if (_vm->_room == kRoomYours) {
+ // Put something into the box.
+ if (_vm->_boxContent != kNothing)
+ _vm->_dialogs->displayText("There's something in the box already, Avvy. Try taking that out first.");
+ else {
+ switch (_thing) {
+ case kObjectMoney:
+ _vm->_dialogs->displayText("You'd better keep some ready cash on you!");
+ break;
+ case kObjectBell:
+ _vm->_dialogs->displayText("That's a silly place to keep a bell.");
+ break;
+ case kObjectBodkin:
+ _vm->_dialogs->displayText("But you might need it!");
+ break;
+ case kObjectOnion:
+ _vm->_dialogs->displayText("Just give it to Spludwick, Avvy!");
+ break;
+ default:
+ // Put the object into the box...
+ if (_wearing == _thing) {
+ Common::String tmpStr = Common::String::format("You'd better take %s off first!", _vm->getItem(_thing).c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ } else {
+ // Open box.
+ openBox(true);
+
+ _vm->_boxContent = _thing;
+ _vm->_objects[_thing - 1] = false;
+ _vm->refreshObjectList();
+ _vm->_dialogs->displayText("OK, it's in the box.");
+
+ // Shut box.
+ openBox(false);
+ }
+ }
+ }
+ } else
+ _vm->_dialogs->saySilly();
+ break;
+
+ default:
+ _vm->_dialogs->saySilly();
+ }
+}
+
+/**
+ * Display text when ingredients are not in the right order
+ * @remarks Originally called 'not_in_order'
+ */
+void Parser::notInOrder() {
+ Common::String itemStr = _vm->getItem(_vm->kSpludwicksOrder[_vm->_givenToSpludwick]);
+ Common::String tmpStr = Common::String::format("Sorry, I need the ingredients in the right order for this potion. " \
+ "What I need next is %s%c2%c", itemStr.c_str(), kControlRegister, kControlSpeechBubble);
+ _vm->_dialogs->displayText(tmpStr);
+}
+
+/**
+ * Move Spludwick to cauldron
+ * @remarks Originally called 'go_to_cauldron'
+ */
+void Parser::goToCauldron() {
+ // Stops Geida_Procs.
+ _vm->_animation->_sprites[1]->_callEachStepFl = false;
+ _vm->_timer->addTimer(1, Timer::kProcSpludwickGoesToCauldron, Timer::kReasonSpludwickWalk);
+ _vm->_animation->_sprites[1]->walkTo(1);
+}
+
+/**
+ * Check is it's possible to give something to Spludwick
+ * The result of this function is whether or not he says "Hey, thanks!".
+ * @remarks Originally called 'give2spludwick'
+ */
+bool Parser::giveToSpludwick() {
+ if (_vm->kSpludwicksOrder[_vm->_givenToSpludwick] != _thing) {
+ notInOrder();
+ return false;
+ }
+
+ switch (_thing) {
+ case kObjectOnion:
+ _vm->_objects[kObjectOnion - 1] = false;
+ if (_vm->_rottenOnion)
+ _vm->_dialogs->displayScrollChain('Q', 22);
+ else {
+ _vm->_givenToSpludwick++;
+ _vm->_dialogs->displayScrollChain('Q', 20);
+ goToCauldron();
+ _vm->incScore(3);
+ }
+ _vm->refreshObjectList();
+ break;
+ case kObjectInk:
+ _vm->_objects[kObjectInk - 1] = false;
+ _vm->refreshObjectList();
+ _vm->_givenToSpludwick++;
+ _vm->_dialogs->displayScrollChain('Q', 24);
+ goToCauldron();
+ _vm->incScore(3);
+ break;
+ case kObjectMushroom:
+ _vm->_objects[kObjectMushroom - 1] = false;
+ _vm->_dialogs->displayScrollChain('Q', 25);
+ _vm->incScore(5);
+ _vm->_givenToSpludwick++;
+ goToCauldron();
+ _vm->_objects[kObjectPotion - 1] = true;
+ _vm->refreshObjectList();
+ break;
+ default:
+ return true;
+ }
+ return false;
+}
+
+void Parser::drink() {
+ _alcoholLevel++;
+ if (_alcoholLevel == 5) {
+ // Get the key.
+ _vm->_objects[kObjectKey - 1] = true;
+ _vm->_teetotal = true;
+ _vm->_avvyIsAwake = false;
+ _vm->_avvyInBed = true;
+ _vm->refreshObjectList();
+ _vm->fadeOut();
+ _vm->flipRoom(kRoomYours, 1);
+ _vm->_graphics->setBackgroundColor(kColorYellow);
+ _vm->_animation->_sprites[0]->_visible = false;
+ }
+}
+
+void Parser::cardiffClimbing() {
+ if (_vm->_standingOnDais) {
+ // Clamber up.
+ _vm->_dialogs->displayText("You climb down, back onto the floor.");
+ _vm->_standingOnDais = false;
+ _vm->_animation->appearPed(0, 2);
+ } else if (_vm->_animation->inField(0)) {
+ // Clamber down
+ _vm->_dialogs->displayText("You clamber up onto the dais.");
+ _vm->_standingOnDais = true;
+ _vm->_animation->appearPed(0, 1);
+ } else
+ _vm->_dialogs->displayText("Get a bit closer, Avvy.");
+}
+
+void Parser::already() {
+ _vm->_dialogs->displayText("You're already standing!");
+}
+
+/**
+ * Called when you ask Avvy to stand.
+ */
+void Parser::standUp() {
+ switch (_vm->_room) {
+ case kRoomYours:
+ // Avvy isn't asleep.
+ if (_vm->_avvyIsAwake && _vm->_avvyInBed) {
+ // But he's in bed.
+ if (_vm->_teetotal) {
+ _vm->_dialogs->displayScrollChain('D', 12);
+ _vm->_graphics->setBackgroundColor(kColorBlack);
+ _vm->_dialogs->displayScrollChain('D', 14);
+ }
+ _vm->_animation->_sprites[0]->_visible = true;
+ _vm->_userMovesAvvy = true;
+ _vm->_animation->appearPed(0, 1);
+ _vm->_animation->setDirection(kDirLeft);
+ // Display a picture of empty pillow in the background.
+ _vm->_background->draw(-1, -1, 3);
+ _vm->incScore(1);
+ _vm->_avvyInBed = false;
+ _vm->_timer->loseTimer(Timer::kReasonArkataShouts);
+ } else
+ already();
+ break;
+
+ case kRoomInsideCardiffCastle:
+ cardiffClimbing();
+ break;
+
+ case kRoomNottsPub:
+ if (_vm->_sittingInPub) {
+ // Not sitting down.
+ _vm->_background->draw(-1, -1, 3);
+ // But standing up.
+ _vm->_animation->_sprites[0]->_visible = true;
+ // And walking away.
+ _vm->_animation->appearPed(0, 3);
+ // Really not sitting down.
+ _vm->_sittingInPub = false;
+ // And ambulant.
+ _vm->_userMovesAvvy = true;
+ } else
+ already();
+ break;
+ default:
+ already();
+ }
+}
+
+void Parser::getProc(char thing) {
+ switch (_vm->_room) {
+ case kRoomYours:
+ if (_vm->_animation->inField(1)) {
+ if (_vm->_boxContent == thing) {
+ _vm->_background->draw(-1, -1, 4);
+ _vm->_dialogs->displayText("OK, I've got it.");
+ _vm->_objects[thing - 1] = true;
+ _vm->refreshObjectList();
+ _vm->_boxContent = kNothing;
+ _vm->_background->draw(-1, -1, 5);
+ } else {
+ Common::String tmpStr = Common::String::format("I can't see %s in the box.", _vm->getItem(thing).c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ } else
+ _vm->_dialogs->displayScrollChain('Q', 57);
+ break;
+ case kRoomInsideCardiffCastle:
+ switch (thing) {
+ case kObjectPen:
+ if (_vm->_animation->inField(1)) {
+ // Standing on the dais.
+ if (_vm->_takenPen)
+ _vm->_dialogs->displayText("It's not there, Avvy.");
+ else {
+ // OK: we're taking the pen, and it's there.
+ // No pen there now.
+ _vm->_background->draw(-1, -1, 3);
+ // Zap!
+ _vm->_animation->callSpecial(3);
+ _vm->_takenPen = true;
+ _vm->_objects[kObjectPen - 1] = true;
+ _vm->refreshObjectList();
+ _vm->_dialogs->displayText("Taken.");
+ }
+ } else if (_vm->_standingOnDais)
+ _vm->_dialogs->displayScrollChain('Q', 53);
+ else
+ _vm->_dialogs->displayScrollChain('Q', 51);
+ break;
+ case kObjectBolt:
+ _vm->_dialogs->displayScrollChain('Q', 52);
+ break;
+ default:
+ _vm->_dialogs->displayScrollChain('Q', 57);
+ }
+ break;
+ case kRoomRobins:
+ if ((thing == kObjectMushroom) & (_vm->_animation->inField(0)) & (_vm->_mushroomGrowing)) {
+ _vm->_background->draw(-1, -1, 2);
+ _vm->_dialogs->displayText("Got it!");
+ _vm->_mushroomGrowing = false;
+ _vm->_takenMushroom = true;
+ _vm->_objects[kObjectMushroom - 1] = true;
+ _vm->refreshObjectList();
+ _vm->incScore(3);
+ } else
+ _vm->_dialogs->displayScrollChain('Q', 57);
+ break;
+ default:
+ _vm->_dialogs->displayScrollChain('Q', 57);
+ }
+}
+
+/**
+ * Give the lute to Geida
+ * @remarks Originally called 'give_Geida_the_lute'
+ */
+void Parser::giveGeidaTheLute() {
+ if (_vm->_room != kRoomLustiesRoom) {
+ Common::String tmpStr = Common::String::format("Not yet. Try later!%c2%c", kControlRegister, kControlSpeechBubble);
+ _vm->_dialogs->displayText(tmpStr);
+ return;
+ }
+ _vm->_objects[kObjectLute - 1] = false;
+ _vm->refreshObjectList();
+ // She plays it.
+ _vm->_dialogs->displayScrollChain('Q', 64);
+
+ _vm->_timer->addTimer(1, Timer::kProcGiveLuteToGeida, Timer::kReasonGeidaSings);
+ //_vm->_enid->backToBootstrap(4); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then!
+}
+
+void Parser::playHarp() {
+ if (_vm->_animation->inField(6))
+ _vm->_dialogs->displayMusicalScroll();
+ else
+ _vm->_dialogs->displayText("Get a bit closer to it, Avvy!");
+}
+
+void Parser::winSequence() {
+ _vm->_dialogs->displayScrollChain('Q', 78);
+ _vm->_sequence->startWinSeq();
+ _vm->_timer->addTimer(30, Timer::kProcWinning, Timer::kReasonWinning);
+}
+
+/**
+ * @remarks Originally called 'do_that'
+ */
+void Parser::doThat() {
+ static const char booze[8][8] = {"Bitter", "GIED", "Whisky", "Cider", "", "", "", "Mead"};
+ static const char kWhat[] = "That's not possible!";
+
+ if (_thats == Common::String(kNothing)) {
+ if (!_thats.empty())
+ _thats.clear();
+ return;
+ }
+
+ if (_weirdWord)
+ return;
+
+ if (_thing < 200)
+ // "Slip" object
+ _thing -= 49;
+
+ if ((_verb != kVerbCodeLoad) && (_verb != kVerbCodeSave) && (_verb != kVerbCodeQuit) && (_verb != kVerbCodeInfo) && (_verb != kVerbCodeHelp)
+ && (_verb != kVerbCodeLarrypass) && (_verb != kVerbCodePhaon) && (_verb != kVerbCodeBoss) && (_verb != kVerbCodeCheat) && (_verb != kVerbCodeRestart)
+ && (_verb != kVerbCodeDir) && (_verb != kVerbCodeScore) && (_verb != kVerbCodeHiscores) && (_verb != kVerbCodeSmartAlec)) {
+ if (!_vm->_alive) {
+ _vm->_dialogs->displayText("You're dead, so don't talk. What are you, a ghost or something? " \
+ "Try restarting, or restoring a saved game!");
+ return;
+ }
+ if (!_vm->_avvyIsAwake && (_verb != kVerbCodeDie) && (_verb != kVerbCodeExpletive) && (_verb != kVerbCodeWake)) {
+ _vm->_dialogs->displayText("Talking in your sleep? Try waking up!");
+ return;
+ }
+ }
+
+ switch (_verb) {
+ case kVerbCodeExam:
+ examine();
+ break;
+ case kVerbCodeOpen:
+ openDoor();
+ break;
+ case kVerbCodePause: {
+ // Note that the original game doesn't care about the "O.K." box neither, it accepts
+ // clicks from everywhere on the screen to continue. Just like my code.
+ Common::String tmpStr = Common::String::format("Game paused.%c%c%cPress Enter, Esc, or click the mouse on the `O.K.\" " \
+ "box to continue.", kControlCenter, kControlNewLine, kControlNewLine);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodeGet:
+ if (_thing != kPardon) {
+ // Legitimate try to pick something up.
+ if (_vm->_carryNum >= kCarryLimit)
+ _vm->_dialogs->displayText("You can't carry any more!");
+ else
+ getProc(_thing);
+ } else {
+ // Not... ditto.
+ if (_person != kPeoplePardon)
+ _vm->_dialogs->displayText("You can't sweep folk off their feet!");
+ else
+ _vm->_dialogs->displayText("I assure you, you don't need it.");
+ }
+ break;
+ case kVerbCodeDrop:
+ _vm->_dialogs->displayText("Two years ago you dropped a florin in the street. Three days " \
+ "later it was gone! So now you never leave ANYTHING lying around. OK?");
+ break;
+ case kVerbCodeInv:
+ inventory();
+ break;
+ case kVerbCodeTalk:
+ if (_person == kPeoplePardon) {
+ if (_vm->_subjectNum == 99) {
+ // They typed "say password".
+ Common::String tmpStr = Common::String::format("Yes, but what %cis%c the password?", kControlItalic, kControlRoman);
+ _vm->_dialogs->displayText(tmpStr);
+ } else if (((1 <= _vm->_subjectNum) && (_vm->_subjectNum <= 49)) || (_vm->_subjectNum == 253) || (_vm->_subjectNum == 249)) {
+ _thats.deleteChar(0);
+
+ for (int i = 0; i < 10; i++)
+ _realWords[i] = _realWords[i + 1];
+
+ _verb = (VerbCode)_vm->_subjectNum;
+ doThat();
+ return;
+ } else {
+ _person = (People)_vm->_subjectNum;
+ _vm->_subjectNum = 0;
+ if ((_person == kPeopleNone) || (_person == kPeoplePardon))
+ _vm->_dialogs->displayText("Talk to whom?");
+ else if (isPersonHere())
+ _vm->_dialogs->talkTo(_person);
+ }
+ } else if (isPersonHere())
+ _vm->_dialogs->talkTo(_person);
+ break;
+ case kVerbCodeGive:
+ if (isHolding()) {
+ if (_person == kPeoplePardon)
+ _vm->_dialogs->displayText("Give to whom?");
+ else if (isPersonHere()) {
+ switch (_thing) {
+ case kObjectMoney :
+ _vm->_dialogs->displayText("You can't bring yourself to give away your moneybag.");
+ break;
+ case kObjectBodkin:
+ case kObjectBell:
+ case kObjectClothes:
+ case kObjectHabit :
+ _vm->_dialogs->displayText("Don't give it away, it might be useful!");
+ break;
+ default:
+ switch (_person) {
+ case kPeopleCrapulus:
+ if (_thing == kObjectWine) {
+ _vm->_dialogs->displayText("Crapulus grabs the wine and gulps it down.");
+ _vm->_objects[kObjectWine - 1] = false;
+ } else
+ _vm->_dialogs->sayThanks(_thing - 1);
+ break;
+ case kPeopleCwytalot:
+ if ((_thing == kObjectCrossbow) || (_thing == kObjectBolt))
+ _vm->_dialogs->displayText("You might be able to influence Cwytalot more if you used it!");
+ else
+ _vm->_dialogs->sayThanks(_thing - 1);
+ break;
+ case kPeopleSpludwick:
+ if (giveToSpludwick())
+ _vm->_dialogs->sayThanks(_thing - 1);
+ break;
+ case kPeopleIbythneth:
+ if (_thing == kObjectBadge) {
+ _vm->_dialogs->displayScrollChain('Q', 32); // Thanks! Wow!
+ _vm->incScore(3);
+ _vm->_objects[kObjectBadge - 1] = false;
+ _vm->_objects[kObjectHabit - 1] = true;
+ _vm->_givenBadgeToIby = true;
+ _vm->_background->draw(-1, -1, 7);
+ _vm->_background->draw(-1, -1, 8);
+ } else
+ _vm->_dialogs->sayThanks(_thing - 1);
+ break;
+ case kPeopleAyles:
+ if (_vm->_aylesIsAwake) {
+ if (_thing == kObjectPen) {
+ _vm->_objects[kObjectPen - 1] = false;
+ _vm->_dialogs->displayScrollChain('Q', 54);
+ _vm->_objects[kObjectInk - 1] = true;
+ _vm->_givenPenToAyles = true;
+ _vm->refreshObjectList();
+ _vm->incScore(2);
+ } else
+ _vm->_dialogs->sayThanks(_thing - 1);
+ } else
+ _vm->_dialogs->displayText("But he's asleep!");
+ break;
+ case kPeopleGeida:
+ switch (_thing) {
+ case kObjectPotion:
+ _vm->_objects[kObjectPotion - 1] = false;
+ // She drinks it.
+ _vm->_dialogs->displayScrollChain('U', 16);
+ _vm->incScore(2);
+ _vm->_givenPotionToGeida = true;
+ _vm->refreshObjectList();
+ break;
+ case kObjectLute:
+ giveGeidaTheLute();
+ break;
+ default:
+ _vm->_dialogs->sayThanks(_thing - 1);
+ }
+ break;
+ case kPeopleArkata:
+ switch (_thing) {
+ case kObjectPotion:
+ if (_vm->_givenPotionToGeida)
+ winSequence();
+ else
+ // That Geida woman!
+ _vm->_dialogs->displayScrollChain('Q', 77);
+ break;
+ default:
+ _vm->_dialogs->sayThanks(_thing - 1);
+ }
+ break;
+ default:
+ _vm->_dialogs->sayThanks(_thing - 1);
+ }
+ }
+ }
+ // Just in case...
+ _vm->refreshObjectList();
+ }
+ break;
+
+ case kVerbCodeEat:
+ case kVerbCodeDrink:
+ if (isHolding())
+ swallow();
+ break;
+
+ case kVerbCodeLoad: {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ int16 savegameId = dialog->runModalWithCurrentTarget();
+ delete dialog;
+
+ if (savegameId < 0)
+ // dialog aborted, nothing to load
+ return;
+
+ _vm->loadGame(savegameId);
+ }
+ break;
+ case kVerbCodeSave: {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ int16 savegameId = dialog->runModalWithCurrentTarget();
+ Common::String savegameDescription = dialog->getResultString();
+ delete dialog;
+
+ if (savegameId < 0)
+ // dialog aborted, nothing to save
+ return;
+
+ _vm->saveGame(savegameId, savegameDescription);
+ }
+ break;
+ case kVerbCodePay:
+ _vm->_dialogs->displayText("No money need change hands.");
+ break;
+ case kVerbCodeLook:
+ lookAround();
+ break;
+ case kVerbCodeBreak:
+ _vm->_dialogs->displayText("Vandalism is prohibited within this game!");
+ break;
+ case kVerbCodeQuit:
+ if (!_polite)
+ _vm->_dialogs->displayText("How about a `please\", Avvy?");
+ else {
+ Common::String tmpStr = Common::String::format("%cC%cDo you really want to quit?", kControlRegister, kControlIcon);
+ if (_vm->_dialogs->displayQuestion(tmpStr))
+ _vm->_letMeOut = true;
+ }
+ break;
+ case kVerbCodeGo:
+ _vm->_dialogs->displayText("Just use the arrow keys to walk there.");
+ break;
+ case kVerbCodeInfo: {
+ _vm->_dialogs->_aboutBox = true;
+
+ Common::String toDisplay;
+ for (int i = 0; i < 7; i++)
+ toDisplay += kControlNewLine;
+ toDisplay = toDisplay + "LORD AVALOT D'ARGENT" + kControlCenter + kControlNewLine
+ + "The medi\x91val descendant of" + kControlNewLine
+ + "Denarius Avaricius Sextus" + kControlNewLine + kControlNewLine
+ + "version " + kVersionNum + kControlNewLine + kControlNewLine + "Copyright \xEF "
+ + kCopyright + ", Mark, Mike and Thomas Thurman." + kControlRegister + 'Y' + kControlIcon;
+ _vm->_dialogs->displayText(toDisplay);
+ _vm->_dialogs->_aboutBox = false;
+ }
+ break;
+ case kVerbCodeUndress:
+ if (_wearing == kNothing)
+ _vm->_dialogs->displayText("You're already stark naked!");
+ else if (_vm->_avvysInTheCupboard) {
+ Common::String tmpStr = Common::String::format("You take off %s.", _vm->getItem(_wearing).c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ _wearing = kNothing;
+ _vm->refreshObjectList();
+ } else
+ _vm->_dialogs->displayText("Hadn't you better find somewhere more private, Avvy?");
+ break;
+ case kVerbCodeWear:
+ if (isHolding()) { // Wear something.
+ switch (_thing) {
+ case kObjectChastity:
+ // \? are used to avoid that ??! is parsed as a trigraph
+ _vm->_dialogs->displayText("Hey, what kind of a weirdo are you\?\?!");
+ break;
+ case kObjectClothes:
+ case kObjectHabit: {
+ // Change clothes!
+ if (_wearing != kNothing) {
+ if (_wearing == _thing)
+ _vm->_dialogs->displayText("You're already wearing that.");
+ else
+ _vm->_dialogs->displayText("You'll be rather warm wearing two sets of clothes!");
+ return;
+ } else
+ _wearing = _thing;
+
+ _vm->refreshObjectList();
+
+ byte i;
+ if (_thing == kObjectHabit)
+ i = 3;
+ else
+ i = 0;
+
+ _vm->_animation->setAvvyClothes(i);
+ }
+ break;
+ default:
+ _vm->_dialogs->displayText(kWhat);
+ }
+ }
+ break;
+ case kVerbCodePlay:
+ if (_thing == kPardon) {
+ // They just typed "play"...
+ switch (_vm->_room) {
+ case kRoomArgentPub:
+ _vm->_nim->playNim(); // ...in the pub, => play Nim.
+ break;
+ case kRoomMusicRoom:
+ playHarp();
+ break;
+ default:
+ break;
+ }
+ } else if (isHolding()) {
+ switch (_thing) {
+ case kObjectLute :
+ _vm->_dialogs->displayScrollChain('U', 7);
+
+ if (_vm->getRoom(kPeopleCwytalot) == _vm->_room)
+ _vm->_dialogs->displayScrollChain('U', 10);
+
+ if (_vm->getRoom(kPeopleDuLustie) == _vm->_room)
+ _vm->_dialogs->displayScrollChain('U', 15);
+ break;
+ case 52:
+ if (_vm->_room == kRoomMusicRoom)
+ playHarp();
+ else
+ _vm->_dialogs->displayText(kWhat);
+ break;
+ case 55:
+ if (_vm->_room == kRoomArgentPub)
+ // play_nim();
+ warning("STUB: Parser::doThat() - case kVerbCodeplay - play_nim()");
+ else
+ _vm->_dialogs->displayText(kWhat);
+ break;
+ default:
+ _vm->_dialogs->displayText(kWhat);
+ }
+ }
+ break;
+ case kVerbCodeRing:
+ if (isHolding()) {
+ if (_thing == kObjectBell) {
+ _vm->_dialogs->displayText("Ding, dong, ding, dong, ding, dong, ding, dong...");
+ if ((_vm->_bellsAreRinging) & (_vm->getFlag('B')))
+ // '\?' are used to avoid that '??!' is parsed as a trigraph
+ _vm->_dialogs->displayText("(Are you trying to join in, Avvy\?\?!)");
+ } else
+ _vm->_dialogs->displayText(kWhat);
+ }
+ break;
+ case kVerbCodeHelp:
+ // boot_help();
+ warning("STUB: Parser::doThat() - case kVerbCodehelp");
+ break;
+ case kVerbCodeLarrypass:
+ _vm->_dialogs->displayText("Wrong game!");
+ break;
+ case kVerbCodePhaon:
+ _vm->_dialogs->displayText("Hello, Phaon!");
+ break;
+ case kVerbCodeBoss:
+ // bosskey();
+ warning("STUB: Parser::doThat() - case kVerbCodeboss");
+ break;
+ case kVerbCodePee:
+ if (_vm->getFlag('P')) {
+ _vm->_dialogs->displayText("Hmm, I don't think anyone will notice...");
+ _vm->_timer->addTimer(4, Timer::kProcUrinate, Timer::kReasonGoToToilet);
+ } else {
+ Common::String tmpStr = Common::String::format("It would be %cVERY%c unwise to do that here, Avvy!", kControlItalic, kControlRoman);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodeCheat: {
+ Common::String tmpStr = Common::String::format("%cCheat mode now enabled.", kControlItalic);
+ _vm->_dialogs->displayText(tmpStr);
+ _vm->_cheat = true;
+ }
+ break;
+ case kVerbCodeMagic:
+ if (_vm->_avariciusTalk > 0)
+ _vm->_dialogs->displayScrollChain('Q', 19);
+ else {
+ if ((_vm->_room == kRoomSpludwicks) & (_vm->_animation->inField(1))) {
+ // Avaricius appears!
+ _vm->_dialogs->displayScrollChain('Q', 17);
+ if (_vm->getRoom(kPeopleSpludwick) == kRoomSpludwicks)
+ _vm->_dialogs->displayScrollChain('Q', 18);
+ else {
+ Avalanche::AnimationType *spr = _vm->_animation->_sprites[1];
+ // Avaricius
+ spr->init(1, false);
+ _vm->_animation->appearPed(1, 3);
+ spr->walkTo(4);
+ spr->_callEachStepFl = true;
+ spr->_eachStepProc = Animation::kProcBackAndForth;
+ _vm->_avariciusTalk = 14;
+ _vm->_timer->addTimer(177, Timer::kProcAvariciusTalks, Timer::kReasonAvariciusTalks);
+ }
+ } else
+ _vm->_dialogs->displayText("Nothing appears to happen...");
+ }
+ break;
+ case kVerbCodeSmartAlec:
+ _vm->_dialogs->displayText("Listen, smart alec, that was just rhetoric.");
+ break;
+ case kVerbCodeExpletive:
+ switch (_sworeNum) {
+ case 0: {
+ Common::String tmpStr = Common::String::format("Avvy! Do you mind? There might be kids playing!%c%c" \
+ "(I shouldn't say it again, if I were you!)", kControlNewLine, kControlNewLine);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case 1: {
+ Common::String tmpStr = Common::String::format("You hear a distant rumble of thunder. Must you always" \
+ "do things I tell you not to?%c%cDon't do it again!", kControlNewLine, kControlNewLine);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ default: {
+ _vm->_pingo->zonk();
+ Common::String tmpStr = Common::String::format("A crack of lightning shoots from the sky, and fries you." \
+ "%c%c(`Such is the anger of the gods, Avvy!\")", kControlNewLine, kControlNewLine);
+ _vm->_dialogs->displayText(tmpStr);
+ _vm->gameOver();
+ }
+ }
+ _sworeNum++;
+ break;
+ case kVerbCodeListen:
+ if ((_vm->_bellsAreRinging) & (_vm->getFlag('B')))
+ _vm->_dialogs->displayText("All other noise is drowned out by the ringing of the bells.");
+ else if (_vm->_listen.empty())
+ _vm->_dialogs->displayText("You can't hear anything much at the moment, Avvy.");
+ else
+ _vm->_dialogs->displayText(_vm->_listen);
+ break;
+ case kVerbCodeBuy:
+ // What are they trying to buy?
+ switch (_vm->_room) {
+ case kRoomArgentPub:
+ // We're in a pub, and near the bar.
+ if (_vm->_animation->inField(5)) {
+ switch (_thing) {
+ case 51:
+ case 53:
+ case 54:
+ case 58:
+ // Beer, whisky, cider or mead.
+ if (_vm->_malagauche == 177) {
+ // Already getting us one.
+ _vm->_dialogs->displayScrollChain('D', 15);
+ return;
+ }
+
+ if (_vm->_teetotal) {
+ _vm->_dialogs->displayScrollChain('D', 6);
+ return;
+ }
+
+ if (_alcoholLevel == 0)
+ _vm->incScore(3);
+
+ _vm->_background->draw(-1, -1, 11);
+ _vm->_dialogs->displayText(Common::String(booze[_thing - 51]) + ", please." + kControlRegister + '1' + kControlSpeechBubble);
+ _vm->_drinking = _thing;
+
+ _vm->_background->draw(-1, -1, 9);
+ _vm->_malagauche = 177;
+ _vm->_timer->addTimer(27, Timer::kProcBuyDrinks, Timer::kReasonDrinks);
+ break;
+ case 52:
+ examine();
+ break; // We have a right one here - buy Pepsi??!
+ case kObjectWine:
+ if (_vm->_objects[kObjectWine - 1])
+ // We've already got the wine!
+ // 1 bottle's shufishent!
+ _vm->_dialogs->displayScrollChain('D', 2);
+ else {
+ if (_vm->_malagauche == 177) {
+ // Already getting us one.
+ _vm->_dialogs->displayScrollChain('D', 15);
+ return;
+ }
+
+ if (_vm->_carryNum >= kCarryLimit) {
+ _vm->_dialogs->displayText("Your hands are full.");
+ return;
+ }
+
+ _vm->_background->draw(-1, -1, 11);
+ Common::String tmpStr = Common::String::format("Wine, please.%c1%c", kControlRegister, kControlSpeechBubble);
+ _vm->_dialogs->displayText(tmpStr);
+ if (_alcoholLevel == 0)
+ _vm->incScore(3);
+ _vm->_background->draw(-1, -1, 9);
+ _vm->_malagauche = 177;
+
+ _vm->_timer->addTimer(27, Timer::kProcBuyWine, Timer::kReasonDrinks);
+ }
+ break;
+ }
+ } else
+ // Go to the bar!
+ _vm->_dialogs->displayScrollChain('D', 5);
+ break;
+
+ case kRoomOutsideDucks:
+ if (_vm->_animation->inField(5)) {
+ if (_thing == kObjectOnion) {
+ if (_vm->_objects[kObjectOnion - 1])
+ // Not planning to juggle with the things!
+ _vm->_dialogs->displayScrollChain('D', 10);
+ else if (_vm->_carryNum >= kCarryLimit)
+ _vm->_dialogs->displayText("Before you ask, you remember that your hands are full.");
+ else {
+ if (_boughtOnion)
+ _vm->_dialogs->displayScrollChain('D', 11);
+ else {
+ _vm->_dialogs->displayScrollChain('D', 9);
+ _vm->incScore(3);
+ }
+ // It costs thruppence.
+ _vm->decreaseMoney(3);
+ _vm->_objects[kObjectOnion - 1] = true;
+ _vm->refreshObjectList();
+ _boughtOnion = true;
+ // It's OK when it leaves the stall!
+ _vm->_rottenOnion = false;
+ _vm->_onionInVinegar = false;
+ }
+ } else
+ _vm->_dialogs->displayScrollChain('D', 0);
+ } else
+ _vm->_dialogs->displayScrollChain('D', 0);
+ break;
+
+ case kRoomNottsPub:
+ // Can't sell to southerners.
+ _vm->_dialogs->displayScrollChain('N', 15);
+ break;
+ default:
+ // Can't buy that.
+ _vm->_dialogs->displayScrollChain('D', 0);
+ }
+ break;
+ case kVerbCodeAttack:
+ if ((_vm->_room == kRoomBrummieRoad) &&
+ ((_person == kPeopleCwytalot) || (_thing == kObjectCrossbow) || (_thing == kObjectBolt)) &&
+ (_vm->getRoom(kPeopleCwytalot) == _vm->_room)) {
+ switch (_vm->_objects[kObjectBolt - 1] + _vm->_objects[kObjectCrossbow - 1] * 2) {
+ // 0 = neither, 1 = only bolt, 2 = only crossbow, 3 = both.
+ case 0:
+ _vm->_dialogs->displayScrollChain('Q', 10);
+ _vm->_dialogs->displayText("(At the very least, don't use your bare hands!)");
+ break;
+ case 1:
+ _vm->_dialogs->displayText("Attack _vm->him with only a crossbow bolt? Are you planning on playing darts?!");
+ break;
+ case 2:
+ _vm->_dialogs->displayText("Come on, Avvy! You're not going to get very far with only a crossbow!");
+ break;
+ case 3:
+ _vm->_dialogs->displayScrollChain('Q', 11);
+ _vm->_cwytalotGone = true;
+ _vm->_objects[kObjectBolt - 1] = false;
+ _vm->_objects[kObjectCrossbow - 1] = false;
+ _vm->refreshObjectList();
+ _vm->_magics[11]._operation = kMagicNothing;
+ _vm->incScore(7);
+ _vm->_animation->_sprites[1]->walkTo(1);
+ _vm->_animation->_sprites[1]->_vanishIfStill = true;
+ _vm->_animation->_sprites[1]->_callEachStepFl = false;
+ _vm->setRoom(kPeopleCwytalot, kRoomDummy);
+ break;
+ default:
+ // Please try not to be so violent!
+ _vm->_dialogs->displayScrollChain('Q', 10);
+ }
+ } else
+ _vm->_dialogs->displayScrollChain('Q', 10);
+ break;
+ case kVerbCodePasswd:
+ if (_vm->_room != kRoomBridge)
+ _vm->_dialogs->displayScrollChain('Q', 12);
+ else {
+ bool ok = true;
+ for (uint i = 0; i < _thats.size(); i++) {
+ Common::String temp = _realWords[i];
+ temp.toUppercase();
+ int pwdId = _vm->_passwordNum + kFirstPassword;
+ for (uint j = 0; j < _vocabulary[pwdId]._word.size(); j++) {
+ if (_vocabulary[pwdId]._word[j] != temp[j])
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ if (_vm->_drawbridgeOpen != 0)
+ _vm->_dialogs->displayText("Contrary to your expectations, the drawbridge fails to close again.");
+ else {
+ _vm->incScore(4);
+ _vm->_dialogs->displayText("The drawbridge opens!");
+ _vm->_timer->addTimer(7, Timer::kProcOpenDrawbridge, Timer::kReasonDrawbridgeFalls);
+ _vm->_drawbridgeOpen = 1;
+ }
+ } else
+ _vm->_dialogs->displayScrollChain('Q', 12);
+ }
+ break;
+ case kVerbCodeDie:
+ _vm->gameOver();
+ break;
+ case kVerbCodeScore: {
+ Common::String tmpStr = Common::String::format("Your score is %d,%c%cout of a possible 128.%c%c " \
+ "This gives you a rank of %s.%c%c%s", _vm->_dnascore, kControlCenter, kControlNewLine, kControlNewLine,
+ kControlNewLine, rank().c_str(), kControlNewLine, kControlNewLine, totalTime().c_str());
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodePut:
+ putProc();
+ break;
+ case kVerbCodeStand:
+ standUp();
+ break;
+ case kVerbCodeKiss:
+ if (_person == kPeoplePardon)
+ _vm->_dialogs->displayText("Kiss whom?");
+ else if (isPersonHere()) {
+ switch (_person) {
+ case kPeopleArkata:
+ _vm->_dialogs->displayScrollChain('U', 12);
+ break;
+ case kPeopleGeida:
+ _vm->_dialogs->displayScrollChain('U', 13);
+ break;
+ case kPeopleWisewoman:
+ _vm->_dialogs->displayScrollChain('U', 14);
+ break;
+ default:
+ // You WHAT?
+ _vm->_dialogs->displayScrollChain('U', 5);
+ }
+ } else if ((kPeopleAvalot <= _person) && (_person < kPeopleArkata))
+ _vm->_dialogs->displayText("Hey, what kind of a weirdo are you??");
+
+ break;
+ case kVerbCodeClimb:
+ if (_vm->_room == kRoomInsideCardiffCastle)
+ cardiffClimbing();
+ else
+ // In the wrong room!
+ _vm->_dialogs->displayText("Not with your head for heights, Avvy!");
+ break;
+ case kVerbCodeJump:
+ _vm->_timer->addTimer(1, Timer::kProcJump, Timer::kReasonJumping);
+ _vm->_userMovesAvvy = false;
+ break;
+ case kVerbCodeHiscores:
+ // show_highs();
+ warning("STUB: Parser::doThat() - case kVerbCodehighscores");
+ break;
+ case kVerbCodeWake:
+ if (isPersonHere())
+ switch (_person) {
+ case kPeoplePardon:
+ case kPeopleAvalot:
+ case 0:
+ if (!_vm->_avvyIsAwake) {
+ _vm->_avvyIsAwake = true;
+ _vm->incScore(1);
+ _vm->_avvyInBed = true;
+ // Picture of Avvy, awake in bed.
+ _vm->_background->draw(-1, -1, 2);
+ if (_vm->_teetotal)
+ _vm->_dialogs->displayScrollChain('D', 13);
+ } else
+ _vm->_dialogs->displayText("You're already awake, Avvy!");
+ break;
+ case kPeopleAyles:
+ if (!_vm->_aylesIsAwake)
+ _vm->_dialogs->displayText("You can't seem to wake him by yourself.");
+ break;
+ case kPeopleJacques: {
+ Common::String tmpStr = Common::String::format("Brother Jacques, Brother Jacques, are you asleep?%c1%c" \
+ "Hmmm... that doesn't seem to do any good...", kControlRegister, kControlSpeechBubble);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ default:
+ _vm->_dialogs->displayText("It's difficult to awaken people who aren't asleep...!");
+ }
+ break;
+ case kVerbCodeSit:
+ if (_vm->_room == kRoomNottsPub) {
+ if (_vm->_sittingInPub)
+ _vm->_dialogs->displayText("You're already sitting!");
+ else {
+ // Move Avvy to the place, and sit him down.
+ _vm->_animation->_sprites[0]->walkTo(3);
+ _vm->_timer->addTimer(1, Timer::kProcAvvySitDown, Timer::kReasonSittingDown);
+ }
+ } else {
+ // Default doodah.
+ _vm->fadeOut();
+ _vm->fadeIn();
+ Common::String tmpStr = Common::String::format("A few hours later...%cnothing much has happened...", kControlParagraph);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodeRestart:
+ if (_vm->_dialogs->displayQuestion("Restart game and lose changes?")) {
+ _vm->fadeOut();
+ _vm->newGame();
+ _vm->fadeIn();
+ }
+ break;
+ case kVerbCodePardon:
+ _vm->_dialogs->displayText("Hey, a verb would be helpful!");
+ break;
+ case kVerbCodeHello:
+ _vm->_dialogs->sayHello();
+ break;
+ case kVerbCodeThanks:
+ _vm->_dialogs->sayOK();
+ break;
+ default:
+ Common::String tmpStr = Common::String::format("%cUnhandled verb: %d", kControlBell, _verb);
+ _vm->_dialogs->displayText(tmpStr);
+ }
+}
+
+void Parser::verbOpt(byte verb, Common::String &answer, char &ansKey) {
+ // kVerbCodegive isn't dealt with by this procedure, but by ddm__with.
+ switch (verb) {
+ case kVerbCodeExam:
+ answer = "Examine";
+ ansKey = 'x';
+ break;
+ case kVerbCodeDrink:
+ answer = "Drink";
+ ansKey = 'D';
+ break;
+ case kVerbCodeWear:
+ answer = "Wear";
+ ansKey = 'W';
+ break;
+ case kVerbCodeRing:
+ answer = "Ring";
+ ansKey = 'R';
+ break; // Only the bell!
+ case kVerbCodePlay:
+ answer = "Play";
+ ansKey = 'P';
+ break;
+ case kVerbCodeEat:
+ answer = "Eat";
+ ansKey = 'E';
+ break;
+ default:
+ answer = "? Unknown!"; // Bug!
+ ansKey = '?';
+ }
+}
+
+void Parser::doVerb(VerbCode id) {
+ _weirdWord = false;
+ _polite = true;
+ _verb = id;
+ doThat();
+}
+
+void Parser::resetVariables() {
+ _wearing = kNothing;
+ _sworeNum = 0;
+ _alcoholLevel = 0;
+ _boughtOnion = false;
+}
+
+void Parser::synchronize(Common::Serializer &sz) {
+ sz.syncAsByte(_wearing);
+ sz.syncAsByte(_sworeNum);
+ sz.syncAsByte(_alcoholLevel);
+ if (sz.isLoading() && sz.getVersion() < 2) {
+ int dummy;
+ sz.syncAsByte(dummy);
+ }
+ sz.syncAsByte(_boughtOnion);
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/parser.h b/engines/avalanche/parser.h
new file mode 100644
index 0000000000..20066329e5
--- /dev/null
+++ b/engines/avalanche/parser.h
@@ -0,0 +1,153 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+#ifndef AVALANCHE_PARSER_H
+#define AVALANCHE_PARSER_H
+
+#include "avalanche/enums.h"
+
+#include "common/events.h"
+#include "common/str.h"
+#include "common/serializer.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Parser {
+public:
+ static const int16 kParserWordsNum = 277; // How many words does the parser know?
+ static const int16 kFirstPassword = 88; // words[kFirstPassword] should equal "TIROS".
+ static const byte kPardon = 254; // Didn't understand / wasn't given.
+ static const byte kNothing = 250;
+ static const byte kMoved = 0; // This word was moved. (Usually because it was the subject of conversation.)
+
+ struct VocabEntry {
+ byte _number;
+ Common::String _word;
+
+ void init(byte number, Common::String word) {
+ _number = number;
+ _word = word;
+ }
+ };
+
+ VocabEntry _vocabulary[kParserWordsNum];
+
+ Common::String _realWords[11];
+ VerbCode _verb;
+ byte _thing;
+ People _person;
+ bool _polite;
+ Common::String _inputText;
+ Common::String _inputTextBackup;
+ byte _inputTextPos;
+ bool _quote;
+ bool _cursorState;
+ bool _weirdWord;
+
+ byte _wearing; // what you're wearing
+
+ Parser(AvalancheEngine *vm);
+
+ void init();
+ void parse();
+ void doThat();
+ void verbOpt(byte verb, Common::String &answer, char &ansKey);
+ void drink();
+
+ void handleInputText(const Common::Event &event);
+ void handleBackspace();
+ void handleReturn();
+ void handleFunctionKey(const Common::Event &event);
+ void plotText();
+ void cursorOn();
+ void cursorOff();
+ void tryDropdown();
+ int16 getPos(const Common::String &crit, const Common::String &src);
+ void doVerb(VerbCode id);
+
+ void resetVariables();
+ void synchronize(Common::Serializer &sz);
+
+private:
+ AvalancheEngine *_vm;
+
+ struct RankType {
+ uint16 _score;
+ char _title[20];
+ };
+
+ static const char *kCopyright;
+ static const char *kVersionNum;
+
+ Common::String _thats;
+ byte _thing2;
+ byte _sworeNum; // number of times you've sworn
+ byte _alcoholLevel; // Your blood alcohol level.
+ bool _boughtOnion; // Have you bought an onion yet?
+
+ byte wordNum(Common::String word);
+ void replace(Common::String oldChars, byte newChar);
+
+ Common::String rank();
+ Common::String totalTime();
+
+ void clearWords();
+ void cheatParse(Common::String codes);
+ void stripPunctuation(Common::String &word);
+ void displayWhat(byte target, bool animate, bool &ambiguous);
+ bool doPronouns();
+ void properNouns();
+ void lookAround();
+ void openDoor();
+ void storeInterrogation(byte interrogation);
+ void examineObject();
+ bool isPersonHere();
+ void exampers();
+ bool isHolding();
+ void openBox(bool isOpening);
+ void examine();
+ void inventory();
+ void swallow();
+ void peopleInRoom();
+ void putProc();
+ void notInOrder();
+ void goToCauldron();
+ bool giveToSpludwick();
+ void cardiffClimbing();
+ void already();
+ void standUp();
+ void getProc(char thing);
+ void giveGeidaTheLute();
+ void playHarp();
+ void winSequence();
+ void wipeText();
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_PARSER_H
diff --git a/engines/avalanche/pingo.cpp b/engines/avalanche/pingo.cpp
new file mode 100644
index 0000000000..433924f594
--- /dev/null
+++ b/engines/avalanche/pingo.cpp
@@ -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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* PINGO Full-screen sub-parts of the game. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/pingo.h"
+
+namespace Avalanche {
+
+Pingo::Pingo(AvalancheEngine *vm) {
+ _vm = vm;
+}
+
+void Pingo::dPlot(int16 x, int16 y, Common::String z) {
+ warning("STUB: Pingo::dPlot()");
+}
+
+void Pingo::bossKey() {
+ warning("STUB: Pingo::bossKey()");
+}
+
+void Pingo::copy02() { // taken from Wobble (below)
+ warning("STUB: Pingo::copy02()");
+}
+
+void Pingo::copy03() { // taken from Wobble (below)
+ warning("STUB: Pingo::copy03()");
+}
+
+void Pingo::copyPage(byte frp, byte top) { // taken from Copy02 (above)
+ warning("STUB: Pingo::copyPage()");
+}
+
+void Pingo::wobble() {
+ warning("STUB: Pingo::wobble()");
+}
+
+void Pingo::zl(int16 x1, int16 y1, int16 x2, int16 y2) {
+ warning("STUB: Pingo::zl()");
+}
+
+void Pingo::zonk() {
+ warning("STUB: Pingo::zonk()");
+}
+
+void Pingo::winningPic() {
+ Common::File f;
+ _vm->fadeOut();
+
+ if (!f.open("finale.avd"))
+ error("AVALANCHE: File not found: finale.avd");
+
+#if 0
+ for (int bit = 0; bit <= 3; bit++) {
+ port[0x3c4] = 2;
+ port[0x3ce] = 4;
+ port[0x3c5] = 1 << bit;
+ port[0x3cf] = bit;
+ blockread(f, mem[0xa000 * 0], 16000);
+ }
+#endif
+
+ f.close();
+
+ warning("STUB: Pingo::winningPic()");
+
+ _vm->fadeIn();
+
+#if 0
+ do {
+ _vm->check();
+ } while (!(keypressed() || (mrelease > 0)));
+ while (keypressed())
+ char r = readkey();
+ major_redraw();
+#endif
+
+ warning("STUB: Pingo::winningPic()");
+}
+
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/pingo.h b/engines/avalanche/pingo.h
new file mode 100644
index 0000000000..72fdb54c2a
--- /dev/null
+++ b/engines/avalanche/pingo.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* PINGO Full-screen sub-parts of the game. */
+
+#ifndef AVALANCHE_PINGO_H
+#define AVALANCHE_PINGO_H
+
+#include "common/str.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Pingo {
+public:
+ Pingo(AvalancheEngine *vm);
+
+ void bossKey();
+ void copy02();
+ void copy03();
+ void copyPage(byte frp, byte top);
+ void wobble();
+ void zonk();
+ void winningPic();
+
+private:
+ AvalancheEngine *_vm;
+
+ void dPlot(int16 x, int16 y, Common::String z);
+ void zl(int16 x1, int16 y1, int16 x2, int16 y2);
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_PINGO_H
diff --git a/engines/avalanche/sequence.cpp b/engines/avalanche/sequence.cpp
new file mode 100644
index 0000000000..3a60c4ec1d
--- /dev/null
+++ b/engines/avalanche/sequence.cpp
@@ -0,0 +1,230 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* SEQUENCE The sequencer. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/sequence.h"
+
+namespace Avalanche {
+
+Sequence::Sequence(AvalancheEngine *vm) {
+ _vm = vm;
+
+ resetVariables();
+}
+
+void Sequence::resetVariables() {
+ _flipToWhere = kRoomNowhere;
+ _flipToPed = 0;
+}
+
+void Sequence::init(byte what) {
+ _seq[0] = what;
+
+ for (int i = 1; i < kSeqLength; i++)
+ _seq[i] = 0;
+}
+
+void Sequence::add(byte what) {
+ for (int16 i = 0; i < kSeqLength; i++) {
+ if (_seq[i] == 0) {
+ _seq[i] = what;
+ return;
+ }
+ }
+}
+
+void Sequence::switchRoom(Room where, byte ped) {
+ add(kNowFlip);
+
+ _flipToWhere = where;
+ _flipToPed = ped;
+}
+
+void Sequence::startTimer() {
+ _vm->_timer->loseTimer(Timer::kReasonSequencer);
+ _vm->_timer->addTimer(7, Timer::kProcSequence, Timer::kReasonSequencer);
+}
+
+void Sequence::startTimerImmobilized() {
+ // They can't move.
+ _vm->_userMovesAvvy = false;
+ // And they're not moving now.
+ _vm->_animation->stopWalking();
+ // Apart from that, it's the same thing.
+ startTimer();
+}
+
+void Sequence::shoveLeft() {
+ for (uint i = 0; i < kSeqLength - 1; i++)
+ _seq[i] = _seq[i + 1];
+ _seq[kSeqLength - 1] = 0;
+}
+
+void Sequence::callSequencer() {
+ byte curSeq = _seq[0];
+
+ switch (curSeq) {
+ case 0:
+ // No more routines.
+ return;
+ break;
+ case kNowFlip:
+ // Flip room.
+ _vm->_userMovesAvvy = true;
+ _vm->flipRoom(_flipToWhere, _flipToPed);
+ shoveLeft();
+ break;
+ }
+
+ if (curSeq <= 176) {
+ // Show a frame.
+ _vm->_background->draw(-1, -1, curSeq - 1);
+ shoveLeft();
+ }
+
+ // Make sure this PROC gets called again.
+ startTimer();
+}
+
+void Sequence::startHallSeq(Room whither, byte ped) {
+ init(1);
+ add(2);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startOutsideSeq(Room whither, byte ped) {
+ init(1);
+ add(2);
+ add(3);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startCardiffSeq(Room whither, byte ped) {
+ init(1);
+ add(5);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startNaughtyDukeSeq() {
+ init(2);
+ startTimer();
+}
+
+void Sequence::startGardenSeq() {
+ init(2);
+ add(1);
+ add(3);
+ startTimer();
+}
+
+void Sequence::startDuckSeq() {
+ init(3);
+ add(2);
+ add(1);
+ add(4);
+ startTimer();
+}
+
+void Sequence::startLustiesSeq3(Room whither, byte ped) {
+ init(4);
+ add(5);
+ add(6);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startMusicRoomSeq2(Room whither, byte ped) {
+ init(5);
+ add(6);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startGeidaLuteSeq() {
+ init(5);
+ // He falls asleep...
+ add(6);
+ // Not really closing, but we're using the same procedure.
+ startTimer();
+}
+
+void Sequence::startMusicRoomSeq() {
+ init(6);
+ add(5);
+ add(7);
+ startTimer();
+}
+
+void Sequence::startWinSeq() {
+ init(7);
+ add(8);
+ add(9);
+ startTimer();
+}
+
+void Sequence::startCupboardSeq() {
+ init(8);
+ add(7);
+ startTimer();
+}
+
+void Sequence::startLustiesSeq2(Room whither, byte ped) {
+ init(8);
+ add(9);
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::startCardiffSeq2() {
+ init(1);
+ if (_vm->_arrowInTheDoor)
+ add(3);
+ else
+ add(2);
+
+ if (_vm->_takenPen)
+ _vm->_background->draw(-1, -1, 3);
+
+ startTimer();
+}
+
+void Sequence::startDummySeq(Room whither, byte ped) {
+ switchRoom(whither, ped);
+ startTimerImmobilized();
+}
+
+void Sequence::synchronize(Common::Serializer &sz) {
+ sz.syncBytes(_seq, kSeqLength);
+ sz.syncAsByte(_flipToWhere);
+ sz.syncAsByte(_flipToPed);
+}
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/sequence.h b/engines/avalanche/sequence.h
new file mode 100644
index 0000000000..d3c1b54963
--- /dev/null
+++ b/engines/avalanche/sequence.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* SEQUENCE The sequencer. */
+
+#ifndef AVALANCHE_SEQUENCE_H
+#define AVALANCHE_SEQUENCE_H
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Sequence {
+private:
+ static const int16 kNowFlip = 177;
+ static const int16 kSeqLength = 10;
+
+ byte _seq[kSeqLength];
+
+ Room _flipToWhere;
+ byte _flipToPed;
+
+ AvalancheEngine *_vm;
+
+ void shoveLeft(); // This is called by Timer when it's time to do another frame. It shifts everything to the left.
+ void init(byte what);
+ void add(byte what);
+ void switchRoom(Room where, byte ped);
+ void startTimer();
+ void startTimerImmobilized();
+
+public:
+ Sequence(AvalancheEngine *vm);
+ void synchronize(Common::Serializer &sz);
+ void resetVariables();
+ void callSequencer();
+
+ void startCupboardSeq();
+ void startMusicRoomSeq();
+ void startMusicRoomSeq2(Room whither, byte ped);
+ void startGardenSeq();
+ void startGeidaLuteSeq();
+ void startWinSeq();
+ void startNaughtyDukeSeq();
+ void startLustiesSeq2(Room whither, byte ped);
+ void startLustiesSeq3(Room whither, byte ped);
+ void startHallSeq(Room whither, byte ped);
+ void startCardiffSeq(Room whither, byte ped);
+ void startOutsideSeq(Room whither, byte ped);
+ void startDuckSeq();
+ void startCardiffSeq2();
+ void startDummySeq(Room whither, byte ped);
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_SEQUENCE_H
diff --git a/engines/avalanche/sound.cpp b/engines/avalanche/sound.cpp
new file mode 100644
index 0000000000..c324df4713
--- /dev/null
+++ b/engines/avalanche/sound.cpp
@@ -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.
+ *
+ */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/sound.h"
+
+#include "audio/audiostream.h"
+#include "common/config-manager.h"
+
+namespace Avalanche {
+
+SoundHandler::SoundHandler(AvalancheEngine *vm) : _vm(vm) {
+ _soundFl = true;
+ _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
+ _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
+ _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, true);
+}
+
+SoundHandler::~SoundHandler() {
+ _vm->_mixer->stopHandle(_speakerHandle);
+}
+
+/**
+ * Stop any sound that might be playing
+ */
+void SoundHandler::stopSound() {
+ _vm->_mixer->stopAll();
+}
+
+/**
+ * Turn digitized sound on and off
+ */
+void SoundHandler::toggleSound() {
+ _soundFl = !_soundFl;
+}
+
+void SoundHandler::syncVolume() {
+ int soundVolume;
+
+ if (ConfMan.getBool("sfx_mute") || ConfMan.getBool("mute"))
+ soundVolume = -1;
+ else
+ soundVolume = MIN(255, ConfMan.getInt("sfx_volume"));
+
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume);
+}
+
+void SoundHandler::playNote(int freq, int length) {
+ // Does the user not want any sound?
+ if (!_soundFl || !_vm->_mixer->isReady())
+ return;
+
+ // Start a note playing (we will stop it when the timer expires).
+ _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, freq, length);
+}
+
+void SoundHandler::click() {
+ _vm->_mixer->stopAll();
+
+ playNote(7177, 1);
+}
+
+void SoundHandler::blip() {
+ _vm->_mixer->stopAll();
+
+ playNote(177, 77);
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/sound.h b/engines/avalanche/sound.h
new file mode 100644
index 0000000000..25b6b267d3
--- /dev/null
+++ b/engines/avalanche/sound.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AVALANCHE_SOUND_H
+#define AVALANCHE_SOUND_H
+
+#include "audio/mixer.h"
+#include "audio/softsynth/pcspk.h"
+
+namespace Avalanche {
+
+class SoundHandler {
+public:
+ bool _soundFl;
+
+ SoundHandler(AvalancheEngine *vm);
+ ~SoundHandler();
+
+ void toggleSound();
+ void playNote(int freq, int length);
+ void click();
+ void blip();
+ void syncVolume();
+ void stopSound();
+
+private:
+ AvalancheEngine *_vm;
+ Audio::PCSpeaker *_speakerStream;
+ Audio::SoundHandle _speakerHandle;
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_SOUND_H
diff --git a/engines/avalanche/timer.cpp b/engines/avalanche/timer.cpp
new file mode 100644
index 0000000000..40f2af529a
--- /dev/null
+++ b/engines/avalanche/timer.cpp
@@ -0,0 +1,693 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: TIMEOUT The scheduling unit. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/timer.h"
+
+namespace Avalanche {
+
+Timer::Timer(AvalancheEngine *vm) {
+ _vm = vm;
+
+ resetVariables();
+}
+
+/**
+ * Add a nex timer
+ * @remarks Originally called 'set_up_timer'
+ */
+void Timer::addTimer(int32 duration, byte action, byte reason) {
+ byte i = 0;
+ while ((i < 7) && (_times[i]._timeLeft != 0)) {
+ if (_times[i]._reason == reason) // We only add a timer if it's not already in the array.
+ return;
+ i++;
+ }
+
+ if (i == 7)
+ return; // Oh dear... No timer left
+
+ // Everything's OK here!
+ _times[i]._timeLeft = duration;
+ _times[i]._action = action;
+ _times[i]._reason = reason;
+}
+
+/**
+ * Update the timers
+ * @remarks Originally called 'one_tick'
+ */
+void Timer::updateTimer() {
+ if (_vm->_menu->isActive())
+ return;
+
+ for (int i = 0; i < 7; i++) {
+ if (_times[i]._timeLeft <= 0)
+ continue;
+
+ _times[i]._timeLeft--;
+
+ if (_times[i]._timeLeft == 0) {
+ switch (_times[i]._action) {
+ case kProcOpenDrawbridge :
+ openDrawbridge();
+ break;
+ case kProcAvariciusTalks :
+ avariciusTalks();
+ break;
+ case kProcUrinate :
+ urinate();
+ break;
+ case kProcToilet :
+ toilet();
+ break;
+ case kProcBang:
+ bang();
+ break;
+ case kProcBang2:
+ bang2();
+ break;
+ case kProcStairs:
+ stairs();
+ break;
+ case kProcCardiffSurvey:
+ cardiffSurvey();
+ break;
+ case kProcCardiffReturn:
+ cardiffReturn();
+ break;
+ case kProcCwytalotInHerts:
+ cwytalotInHerts();
+ break;
+ case kProcGetTiedUp:
+ getTiedUp();
+ break;
+ case kProcGetTiedUp2:
+ getTiedUp2();
+ break;
+ case kProcHangAround:
+ hangAround();
+ break;
+ case kProcHangAround2:
+ hangAround2();
+ break;
+ case kProcAfterTheShootemup:
+ afterTheShootemup();
+ break;
+ case kProcJacquesWakesUp:
+ jacquesWakesUp();
+ break;
+ case kProcNaughtyDuke:
+ naughtyDuke();
+ break;
+ case kProcNaughtyDuke2:
+ naughtyDuke2();
+ break;
+ case kProcNaughtyDuke3:
+ naughtyDuke3();
+ break;
+ case kProcJump:
+ jump();
+ break;
+ case kProcSequence:
+ _vm->_sequence->callSequencer();
+ break;
+ case kProcCrapulusSpludOut:
+ crapulusSaysSpludOut();
+ break;
+ case kProcDawnDelay:
+ _vm->fadeIn();
+ break;
+ case kProcBuyDrinks:
+ buyDrinks();
+ break;
+ case kProcBuyWine:
+ buyWine();
+ break;
+ case kProcCallsGuards:
+ callsGuards();
+ break;
+ case kProcGreetsMonk:
+ greetsMonk();
+ break;
+ case kProcFallDownOubliette:
+ fallDownOubliette();
+ break;
+ case kProcMeetAvaroid:
+ meetAvaroid();
+ break;
+ case kProcRiseUpOubliette:
+ riseUpOubliette();
+ break;
+ case kProcRobinHoodAndGeida:
+ robinHoodAndGeida();
+ break;
+ case kProcRobinHoodAndGeidaTalk:
+ robinHoodAndGeidaTalk();
+ break;
+ case kProcAvalotReturns:
+ avalotReturns();
+ break;
+ case kProcAvvySitDown:
+ avvySitDown();
+ break;
+ case kProcGhostRoomPhew:
+ ghostRoomPhew();
+ break;
+ case kProcArkataShouts:
+ arkataShouts();
+ break;
+ case kProcWinning:
+ winning();
+ break;
+ case kProcAvalotFalls:
+ avalotFalls();
+ break;
+ case kProcSpludwickGoesToCauldron:
+ spludwickGoesToCauldron();
+ break;
+ case kProcSpludwickLeavesCauldron:
+ spludwickLeavesCauldron();
+ break;
+ case kProcGiveLuteToGeida:
+ giveLuteToGeida();
+ break;
+ }
+ }
+ }
+
+ _vm->_roomCycles++; // Cycles since you've been in this room.
+}
+
+void Timer::loseTimer(byte which) {
+ for (int i = 0; i < 7; i++) {
+ if (_times[i]._reason == which)
+ _times[i]._timeLeft = 0; // Cancel this one!
+ }
+
+}
+
+void Timer::openDrawbridge() {
+ _vm->_drawbridgeOpen++;
+ _vm->_background->draw(-1, -1, _vm->_drawbridgeOpen - 2);
+
+ if (_vm->_drawbridgeOpen == 4)
+ _vm->_magics[1]._operation = kMagicNothing; // You may enter the drawbridge.
+ else
+ addTimer(7, kProcOpenDrawbridge, kReasonDrawbridgeFalls);
+}
+
+void Timer::avariciusTalks() {
+ _vm->_dialogs->displayScrollChain('Q', _vm->_avariciusTalk);
+ _vm->_avariciusTalk++;
+
+ if (_vm->_avariciusTalk < 17)
+ addTimer(177, kProcAvariciusTalks, kReasonAvariciusTalks);
+ else
+ _vm->incScore(3);
+}
+
+void Timer::urinate() {
+ _vm->_animation->_sprites[0]->turn(kDirUp);
+ _vm->_animation->stopWalking();
+ _vm->drawDirection();
+ addTimer(14, kProcToilet, kReasonGoToToilet);
+}
+
+void Timer::toilet() {
+ _vm->_dialogs->displayText("That's better!");
+}
+
+void Timer::bang() {
+ Common::String tmpStr = Common::String::format("%c< BANG! >", kControlItalic);
+ _vm->_dialogs->displayText(tmpStr);
+ addTimer(30, kProcBang2, kReasonExplosion);
+}
+
+void Timer::bang2() {
+ _vm->_dialogs->displayText("Hmm... sounds like Spludwick's up to something...");
+}
+
+void Timer::stairs() {
+ _vm->_sound->blip();
+ _vm->_animation->_sprites[0]->walkTo(3);
+ _vm->_background->draw(-1, -1, 1);
+ _vm->_brummieStairs = 2;
+ _vm->_magics[10]._operation = kMagicSpecial;
+ _vm->_magics[10]._data = 2; // Reached the bottom of the stairs.
+ _vm->_magics[3]._operation = kMagicNothing; // Stop them hitting the sides (or the game will hang.)
+}
+
+void Timer::cardiffSurvey() {
+ if (_vm->_cardiffQuestionNum == 0) {
+ _vm->_cardiffQuestionNum++;
+ _vm->_dialogs->displayScrollChain('Q', 27);
+ }
+
+ _vm->_dialogs->displayScrollChain('Z', _vm->_cardiffQuestionNum);
+ _vm->_interrogation = _vm->_cardiffQuestionNum;
+ addTimer(182, kProcCardiffSurvey, kReasonCardiffsurvey);
+}
+
+void Timer::cardiffReturn() {
+ _vm->_dialogs->displayScrollChain('Q', 28);
+ cardiffSurvey(); // Add end of question.
+}
+
+void Timer::cwytalotInHerts() {
+ _vm->_dialogs->displayScrollChain('Q', 29);
+}
+
+void Timer::getTiedUp() {
+ _vm->_dialogs->displayScrollChain('Q', 34); // ...Trouble!
+ _vm->_userMovesAvvy = false;
+ _vm->_beenTiedUp = true;
+ _vm->_animation->stopWalking();
+
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ spr->stopWalk();
+ spr->stopHoming();
+ spr->_callEachStepFl = true;
+ spr->_eachStepProc = Animation::kProcGrabAvvy;
+ addTimer(70, kProcGetTiedUp2, kReasonGettingTiedUp);
+}
+
+void Timer::getTiedUp2() {
+ _vm->_animation->_sprites[0]->walkTo(3);
+ _vm->_animation->_sprites[1]->walkTo(4);
+ _vm->_magics[3]._operation = kMagicNothing; // No effect when you touch the boundaries.
+ _vm->_friarWillTieYouUp = true;
+}
+
+void Timer::hangAround() {
+ _vm->_animation->_sprites[1]->_doCheck = false;
+
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ avvy->init(7, true); // Robin Hood
+ _vm->setRoom(kPeopleRobinHood, kRoomRobins);
+ _vm->_animation->appearPed(0, 1);
+ _vm->_dialogs->displayScrollChain('Q', 39);
+ avvy->walkTo(6);
+ addTimer(55, kProcHangAround2, kReasonHangingAround);
+}
+
+void Timer::hangAround2() {
+ _vm->_dialogs->displayScrollChain('Q', 40);
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ spr->_vanishIfStill = false;
+ spr->walkTo(3);
+ _vm->setRoom(kPeopleFriarTuck, kRoomRobins);
+ _vm->_dialogs->displayScrollChain('Q', 41);
+ _vm->_animation->_sprites[0]->remove();
+ spr->remove(); // Get rid of Robin Hood and Friar Tuck.
+
+ addTimer(1, kProcAfterTheShootemup, kReasonHangingAround);
+ // Immediately call the following proc (when you have a chance).
+
+ _vm->_tiedUp = false;
+
+ // _vm->_enid->backToBootstrap(1); Call the shoot-'em-up. TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then!
+}
+
+void Timer::afterTheShootemup() {
+ // Only placed this here to replace the minigame. TODO: Remove it when the shoot em' up is implemented!
+ _vm->flipRoom(_vm->_room, 1);
+
+ _vm->_animation->_sprites[0]->init(0, true); // Avalot.
+ _vm->_animation->appearPed(0, 1);
+ _vm->_userMovesAvvy = true;
+ _vm->_objects[kObjectCrossbow - 1] = true;
+ _vm->refreshObjectList();
+
+ // Same as the added line above: TODO: Remove it later!!!
+ _vm->_dialogs->displayText(Common::String("P.S.: There should have been the mini-game called \"shoot em' up\", " \
+ "but I haven't implemented it yet: you get the crossbow automatically.") + kControlNewLine + kControlNewLine + "Peter (uruk)");
+
+#if 0
+ byte shootscore, gain;
+
+ shootscore = mem[storage_seg * storage_ofs];
+ gain = (shootscore + 5) / 10; // Rounding up.
+
+ display(string("\6Your score was ") + strf(shootscore) + '.' + "\r\rYou gain (" +
+ strf(shootscore) + " 0xF6 10) = " + strf(gain) + " points.");
+
+ if (gain > 20) {
+ display("But we won't let you have more than 20 points!");
+ points(20);
+ } else
+ points(gain);
+#endif
+
+ warning("STUB: Timer::after_the_shootemup()");
+
+ _vm->_dialogs->displayScrollChain('Q', 70);
+}
+
+void Timer::jacquesWakesUp() {
+ _vm->_jacquesState++;
+
+ switch (_vm->_jacquesState) { // Additional pictures.
+ case 1 :
+ _vm->_background->draw(-1, -1, 0); // Eyes open.
+ _vm->_dialogs->displayScrollChain('Q', 45);
+ break;
+ case 2 : // Going through the door.
+ _vm->_background->draw(-1, -1, 1); // Not on the floor.
+ _vm->_background->draw(-1, -1, 2); // But going through the door.
+ _vm->_magics[5]._operation = kMagicNothing; // You can't wake him up now.
+ break;
+ case 3 : // Gone through the door.
+ _vm->_background->draw(-1, -1, 1); // Not on the floor, either.
+ _vm->_background->draw(-1, -1, 3); // He's gone... so the door's open.
+ _vm->setRoom(kPeopleJacques, kRoomNowhere); // Gone!
+ break;
+ }
+
+ if (_vm->_jacquesState == 5) {
+ _vm->_bellsAreRinging = true;
+ _vm->_aylesIsAwake = true;
+ _vm->incScore(2);
+ }
+
+ switch (_vm->_jacquesState) {
+ case 1:
+ case 2:
+ case 3:
+ addTimer(12, kProcJacquesWakesUp, kReasonJacquesWakingUp);
+ break;
+ case 4:
+ addTimer(24, kProcJacquesWakesUp, kReasonJacquesWakingUp);
+ break;
+ }
+}
+
+void Timer::naughtyDuke() { // This is when the Duke comes in and takes your money.
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ spr->init(9, false); // Here comes the Duke.
+ _vm->_animation->appearPed(1, 0); // He starts at the door...
+ spr->walkTo(2); // He walks over to you.
+
+ // Let's get the door opening.
+ _vm->_background->draw(-1, -1, 0);
+ _vm->_sequence->startNaughtyDukeSeq();
+
+ addTimer(50, kProcNaughtyDuke2, kReasonNaughtyDuke);
+}
+
+void Timer::naughtyDuke2() {
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ _vm->_dialogs->displayScrollChain('Q', 48); // "Ha ha, it worked again!"
+ spr->walkTo(0); // Walk to the door.
+ spr->_vanishIfStill = true; // Then go away!
+
+ addTimer(32, kProcNaughtyDuke3, kReasonNaughtyDuke);
+}
+
+void Timer::naughtyDuke3() {
+ _vm->_background->draw(-1, -1, 0);
+ _vm->_sequence->startNaughtyDukeSeq();
+}
+
+void Timer::jump() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+
+ _vm->_jumpStatus++;
+ switch (_vm->_jumpStatus) {
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ avvy->_y--;
+ break;
+ case 12:
+ case 13:
+ case 14:
+ case 16:
+ case 18:
+ case 19:
+ avvy->_y++;
+ break;
+ }
+
+ if (_vm->_jumpStatus == 20) { // End of jump.
+ _vm->_userMovesAvvy = true;
+ _vm->_jumpStatus = 0;
+ } else // Still jumping.
+ addTimer(1, kProcJump, kReasonJumping);
+
+ if ((_vm->_jumpStatus == 10) // You're at the highest point of your jump.
+ && (_vm->_room == kRoomInsideCardiffCastle)
+ && (_vm->_arrowInTheDoor == true)
+ && (_vm->_animation->inField(2))) { // Beside the wall
+ // Grab the arrow!
+ if (_vm->_carryNum >= kCarryLimit)
+ _vm->_dialogs->displayText("You fail to grab it, because your hands are full.");
+ else {
+ _vm->_background->draw(-1, -1, 1);
+ _vm->_arrowInTheDoor = false; // You've got it.
+ _vm->_objects[kObjectBolt - 1] = true;
+ _vm->refreshObjectList();
+ _vm->_dialogs->displayScrollChain('Q', 50);
+ _vm->incScore(3);
+ }
+ }
+}
+
+void Timer::crapulusSaysSpludOut() {
+ _vm->_dialogs->displayScrollChain('Q', 56);
+ _vm->_crapulusWillTell = false;
+}
+
+void Timer::buyDrinks() {
+ _vm->_background->draw(-1, -1, 10); // Malagauche gets up again.
+ _vm->_malagauche = 0;
+
+ _vm->_dialogs->displayScrollChain('D', _vm->_drinking); // Display message about it.
+ _vm->_pingo->wobble(); // Do the special effects.
+ _vm->_dialogs->displayScrollChain('D', 1); // That'll be thruppence.
+ if (_vm->decreaseMoney(3)) // Pay 3d.
+ _vm->_dialogs->displayScrollChain('D', 3); // Tell 'em you paid up.
+ _vm->_parser->drink();
+}
+
+void Timer::buyWine() {
+ _vm->_background->draw(-1, -1, 10); // Malagauche gets up again.
+ _vm->_malagauche = 0;
+
+ _vm->_dialogs->displayScrollChain('D', 50); // You buy the wine.
+ _vm->_dialogs->displayScrollChain('D', 1); // It'll be thruppence.
+ if (_vm->decreaseMoney(3)) {
+ _vm->_dialogs->displayScrollChain('D', 4); // You paid up.
+ _vm->_objects[kObjectWine - 1] = true;
+ _vm->refreshObjectList();
+ _vm->_wineState = 1; // OK Wine.
+ }
+}
+
+void Timer::callsGuards() {
+ _vm->_dialogs->displayScrollChain('Q', 58); // "GUARDS!!!"
+ _vm->gameOver();
+}
+
+void Timer::greetsMonk() {
+ _vm->_dialogs->displayScrollChain('Q', 59);
+ _vm->_enteredLustiesRoomAsMonk = true;
+}
+
+void Timer::fallDownOubliette() {
+ _vm->_magics[8]._operation = kMagicNothing;
+
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ avvy->_moveY++; // Increments dx/dy!
+ avvy->_y += avvy->_moveY; // Dowwwn we go...
+ addTimer(3, kProcFallDownOubliette, kReasonFallingDownOubliette);
+}
+
+void Timer::meetAvaroid() {
+ if (_vm->_metAvaroid) {
+ Common::String tmpStr = Common::String::format("You can't expect to be %cthat%c lucky twice in a row!",
+ kControlItalic, kControlRoman);
+ _vm->_dialogs->displayText(tmpStr);
+ _vm->gameOver();
+ } else {
+ _vm->_dialogs->displayScrollChain('Q', 60);
+ _vm->_metAvaroid = true;
+ addTimer(1, kProcRiseUpOubliette, kReasonRisingUpOubliette);
+
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ avvy->_facingDir = kDirLeft;
+ avvy->_x = 151;
+ avvy->_moveX = -3;
+ avvy->_moveY = -5;
+
+ _vm->_graphics->setBackgroundColor(kColorGreen);
+ }
+}
+
+void Timer::riseUpOubliette() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ avvy->_visible = true;
+ avvy->_moveY++; // Decrements dx/dy!
+ avvy->_y -= avvy->_moveY; // Uuuupppp we go...
+ if (avvy->_moveY > 0)
+ addTimer(3, kProcRiseUpOubliette, kReasonRisingUpOubliette);
+ else
+ _vm->_userMovesAvvy = true;
+}
+
+void Timer::robinHoodAndGeida() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ avvy->init(7, true);
+ _vm->_animation->appearPed(0, 6);
+ avvy->walkTo(5);
+
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ spr->stopWalk();
+ spr->_facingDir = kDirLeft;
+ addTimer(20, kProcRobinHoodAndGeidaTalk, kReasonRobinHoodAndGeida);
+ _vm->_geidaFollows = false;
+}
+
+void Timer::robinHoodAndGeidaTalk() {
+ _vm->_dialogs->displayScrollChain('Q', 66);
+
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ avvy->walkTo(1);
+ spr->walkTo(1);
+ avvy->_vanishIfStill = true;
+ spr->_vanishIfStill = true;
+
+ addTimer(162, kProcAvalotReturns, kReasonRobinHoodAndGeida);
+}
+
+void Timer::avalotReturns() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ AnimationType *spr = _vm->_animation->_sprites[1];
+ avvy->remove();
+ spr->remove();
+ avvy->init(0, true);
+ _vm->_animation->appearPed(0, 0);
+ _vm->_dialogs->displayScrollChain('Q', 67);
+ _vm->_userMovesAvvy = true;
+}
+
+/**
+ * This is used when you sit down in the pub in Notts. It loops around
+ * so that it will happen when Avvy stops walking.
+ * @remarks Originally called 'avvy_sit_down'
+ */
+void Timer::avvySitDown() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ if (avvy->_homing) // Still walking.
+ addTimer(1, kProcAvvySitDown, kReasonSittingDown);
+ else {
+ _vm->_background->draw(-1, -1, 2);
+ _vm->_sittingInPub = true;
+ _vm->_userMovesAvvy = false;
+ avvy->_visible = false;
+ }
+}
+
+void Timer::ghostRoomPhew() {
+ Common::String tmpStr = Common::String::format("%cPHEW!%c You're glad to get out of %cthere!",
+ kControlItalic, kControlRoman, kControlItalic);
+ _vm->_dialogs->displayText(tmpStr);
+}
+
+void Timer::arkataShouts() {
+ if (_vm->_teetotal)
+ return;
+
+ _vm->_dialogs->displayScrollChain('Q', 76);
+ addTimer(160, kProcArkataShouts, kReasonArkataShouts);
+}
+
+void Timer::winning() {
+ _vm->_dialogs->displayScrollChain('Q', 79);
+ _vm->_pingo->winningPic();
+
+ warning("STUB: Timer::winning()");
+#if 0
+ do {
+ _vm->checkclick();
+ } while (!(_vm->mrelease == 0));
+#endif
+ // TODO: To be implemented with Pingo::winningPic().
+
+ _vm->callVerb(kVerbCodeScore);
+ _vm->_dialogs->displayText(" T H E E N D ");
+ _vm->_letMeOut = true;
+}
+
+void Timer::avalotFalls() {
+ AnimationType *avvy = _vm->_animation->_sprites[0];
+ if (avvy->_stepNum < 5) {
+ avvy->_stepNum++;
+ addTimer(3, kProcAvalotFalls, kReasonFallingOver);
+ } else {
+ Common::String toDisplay = Common::String::format("%c%c%c%c%c%c%c%c%c%c%c%c%cZ%c",
+ kControlNewLine, kControlNewLine, kControlNewLine, kControlNewLine,
+ kControlNewLine, kControlNewLine, kControlInsertSpaces, kControlInsertSpaces,
+ kControlInsertSpaces, kControlInsertSpaces, kControlInsertSpaces,
+ kControlInsertSpaces, kControlRegister, kControlIcon);
+ _vm->_dialogs->displayText(toDisplay);
+ }
+}
+
+void Timer::spludwickGoesToCauldron() {
+ if (_vm->_animation->_sprites[1]->_homing)
+ addTimer(1, kProcSpludwickGoesToCauldron, kReasonSpludwickWalk);
+ else
+ addTimer(17, kProcSpludwickLeavesCauldron, kReasonSpludwickWalk);
+}
+
+void Timer::spludwickLeavesCauldron() {
+ _vm->_animation->_sprites[1]->_callEachStepFl = true; // So that normal procs will continue.
+}
+
+void Timer::giveLuteToGeida() { // Moved here from Acci.
+ _vm->_dialogs->displayScrollChain('Q', 86);
+ _vm->incScore(4);
+ _vm->_lustieIsAsleep = true;
+ _vm->_sequence->startGeidaLuteSeq();
+}
+
+void Timer::resetVariables() {
+ for (int i = 0; i < 7; i++) {
+ _times[i]._timeLeft = 0;
+ _times[i]._action = 0;
+ _times[i]._reason = 0;
+ }
+}
+
+} // End of namespace Avalanche.
diff --git a/engines/avalanche/timer.h b/engines/avalanche/timer.h
new file mode 100644
index 0000000000..9a91c4d24b
--- /dev/null
+++ b/engines/avalanche/timer.h
@@ -0,0 +1,178 @@
+/* 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 the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* Original name: TIMEOUT The scheduling unit. */
+
+#ifndef AVALANCHE_TIMER_H
+#define AVALANCHE_TIMER_H
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Timer {
+public:
+ // Reason runs between 1 and 28.
+ enum Reason {
+ kReasonDrawbridgeFalls = 2,
+ kReasonAvariciusTalks = 3,
+ kReasonGoToToilet = 4,
+ kReasonExplosion = 5,
+ kReasonBrummieStairs = 6,
+ kReasonCardiffsurvey = 7,
+ kReasonCwytalotInHerts = 8,
+ kReasonGettingTiedUp = 9,
+ kReasonHangingAround = 10, // Tied to the tree in Nottingham.
+ kReasonJacquesWakingUp = 11,
+ kReasonNaughtyDuke = 12,
+ kReasonJumping = 13,
+ kReasonSequencer = 14,
+ kReasonCrapulusSaysSpludwickOut = 15,
+ kReasonDawndelay = 16,
+ kReasonDrinks = 17,
+ kReasonDuLustieTalks = 18,
+ kReasonFallingDownOubliette = 19,
+ kReasonMeetingAvaroid = 20,
+ kReasonRisingUpOubliette = 21,
+ kReasonRobinHoodAndGeida = 22,
+ kReasonSittingDown = 23,
+ kReasonGhostRoomPhew = 1,
+ kReasonArkataShouts = 24,
+ kReasonWinning = 25,
+ kReasonFallingOver = 26,
+ kReasonSpludwickWalk = 27,
+ kReasonGeidaSings = 28
+ };
+
+ // Proc runs between 1 and 41.
+ enum Proc {
+ kProcOpenDrawbridge = 3,
+ kProcAvariciusTalks = 4,
+ kProcUrinate = 5,
+ kProcToilet = 6,
+ kProcBang = 7,
+ kProcBang2 = 8,
+ kProcStairs = 9,
+ kProcCardiffSurvey = 10,
+ kProcCardiffReturn = 11,
+ kProcCwytalotInHerts = 12,
+ kProcGetTiedUp = 13,
+ kProcGetTiedUp2 = 1,
+ kProcHangAround = 14,
+ kProcHangAround2 = 15,
+ kProcAfterTheShootemup = 32,
+ kProcJacquesWakesUp = 16,
+ kProcNaughtyDuke = 17,
+ kProcNaughtyDuke2 = 18,
+ kProcNaughtyDuke3 = 38,
+ kProcJump = 19,
+ kProcSequence = 20,
+ kProcCrapulusSpludOut = 21,
+ kProcDawnDelay = 22,
+ kProcBuyDrinks = 23,
+ kProcBuyWine = 24,
+ kProcCallsGuards = 25,
+ kProcGreetsMonk = 26,
+ kProcFallDownOubliette = 27,
+ kProcMeetAvaroid = 28,
+ kProcRiseUpOubliette = 29,
+ kProcRobinHoodAndGeida = 2,
+ kProcRobinHoodAndGeidaTalk = 30,
+ kProcAvalotReturns = 31,
+ kProcAvvySitDown = 33, // In Nottingham.
+ kProcGhostRoomPhew = 34,
+ kProcArkataShouts = 35,
+ kProcWinning = 36,
+ kProcAvalotFalls = 37,
+ kProcSpludwickGoesToCauldron = 39,
+ kProcSpludwickLeavesCauldron = 40,
+ kProcGiveLuteToGeida = 41
+ };
+
+ struct TimerType {
+ int32 _timeLeft;
+ byte _action;
+ byte _reason;
+ };
+
+ TimerType _times[7];
+
+ Timer(AvalancheEngine *vm);
+
+ void resetVariables();
+ void addTimer(int32 duration, byte action, byte reason);
+ void updateTimer();
+ void loseTimer(byte which);
+
+ // Procedures to do things at the end of amounts of time:
+ void openDrawbridge();
+ void avariciusTalks();
+ void urinate();
+ void toilet();
+ void bang();
+ void bang2();
+ void stairs();
+ void cardiffSurvey();
+ void cardiffReturn();
+ void cwytalotInHerts();
+ void getTiedUp();
+ void getTiedUp2();
+ void hangAround();
+ void hangAround2();
+ void afterTheShootemup();
+ void jacquesWakesUp();
+ void naughtyDuke();
+ void naughtyDuke2();
+ void naughtyDuke3();
+ void jump();
+ void crapulusSaysSpludOut();
+ void buyDrinks();
+ void buyWine();
+ void callsGuards();
+ void greetsMonk();
+ void fallDownOubliette();
+ void meetAvaroid();
+ void riseUpOubliette();
+ void robinHoodAndGeida();
+ void robinHoodAndGeidaTalk();
+ void avalotReturns();
+ void avvySitDown();
+ void ghostRoomPhew();
+ void arkataShouts();
+ void winning();
+ void avalotFalls();
+ void spludwickGoesToCauldron();
+ void spludwickLeavesCauldron();
+ void giveLuteToGeida();
+
+private:
+ AvalancheEngine *_vm;
+
+};
+
+} // End of namespace Avalanche.
+
+#endif // AVALANCHE_TIMER_H
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/cge.h b/engines/cge/cge.h
index 0e8c5a05bb..61558c0989 100644
--- a/engines/cge/cge.h
+++ b/engines/cge/cge.h
@@ -80,6 +80,12 @@ class Talk;
#define kSayTheEnd 41
+enum GameType {
+ kGameTypeNone = 0,
+ kGameTypeSoltys,
+ kGameTypeSfinx
+};
+
// our engine debug channels
enum {
kCGEDebugBitmap = 1 << 0,
diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp
index f4f1cd3e0b..5325558f8b 100644
--- a/engines/cge/cge_main.cpp
+++ b/engines/cge/cge_main.cpp
@@ -358,7 +358,7 @@ void CGEEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &he
// Create a thumbnail and save it
Graphics::Surface *thumb = new Graphics::Surface();
Graphics::Surface *s = _vga->_page[0];
- ::createThumbnail(thumb, (const byte *)s->pixels, kScrWidth, kScrHeight, thumbPalette);
+ ::createThumbnail(thumb, (const byte *)s->getPixels(), kScrWidth, kScrHeight, thumbPalette);
Graphics::saveThumbnail(*out, *thumb);
thumb->free();
delete thumb;
@@ -1046,7 +1046,7 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i
for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
len = line.size();
lcnt++;
- strcpy(tmpStr, line.c_str());
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
if (len == 0 || *tmpStr == '.')
continue;
@@ -1132,7 +1132,7 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i
_sprite->_flags._bDel = true;
// Extract the filename, without the extension
- strcpy(_sprite->_file, fname);
+ Common::strlcpy(_sprite->_file, fname, sizeof(_sprite->_file));
char *p = strchr(_sprite->_file, '.');
if (p)
*p = '\0';
@@ -1158,7 +1158,7 @@ void CGEEngine::loadScript(const char *fname) {
char *p;
lcnt++;
- strcpy(tmpStr, line.c_str());
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
if ((line.size() == 0) || (*tmpStr == '.'))
continue;
diff --git a/engines/cge/configure.engine b/engines/cge/configure.engine
new file mode 100644
index 0000000000..72af1197be
--- /dev/null
+++ b/engines/cge/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine cge "CGE" yes
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 289aede99e..c377970c51 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -36,77 +36,116 @@ static const PlainGameDescriptor CGEGames[] = {
namespace CGE {
-static const ADGameDescription gameDescriptions[] = {
+struct CgeGameDescription {
+ ADGameDescription desc;
+ GameType gameType;
+};
+
+static const CgeGameDescription gameDescriptions[] = {
{
- "soltys", "",
{
- {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
- {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437572},
- AD_LISTEND
+ "soltys", "",
+ {
+ {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
+ {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437572},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ kGameTypeSoltys
},
{
- "soltys", "Soltys Freeware",
{
- {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
- {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676},
- AD_LISTEND
+ "soltys", "Soltys Freeware",
+ {
+ {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
+ {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ kGameTypeSoltys
},
{
- "soltys", "Soltys Demo (not supported)",
{
- {"vol.cat", 0, "1e077c8ff58109a187f07ac54b0c873a", 18788},
- {"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710},
- AD_LISTEND
+ "soltys", "Soltys Demo (not supported)",
+ {
+ {"vol.cat", 0, "1e077c8ff58109a187f07ac54b0c873a", 18788},
+ {"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
+ kGameTypeSoltys
},
{
- "soltys", "Soltys Demo (not supported)",
{
- {"vol.cat", 0, "f17987487fab1ebddd781d8d02fedecc", 7168},
- {"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272},
- AD_LISTEND
+ "soltys", "Soltys Demo (not supported)",
+ {
+ {"vol.cat", 0, "f17987487fab1ebddd781d8d02fedecc", 7168},
+ {"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
+ kGameTypeSoltys
},
{
- "soltys", "Soltys Freeware v1.0",
{
- {"vol.cat", 0, "f1675684c68ab90272f5776f8f2c3974", 50176},
- {"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868},
- AD_LISTEND
+ "soltys", "Soltys Freeware v1.0",
+ {
+ {"vol.cat", 0, "f1675684c68ab90272f5776f8f2c3974", 50176},
+ {"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0()
},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0()
+ kGameTypeSoltys
},
{
- "soltys", "Soltys Freeware v1.0",
{
- {"vol.cat", 0, "20fdce799adb618100ef9ee2362be875", 50176},
- {"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339},
- AD_LISTEND
+ "soltys", "Soltys Freeware v1.0",
+ {
+ {"vol.cat", 0, "20fdce799adb618100ef9ee2362be875", 50176},
+ {"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ kGameTypeSoltys
},
{
- // Polish version, provided by Strangerke
- "sfinx", "Sfinx Freeware",
{
- {"vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024},
- {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
- AD_LISTEND
+ "soltys", "Soltys Freeware v1.0",
+ {
+ {"vol.cat", 0, "fcae86b20eaa5cedec17b24fa5e85eb4", 50176},
+ {"vol.dat", 0, "ff10d54acc2c95696c57e05819b6906f", 8450151},
+ AD_LISTEND
+ },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0()
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ kGameTypeSoltys
},
- AD_TABLE_END_MARKER
+ {
+ {
+ // Polish version, provided by Strangerke
+ "sfinx", "Sfinx Freeware",
+ {
+ {"vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024},
+ {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ },
+ kGameTypeSfinx
+ },
+
+ {AD_TABLE_END_MARKER, kGameTypeNone}
};
static const ADFileBasedFallback fileBasedFallback[] = {
- { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
+ { &gameDescriptions[0].desc, { "vol.cat", "vol.dat", 0 } },
{ 0, { 0 } }
};
@@ -114,7 +153,7 @@ static const ADFileBasedFallback fileBasedFallback[] = {
class CGEMetaEngine : public AdvancedMetaEngine {
public:
- CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(ADGameDescription), CGEGames) {
+ CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames) {
_singleid = "soltys";
}
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/cge/text.cpp b/engines/cge/text.cpp
index 27bb0608fd..08ff005e1e 100644
--- a/engines/cge/text.cpp
+++ b/engines/cge/text.cpp
@@ -69,7 +69,7 @@ int16 Text::count() {
for (line = tf.readLine(); !tf.eos(); line = tf.readLine()) {
char *s;
assert(line.size() <= 513);
- strcpy(tmpStr, line.c_str());
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
if ((s = strtok(tmpStr, " =,;/\t\n")) == NULL)
continue;
if (!Common::isDigit(*s))
@@ -101,8 +101,7 @@ void Text::load() {
for (idx = 0, line = tf.readLine(); !tf.eos(); line = tf.readLine()) {
int n = line.size();
char *s;
- assert(n <= 513);
- strcpy(tmpStr, line.c_str());
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
if ((s = strtok(tmpStr, " =,;/\t\n")) == NULL)
continue;
if (!Common::isDigit(*s))
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp
index 56a0754527..4954e638ab 100644
--- a/engines/cge/vga13h.cpp
+++ b/engines/cge/vga13h.cpp
@@ -214,8 +214,7 @@ Sprite *Sprite::expand() {
for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
len = line.size();
- assert(len <= 513);
- strcpy(tmpStr, line.c_str());
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
lcnt++;
if (len == 0 || *tmpStr == '.')
continue;
@@ -826,7 +825,7 @@ void Vga::update() {
}
}
- g_system->copyRectToScreen(Vga::_page[0]->getBasePtr(0, 0), kScrWidth, 0, 0, kScrWidth, kScrHeight);
+ g_system->copyRectToScreen(Vga::_page[0]->getPixels(), kScrWidth, 0, 0, kScrWidth, kScrHeight);
g_system->updateScreen();
}
@@ -845,7 +844,7 @@ void Bitmap::xShow(int16 x, int16 y) {
debugC(4, kCGEDebugBitmap, "Bitmap::xShow(%d, %d)", x, y);
const byte *srcP = (const byte *)_v;
- byte *destEndP = (byte *)_vm->_vga->_page[1]->pixels + (kScrWidth * kScrHeight);
+ byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight);
byte *lookupTable = _m;
// Loop through processing data for each plane. The game originally ran in plane mapped mode, where a
@@ -898,7 +897,7 @@ void Bitmap::show(int16 x, int16 y) {
debugC(5, kCGEDebugBitmap, "Bitmap::show(%d, %d)", x, y);
const byte *srcP = (const byte *)_v;
- byte *destEndP = (byte *)_vm->_vga->_page[1]->pixels + (kScrWidth * kScrHeight);
+ byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight);
// Loop through processing data for each plane. The game originally ran in plane mapped mode, where a
// given plane holds each fourth pixel sequentially. So to handle an entire picture, each plane's data
diff --git a/engines/cine/configure.engine b/engines/cine/configure.engine
new file mode 100644
index 0000000000..2b7e2085fa
--- /dev/null
+++ b/engines/cine/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine cine "Cinematique evo 1" yes
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 176380c14f..2abe32f797 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -380,8 +380,7 @@ RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) :
* Copy constructor
*/
RawScript::RawScript(const RawScript &src) : _size(src._size),
- _data(new byte[_size + 1]), _labels(src._labels) {
-
+ _data(new byte[src._size + 1]), _labels(src._labels) {
assert(_data);
memcpy(_data, src._data, _size + 1);
}
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 10404ae56b..de6f91d8c3 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -281,7 +281,7 @@ void PCSoundDriver::resetChannel(int channel) {
}
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
- : _mixer(mixer) {
+ : _upCb(0), _upRef(0), _mixer(mixer) {
_sampleRate = _mixer->getOutputRate();
_opl = makeAdLibOPL(_sampleRate);
memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
@@ -309,9 +309,7 @@ void AdLibSoundDriver::setupChannel(int channel, const byte *data, int instrumen
volume = 0;
}
volume += volume / 4;
- if (volume > 127) {
- volume = 127;
- }
+
_channelsVolumeTable[channel] = volume;
setupInstrument(data, channel);
}
diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp
index 5db778dfda..2d7075cba1 100644
--- a/engines/composer/composer.cpp
+++ b/engines/composer/composer.cpp
@@ -48,6 +48,15 @@ namespace Composer {
ComposerEngine::ComposerEngine(OSystem *syst, const ComposerGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
_rnd = new Common::RandomSource("composer");
_audioStream = NULL;
+ _currSoundPriority = 0;
+ _currentTime = 0;
+ _lastTime = 0;
+ _needsUpdate = true;
+ _directoriesToStrip = 1;
+ _mouseVisible = true;
+ _mouseEnabled = false;
+ _mouseSpriteId = 0;
+ _lastButton = NULL;
}
ComposerEngine::~ComposerEngine() {
@@ -79,12 +88,6 @@ Common::Error ComposerEngine::run() {
_queuedScripts[i]._scriptId = 0;
}
- _mouseVisible = true;
- _mouseEnabled = false;
- _mouseSpriteId = 0;
- _lastButton = NULL;
-
- _directoriesToStrip = 1;
if (!_bookIni.loadFromFile("book.ini")) {
_directoriesToStrip = 0;
if (!_bookIni.loadFromFile("programs/book.ini")) {
@@ -103,7 +106,6 @@ Common::Error ComposerEngine::run() {
height = atoi(getStringFromConfig("Common", "Height").c_str());
initGraphics(width, height, true);
_screen.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- _needsUpdate = true;
Graphics::Cursor *cursor = Graphics::makeDefaultWinCursor();
CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(),
@@ -113,11 +115,12 @@ Common::Error ComposerEngine::run() {
loadLibrary(0);
- _currentTime = 0;
- _lastTime = 0;
-
uint fps = atoi(getStringFromConfig("Common", "FPS").c_str());
- uint frameTime = 1000 / fps;
+ uint frameTime = 125; // Default to 125ms (1000/8)
+ if (fps != 0)
+ frameTime = 1000 / fps;
+ else
+ warning("FPS in book.ini is zero. Defaulting to 8...");
uint32 lastDrawTime = 0;
while (!shouldQuit()) {
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
index 33a5356b3a..7d8022455a 100644
--- a/engines/composer/composer.h
+++ b/engines/composer/composer.h
@@ -23,7 +23,7 @@
#ifndef COMPOSER_H
#define COMPOSER_H
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/random.h"
#include "common/system.h"
#include "common/debug.h"
@@ -174,7 +174,7 @@ private:
Common::List<Sprite> _sprites;
uint _directoriesToStrip;
- Common::ConfigFile _bookIni;
+ Common::INIFile _bookIni;
Common::String _bookGroup;
Common::List<Library> _libraries;
Common::Array<PendingPageChange> _pendingPageChanges;
diff --git a/engines/composer/configure.engine b/engines/composer/configure.engine
new file mode 100644
index 0000000000..71a79acb5d
--- /dev/null
+++ b/engines/composer/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine composer "Magic Composer" yes
diff --git a/engines/composer/graphics.cpp b/engines/composer/graphics.cpp
index 2b68fac233..caf3ba3a40 100644
--- a/engines/composer/graphics.cpp
+++ b/engines/composer/graphics.cpp
@@ -39,7 +39,7 @@ bool Sprite::contains(const Common::Point &pos) const {
return false;
if (adjustedPos.y < 0 || adjustedPos.y >= _surface.h)
return false;
- byte *pixels = (byte *)_surface.pixels;
+ const byte *pixels = (const byte *)_surface.getPixels();
return (pixels[(_surface.h - adjustedPos.y - 1) * _surface.w + adjustedPos.x] != 0);
}
@@ -541,7 +541,7 @@ void ComposerEngine::redraw() {
for (uint i = 0; i < _dirtyRects.size(); i++) {
const Common::Rect &rect = _dirtyRects[i];
- byte *pixels = (byte *)_screen.pixels + (rect.top * _screen.pitch) + rect.left;
+ byte *pixels = (byte *)_screen.getBasePtr(rect.left, rect.top);
_system->copyRectToScreen(pixels, _screen.pitch, rect.left, rect.top, rect.width(), rect.height());
}
_system->updateScreen();
@@ -794,7 +794,7 @@ bool ComposerEngine::initSprite(Sprite &sprite) {
if (width > 0 && height > 0) {
sprite._surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- decompressBitmap(type, stream, (byte *)sprite._surface.pixels, size, width, height);
+ decompressBitmap(type, stream, (byte *)sprite._surface.getPixels(), size, width, height);
} else {
// there are some sprites (e.g. a -998x-998 one in Gregory's title screen)
// which have an invalid size, but the original engine doesn't notice for
@@ -814,13 +814,13 @@ void ComposerEngine::drawSprite(const Sprite &sprite) {
int y = sprite._pos.y;
// incoming data is BMP-style (bottom-up), so flip it
- byte *pixels = (byte *)_screen.pixels;
+ byte *pixels = (byte *)_screen.getPixels();
for (int j = 0; j < sprite._surface.h; j++) {
if (j + y < 0)
continue;
if (j + y >= _screen.h)
break;
- byte *in = (byte *)sprite._surface.pixels + (sprite._surface.h - j - 1) * sprite._surface.w;
+ const byte *in = (const byte *)sprite._surface.getBasePtr(0, sprite._surface.h - j - 1);
byte *out = pixels + ((j + y) * _screen.w) + x;
for (int i = 0; i < sprite._surface.w; i++)
if ((x + i >= 0) && (x + i < _screen.w) && in[i])
diff --git a/engines/configure.engines b/engines/configure.engines
deleted file mode 100644
index 7325b105ad..0000000000
--- a/engines/configure.engines
+++ /dev/null
@@ -1,54 +0,0 @@
-# This file is included from the main "configure" script
-# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine scumm "SCUMM" yes "scumm_7_8 he" "v0-v6 games"
-add_engine scumm_7_8 "v7 & v8 games" yes
-add_engine he "HE71+ games" yes
-add_engine agi "AGI" yes
-add_engine agos "AGOS" yes "agos2" "AGOS 1 games"
-add_engine agos2 "AGOS 2 games" yes
-add_engine cge "CGE" yes
-add_engine cine "Cinematique evo 1" yes
-add_engine composer "Magic Composer" yes
-add_engine cruise "Cinematique evo 2" yes
-add_engine draci "Dragon History" yes
-add_engine drascula "Drascula: The Vampire Strikes Back" yes
-add_engine dreamweb "Dreamweb" yes
-add_engine gob "Gobli*ns" yes
-add_engine groovie "Groovie" yes "groovie2" "7th Guest"
-add_engine groovie2 "Groovie 2 games" no
-add_engine hopkins "Hopkins FBI" yes "" "" "16bit"
-add_engine hugo "Hugo Trilogy" yes
-add_engine kyra "Kyra" yes "lol eob" "Legend of Kyrandia 1-3"
-add_engine lol "Lands of Lore" yes
-add_engine eob "Eye of the Beholder" yes
-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 cstime "Where in Time is Carmen Sandiego?" no
-add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit"
-add_engine myst "Myst" no "" "" "16bit"
-add_engine neverhood "Neverhood" no
-add_engine parallaction "Parallaction" yes
-add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit"
-add_engine queen "Flight of the Amazon Queen" yes
-add_engine saga "SAGA" yes "ihnm saga2" "ITE"
-add_engine ihnm "IHNM" yes
-add_engine saga2 "SAGA 2 games" no
-add_engine sci "SCI" yes "sci32" "SCI 0-1.1 games"
-add_engine sci32 "SCI32 games" no
-add_engine sky "Beneath a Steel Sky" yes
-add_engine sword1 "Broken Sword" yes
-add_engine sword2 "Broken Sword II" yes
-add_engine sword25 "Broken Sword 2.5" no "" "" "png zlib 16bit"
-add_engine teenagent "Teen Agent" yes
-add_engine testbed "TestBed: the Testing framework" no
-add_engine tinsel "Tinsel" yes
-add_engine toltecs "3 Skulls of the Toltecs" yes
-add_engine toon "Toonstruck" yes
-add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
-add_engine tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit"
-add_engine tsage "TsAGE" yes
-add_engine tucker "Bud Tucker in Double Trouble" yes
-add_engine voyeur "Voyeur" yes
-add_engine wintermute "Wintermute" no "" "" "png zlib vorbis 16bit"
diff --git a/engines/cruise/POTFILES b/engines/cruise/POTFILES
new file mode 100644
index 0000000000..e3b25bdda8
--- /dev/null
+++ b/engines/cruise/POTFILES
@@ -0,0 +1 @@
+engines/cruise/menu.cpp
diff --git a/engines/cruise/configure.engine b/engines/cruise/configure.engine
new file mode 100644
index 0000000000..925da25370
--- /dev/null
+++ b/engines/cruise/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine cruise "Cinematique evo 2" yes
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index 9782df8f09..3e49e77770 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -43,10 +43,6 @@
*/
namespace Cruise {
-enum CruiseGameType {
- GType_CRUISE = 1
-};
-
#define GAME_FRAME_DELAY_1 50
#define GAME_FRAME_DELAY_2 100
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index b632e4ea7a..bce3f184db 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "base/plugins.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -34,21 +32,12 @@ namespace Cruise {
struct CRUISEGameDescription {
ADGameDescription desc;
-
- int gameType;
- uint32 features;
};
const char *CruiseEngine::getGameId() const {
return _gameDescription->desc.gameid;
}
-int CruiseEngine::getGameType() const {
- return _gameDescription->gameType;
-}
-uint32 CruiseEngine::getFeatures() const {
- return _gameDescription->features;
-}
Common::Language CruiseEngine::getLanguage() const {
return _gameDescription->desc.language;
}
@@ -77,8 +66,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -90,8 +77,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -103,8 +88,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -116,8 +99,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -129,8 +110,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -142,8 +121,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -155,8 +132,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{ // Amiga English US GOLD edition.
{
@@ -168,8 +143,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{ // Amiga Italian US GOLD edition.
{
@@ -181,8 +154,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{ // AtariST English KixxXL edition.
{
@@ -194,8 +165,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -207,8 +176,6 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
{
{
@@ -220,10 +187,8 @@ static const CRUISEGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- GType_CRUISE,
- 0,
},
- {AD_TABLE_END_MARKER, 0, 0}
+ {AD_TABLE_END_MARKER}
};
}
diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp
index 31dfe62dee..584367fdfb 100644
--- a/engines/draci/barchive.cpp
+++ b/engines/draci/barchive.cpp
@@ -203,12 +203,12 @@ void BArchive::openArchive(const Common::String &path) {
uint32 fileOffset;
fileOffset = reader.readUint32LE();
- _f.seek(fileOffset); // Seek to next file in archive
+ _f.seek(fileOffset); // Seek to next file in archive
- _files[i]._compLength = _f.readUint16LE(); // Compressed size
+ _files[i]._compLength = _f.readUint16LE(); // Compressed size
// should be the same as uncompressed
- _files[i]._length = _f.readUint16LE(); // Original size
+ _files[i]._length = _f.readUint16LE(); // Original size
_files[i]._offset = fileOffset; // Offset of file from start
@@ -216,9 +216,9 @@ void BArchive::openArchive(const Common::String &path) {
assert(compressionType == 0 &&
"Compression type flag is non-zero (file is compressed)");
- _files[i]._crc = _f.readByte(); // CRC checksum of the file
- _files[i]._data = NULL; // File data will be read in on demand
- _files[i]._stopper = 0; // Dummy value; not used in BAR files, needed in DFW
+ _files[i]._crc = _f.readByte(); // CRC checksum of the file
+ _files[i]._data = NULL; // File data will be read in on demand
+ _files[i]._stopper = 0; // Dummy value; not used in BAR files, needed in DFW
}
// Last footer item should be equal to footerOffset
diff --git a/engines/draci/configure.engine b/engines/draci/configure.engine
new file mode 100644
index 0000000000..09022b06f5
--- /dev/null
+++ b/engines/draci/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine draci "Dragon History" yes
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index 6aa8477887..06730cfba7 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -92,6 +92,32 @@ DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc)
DebugMan.addDebugChannel(kDraciWalkingDebugLevel, "walking", "Walking debug info");
_console = new DraciConsole(this);
+
+ _screen = 0;
+ _mouse = 0;
+ _game = 0;
+ _script = 0;
+ _anims = 0;
+ _sound = 0;
+ _music = 0;
+ _smallFont = 0;
+ _bigFont = 0;
+ _iconsArchive = 0;
+ _objectsArchive = 0;
+ _spritesArchive = 0;
+ _paletteArchive = 0;
+ _roomsArchive = 0;
+ _overlaysArchive = 0;
+ _animationsArchive = 0;
+ _walkingMapsArchive = 0;
+ _itemsArchive = 0;
+ _itemImagesArchive = 0;
+ _initArchive = 0;
+ _stringsArchive = 0;
+ _soundsArchive = 0;
+ _dubbingArchive = 0;
+ _showWalkingMap = 0;
+ _pauseStartTime = 0;
}
bool DraciEngine::hasFeature(EngineFeature f) const {
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index c4108cc0c7..009f1bb3d2 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -52,6 +52,55 @@ enum {
Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
uint i;
+ _dialogueLinesNum = 0;
+ _blockNum = 0;
+
+ for (i = 0; i < kDialogueLines; i++)
+ _dialogueAnims[0] = 0;
+
+ _loopStatus = kStatusOrdinary;
+ _loopSubstatus = kOuterLoop;
+ _shouldQuit = 0;
+ _shouldExitLoop = 0;
+ _isReloaded = 0;
+ _speechTick = 0;
+ _speechDuration = 0;
+ _objUnderCursor = 0;
+ _animUnderCursor = 0;
+ _markedAnimationIndex = 0;
+ _scheduledPalette = 0;
+ _fadePhases = 0;
+ _fadePhase = 0;
+ _fadeTick = 0;
+ _mouseChangeTick = 0;
+ _enableQuickHero = 0;
+ _wantQuickHero = 0;
+ _enableSpeedText = 0;
+ _titleAnim = 0;
+ _inventoryAnim = 0;
+ _walkingMapOverlay = 0;
+ _walkingShortestPathOverlay = 0;
+ _walkingObliquePathOverlay = 0;
+ _currentItem = 0;
+ _itemUnderCursor = 0;
+ _previousItemPosition = 0;
+
+ for (i = 0; i < kInventorySlots; i++)
+ _inventory[i] = 0;
+
+ _newRoom = 0;
+ _newGate = 0;
+ _previousRoom = 0;
+ _pushedNewRoom = 0;
+ _pushedNewGate = 0;
+ _currentDialogue = 0;
+ _dialogueArchive = 0;
+ _dialogueBlocks = 0;
+ _dialogueBegin = 0;
+ _dialogueExit = 0;
+ _currentBlock = 0;
+ _lastBlock = 0;
+
BArchive *initArchive = _vm->_initArchive;
const BAFile *file;
@@ -951,9 +1000,9 @@ void Game::dialogueMenu(int dialogueID) {
debugC(7, kDraciLogicDebugLevel,
"hit: %d, _lines[hit]: %d, lastblock: %d, dialogueLines: %d, dialogueExit: %d",
- hit, _lines[hit], _lastBlock, _dialogueLinesNum, _dialogueExit);
+ hit, (hit >= 0 ? _lines[hit] : -1), _lastBlock, _dialogueLinesNum, _dialogueExit);
- if ((!_dialogueExit) && (hit != -1) && (_lines[hit] != -1)) {
+ if ((!_dialogueExit) && (hit >= 0) && (_lines[hit] != -1)) {
if ((oldLines == 1) && (_dialogueLinesNum == 1) && (_lines[hit] == _lastBlock)) {
break;
}
@@ -1361,7 +1410,7 @@ void Game::enterNewRoom() {
// for the dragon in the persons array
if (_newRoom == _info._mapRoom) {
_persons[kDragonObject]._x = 160;
- _persons[kDragonObject]._y = 0;
+ _persons[kDragonObject]._y = 0;
}
// Set the appropriate loop status before loading the room
diff --git a/engines/draci/screen.cpp b/engines/draci/screen.cpp
index 8c1a0c40f7..e43e367300 100644
--- a/engines/draci/screen.cpp
+++ b/engines/draci/screen.cpp
@@ -110,7 +110,7 @@ void Screen::copyToScreen() {
// If a full update is needed, update the whole screen
if (_surface->needsFullUpdate()) {
- byte *ptr = (byte *)_surface->getBasePtr(0, 0);
+ byte *ptr = (byte *)_surface->getPixels();
_vm->_system->copyRectToScreen(ptr, kScreenWidth,
0, 0, kScreenWidth, kScreenHeight);
@@ -138,7 +138,7 @@ void Screen::copyToScreen() {
* Clears the screen and marks the whole screen dirty.
*/
void Screen::clearScreen() {
- byte *ptr = (byte *)_surface->getBasePtr(0, 0);
+ byte *ptr = (byte *)_surface->getPixels();
_surface->markDirty();
diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp
index 8ff60033ed..504476869e 100644
--- a/engines/draci/script.cpp
+++ b/engines/draci/script.cpp
@@ -41,65 +41,65 @@ namespace Draci {
void Script::setupCommandList() {
/** A table of all the commands the game player uses */
static const GPL2Command gplCommands[] = {
- { 0, 0, "gplend", 0, { }, NULL },
- { 0, 1, "exit", 0, { }, NULL },
- { 1, 1, "goto", 1, { kGPL2Ident }, &Script::c_Goto },
- { 2, 1, "Let", 2, { kGPL2Ident, kGPL2Math }, &Script::c_Let },
- { 3, 1, "if", 2, { kGPL2Math, kGPL2Ident }, &Script::c_If },
- { 4, 1, "Start", 2, { kGPL2Ident, kGPL2Str }, &Script::start },
- { 5, 1, "Load", 2, { kGPL2Ident, kGPL2Str }, &Script::load },
- { 5, 2, "StartPlay", 2, { kGPL2Ident, kGPL2Str }, &Script::startPlay },
- { 5, 3, "JustTalk", 0, { }, &Script::justTalk },
- { 5, 4, "JustStay", 0, { }, &Script::justStay },
- { 6, 1, "Talk", 2, { kGPL2Ident, kGPL2Str }, &Script::talk },
- { 7, 1, "ObjStat", 2, { kGPL2Ident, kGPL2Ident }, &Script::objStat },
- { 7, 2, "ObjStat_On", 2, { kGPL2Ident, kGPL2Ident }, &Script::objStatOn },
- { 8, 1, "IcoStat", 2, { kGPL2Ident, kGPL2Ident }, &Script::icoStat },
- { 9, 1, "Dialogue", 1, { kGPL2Str }, &Script::dialogue },
- { 9, 2, "ExitDialogue", 0, { }, &Script::exitDialogue },
- { 9, 3, "ResetDialogue", 0, { }, &Script::resetDialogue },
- { 9, 4, "ResetDialogueFrom", 0, { }, &Script::resetDialogueFrom },
- { 9, 5, "ResetBlock", 1, { kGPL2Ident }, &Script::resetBlock },
- { 10, 1, "WalkOn", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::walkOn },
- { 10, 2, "StayOn", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::stayOn },
- { 10, 3, "WalkOnPlay", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::walkOnPlay },
- { 11, 1, "LoadPalette", 1, { kGPL2Str }, &Script::loadPalette },
- { 12, 1, "SetPalette", 0, { }, &Script::setPalette },
- { 12, 2, "BlackPalette", 0, { }, &Script::blackPalette },
- { 13, 1, "FadePalette", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, &Script::fadePalette },
- { 13, 2, "FadePalettePlay", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, &Script::fadePalettePlay },
- { 14, 1, "NewRoom", 2, { kGPL2Ident, kGPL2Num }, &Script::newRoom },
- { 15, 1, "ExecInit", 1, { kGPL2Ident }, &Script::execInit },
- { 15, 2, "ExecLook", 1, { kGPL2Ident }, &Script::execLook },
- { 15, 3, "ExecUse", 1, { kGPL2Ident }, &Script::execUse },
- { 18, 1, "LoadMusic", 1, { kGPL2Str }, &Script::loadMusic },
- { 18, 2, "StartMusic", 0, { }, &Script::startMusic },
- { 18, 3, "StopMusic", 0, { }, &Script::stopMusic },
- { 19, 1, "Mark", 0, { }, &Script::mark },
- { 19, 2, "Release", 0, { }, &Script::release },
- { 20, 1, "Play", 0, { }, &Script::play },
- { 21, 1, "LoadMap", 1, { kGPL2Str }, &Script::loadMap },
- { 21, 2, "RoomMap", 0, { }, &Script::roomMap },
- { 22, 1, "DisableQuickHero", 0, { }, &Script::disableQuickHero },
- { 22, 2, "EnableQuickHero", 0, { }, &Script::enableQuickHero },
- { 23, 1, "DisableSpeedText", 0, { }, &Script::disableSpeedText },
- { 23, 2, "EnableSpeedText", 0, { }, &Script::enableSpeedText },
- { 24, 1, "QuitGame", 0, { }, &Script::quitGame },
- { 25, 1, "PushNewRoom", 0, { }, &Script::pushNewRoom },
- { 25, 2, "PopNewRoom", 0, { }, &Script::popNewRoom },
+ { 0, 0, "gplend", 0, { }, NULL },
+ { 0, 1, "exit", 0, { }, NULL },
+ { 1, 1, "goto", 1, { kGPL2Ident }, &Script::c_Goto },
+ { 2, 1, "Let", 2, { kGPL2Ident, kGPL2Math }, &Script::c_Let },
+ { 3, 1, "if", 2, { kGPL2Math, kGPL2Ident }, &Script::c_If },
+ { 4, 1, "Start", 2, { kGPL2Ident, kGPL2Str }, &Script::start },
+ { 5, 1, "Load", 2, { kGPL2Ident, kGPL2Str }, &Script::load },
+ { 5, 2, "StartPlay", 2, { kGPL2Ident, kGPL2Str }, &Script::startPlay },
+ { 5, 3, "JustTalk", 0, { }, &Script::justTalk },
+ { 5, 4, "JustStay", 0, { }, &Script::justStay },
+ { 6, 1, "Talk", 2, { kGPL2Ident, kGPL2Str }, &Script::talk },
+ { 7, 1, "ObjStat", 2, { kGPL2Ident, kGPL2Ident }, &Script::objStat },
+ { 7, 2, "ObjStat_On", 2, { kGPL2Ident, kGPL2Ident }, &Script::objStatOn },
+ { 8, 1, "IcoStat", 2, { kGPL2Ident, kGPL2Ident }, &Script::icoStat },
+ { 9, 1, "Dialogue", 1, { kGPL2Str }, &Script::dialogue },
+ { 9, 2, "ExitDialogue", 0, { }, &Script::exitDialogue },
+ { 9, 3, "ResetDialogue", 0, { }, &Script::resetDialogue },
+ { 9, 4, "ResetDialogueFrom", 0, { }, &Script::resetDialogueFrom },
+ { 9, 5, "ResetBlock", 1, { kGPL2Ident }, &Script::resetBlock },
+ { 10, 1, "WalkOn", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::walkOn },
+ { 10, 2, "StayOn", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::stayOn },
+ { 10, 3, "WalkOnPlay", 3, { kGPL2Num, kGPL2Num, kGPL2Ident }, &Script::walkOnPlay },
+ { 11, 1, "LoadPalette", 1, { kGPL2Str }, &Script::loadPalette },
+ { 12, 1, "SetPalette", 0, { }, &Script::setPalette },
+ { 12, 2, "BlackPalette", 0, { }, &Script::blackPalette },
+ { 13, 1, "FadePalette", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, &Script::fadePalette },
+ { 13, 2, "FadePalettePlay", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, &Script::fadePalettePlay },
+ { 14, 1, "NewRoom", 2, { kGPL2Ident, kGPL2Num }, &Script::newRoom },
+ { 15, 1, "ExecInit", 1, { kGPL2Ident }, &Script::execInit },
+ { 15, 2, "ExecLook", 1, { kGPL2Ident }, &Script::execLook },
+ { 15, 3, "ExecUse", 1, { kGPL2Ident }, &Script::execUse },
+ { 18, 1, "LoadMusic", 1, { kGPL2Str }, &Script::loadMusic },
+ { 18, 2, "StartMusic", 0, { }, &Script::startMusic },
+ { 18, 3, "StopMusic", 0, { }, &Script::stopMusic },
+ { 19, 1, "Mark", 0, { }, &Script::mark },
+ { 19, 2, "Release", 0, { }, &Script::release },
+ { 20, 1, "Play", 0, { }, &Script::play },
+ { 21, 1, "LoadMap", 1, { kGPL2Str }, &Script::loadMap },
+ { 21, 2, "RoomMap", 0, { }, &Script::roomMap },
+ { 22, 1, "DisableQuickHero", 0, { }, &Script::disableQuickHero },
+ { 22, 2, "EnableQuickHero", 0, { }, &Script::enableQuickHero },
+ { 23, 1, "DisableSpeedText", 0, { }, &Script::disableSpeedText },
+ { 23, 2, "EnableSpeedText", 0, { }, &Script::enableSpeedText },
+ { 24, 1, "QuitGame", 0, { }, &Script::quitGame },
+ { 25, 1, "PushNewRoom", 0, { }, &Script::pushNewRoom },
+ { 25, 2, "PopNewRoom", 0, { }, &Script::popNewRoom },
// The following commands are not used in the original game files.
- { 16, 1, "RepaintInventory", 0, { }, NULL },
- { 16, 2, "ExitInventory", 0, { }, NULL },
- { 17, 1, "ExitMap", 0, { }, NULL },
- { 18, 4, "FadeOutMusic", 1, { kGPL2Num }, NULL },
- { 18, 5, "FadeInMusic", 1, { kGPL2Num }, NULL },
+ { 16, 1, "RepaintInventory", 0, { }, NULL },
+ { 16, 2, "ExitInventory", 0, { }, NULL },
+ { 17, 1, "ExitMap", 0, { }, NULL },
+ { 18, 4, "FadeOutMusic", 1, { kGPL2Num }, NULL },
+ { 18, 5, "FadeInMusic", 1, { kGPL2Num }, NULL },
// The following commands are not even defined in the game
// sources, but their numbers are allocated for internal
// purposes of the old player.
- { 26, 1, "ShowCheat", 0, { }, NULL },
- { 26, 2, "HideCheat", 0, { }, NULL },
- { 26, 3, "ClearCheat", 1, { kGPL2Num }, NULL },
- { 27, 1, "FeedPassword", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, NULL }
+ { 26, 1, "ShowCheat", 0, { }, NULL },
+ { 26, 2, "HideCheat", 0, { }, NULL },
+ { 26, 3, "ClearCheat", 1, { kGPL2Num }, NULL },
+ { 27, 1, "FeedPassword", 3, { kGPL2Num, kGPL2Num, kGPL2Num }, NULL }
};
/** Operators used by the mathematical evaluator */
diff --git a/engines/draci/sprite.cpp b/engines/draci/sprite.cpp
index 965cdabf3e..9a78904d25 100644
--- a/engines/draci/sprite.cpp
+++ b/engines/draci/sprite.cpp
@@ -38,9 +38,9 @@ const Displacement kNoDisplacement = { 0, 0, 1.0, 1.0 };
* height height of the image in the buffer
*/
static void transformToRows(byte *img, uint16 width, uint16 height) {
- byte *buf = new byte[width * height];
+ byte *buf = new byte[(uint)(width * height)];
byte *tmp = buf;
- memcpy(buf, img, width * height);
+ memcpy(buf, img, (uint)(width * height));
for (uint16 i = 0; i < width; ++i) {
for (uint16 j = 0; j < height; ++j) {
diff --git a/engines/draci/surface.cpp b/engines/draci/surface.cpp
index 8380f8777b..4156398070 100644
--- a/engines/draci/surface.cpp
+++ b/engines/draci/surface.cpp
@@ -80,9 +80,9 @@ void Surface::markClean() {
* @brief Fills the surface with the specified color
*/
void Surface::fill(uint color) {
- byte *ptr = (byte *)getBasePtr(0, 0);
+ byte *ptr = (byte *)getPixels();
- memset(ptr, color, w * h);
+ memset(ptr, color, (uint)(w * h));
}
/**
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index f1ae769d80..195b968860 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -556,9 +556,15 @@ bool WalkingState::alignHeroToEdge(const Common::Point &p1, const Common::Point
}
bool reachedEnd;
if (movement == kMoveLeft || movement == kMoveRight) {
+ if (p2Diff.x == 0) {
+ error("Wrong value for horizontal movement");
+ }
reachedEnd = movement == kMoveLeft ? hero->x <= p2.x : hero->x >= p2.x;
hero->y += hero->x * p2Diff.y / p2Diff.x - prevHero.x * p2Diff.y / p2Diff.x;
} else {
+ if (p2Diff.y == 0) {
+ error("Wrong value for vertical movement");
+ }
reachedEnd = movement == kMoveUp ? hero->y <= p2.y : hero->y >= p2.y;
hero->x += hero->y * p2Diff.x / p2Diff.y - prevHero.y * p2Diff.x / p2Diff.y;
}
diff --git a/engines/draci/walking.h b/engines/draci/walking.h
index a43aeb272a..7e4a3184f5 100644
--- a/engines/draci/walking.h
+++ b/engines/draci/walking.h
@@ -103,7 +103,17 @@ struct GPL2Program;
class WalkingState {
public:
- explicit WalkingState(DraciEngine *vm) : _vm(vm) { stopWalking(); }
+ explicit WalkingState(DraciEngine *vm) : _vm(vm) {
+ _dir = kDirectionLast;
+ _startingDirection = kMoveUndefined;
+ _segment = 0;
+ _lastAnimPhase = 0;
+ _turningFinished = 0;
+ _callbackOffset = 0;
+
+ stopWalking();
+ }
+
~WalkingState() {}
void stopWalking();
diff --git a/engines/drascula/POTFILES b/engines/drascula/POTFILES
new file mode 100644
index 0000000000..ea79f9e066
--- /dev/null
+++ b/engines/drascula/POTFILES
@@ -0,0 +1,2 @@
+engines/drascula/detection.cpp
+engines/drascula/saveload.cpp
diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp
index 9d5d6550fa..e0983809fa 100644
--- a/engines/drascula/actors.cpp
+++ b/engines/drascula/actors.cpp
@@ -135,7 +135,7 @@ void DrasculaEngine::startWalking() {
else
characterMoved = 0;
}
- startTime = getTime();
+ _startTime = getTime();
}
void DrasculaEngine::moveCharacters() {
@@ -239,7 +239,7 @@ void DrasculaEngine::moveCharacters() {
factor_red[curY + curHeight], frontSurface, screenSurface);
}
} else if (characterMoved == 1) {
- curPos[0] = _frameX[num_frame];
+ curPos[0] = _frameX[_characterFrame];
curPos[1] = frame_y + DIF_MASK_HARE;
curPos[2] = curX;
curPos[3] = curY;
@@ -369,13 +369,11 @@ void DrasculaEngine::quadrant_4() {
}
void DrasculaEngine::increaseFrameNum() {
- timeDiff = getTime() - startTime;
-
- if (timeDiff >= 6) {
- startTime = getTime();
- num_frame++;
- if (num_frame == 6)
- num_frame = 0;
+ if (getTime() - _startTime >= 6) {
+ _startTime = getTime();
+ _characterFrame++;
+ if (_characterFrame == 6)
+ _characterFrame = 0;
if (curDirection == kDirectionUp) {
curX -= stepX;
diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp
index 52cab6cd32..ee981c36da 100644
--- a/engines/drascula/animation.cpp
+++ b/engines/drascula/animation.cpp
@@ -426,7 +426,7 @@ void DrasculaEngine::animation_2_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit())
break;
- roomNumber = 16;
+ _roomNumber = 16;
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit())
break;
@@ -512,7 +512,7 @@ void DrasculaEngine::animation_2_1() {
// room number to -1 for the same purpose
// Also check animation_9_6(), where the same hack was used by
// the original
- roomNumber = -1;
+ _roomNumber = -1;
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit())
break;
pause(8);
@@ -734,7 +734,7 @@ void DrasculaEngine::animation_14_2() {
void DrasculaEngine::asco() {
loadPic(roomDisk, drawSurface3);
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
black();
updateRoom();
updateScreen();
@@ -1645,10 +1645,10 @@ void DrasculaEngine::animation_9_6() {
int v_cd;
- animate("fin.bin", 14);
+ (void)animate("fin.bin", 14);
playMusic(13);
flags[5] = 1;
- animate("drf.bin", 16);
+ (void)animate("drf.bin", 16);
fadeToBlack(0);
clearRoom();
curX = -1;
@@ -1661,7 +1661,7 @@ void DrasculaEngine::animation_9_6() {
// We set the room number to -1 for the same purpose.
// Also check animation_2_1(), where the same hack was used
// by the original
- roomNumber = -2;
+ _roomNumber = -2;
loadPic("nota2.alg", bgSurface, HALF_PAL);
black();
trackProtagonist = 1;
@@ -2176,9 +2176,9 @@ void DrasculaEngine::animation_5_4(){
void DrasculaEngine::animation_6_4() {
debug(4, "animation_6_4()");
- int prevRoom = roomNumber;
+ int prevRoom = _roomNumber;
- roomNumber = 26;
+ _roomNumber = 26;
clearRoom();
loadPic(26, bgSurface, HALF_PAL);
loadPic("aux26.alg", drawSurface3);
@@ -2191,11 +2191,11 @@ void DrasculaEngine::animation_6_4() {
updateScreen();
pause(40);
talk_igor(26, kIgorFront);
- roomNumber = prevRoom;
+ _roomNumber = prevRoom;
clearRoom();
loadPic(96, frontSurface);
loadPic(roomDisk, drawSurface3);
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
selectVerb(kVerbNone);
updateRoom();
}
@@ -2224,7 +2224,7 @@ void DrasculaEngine::activatePendulum() {
flags[1] = 2;
hare_se_ve = 0;
- roomNumber = 102;
+ _roomNumber = 102;
loadPic(102, bgSurface, HALF_PAL);
loadPic("an_p1.alg", drawSurface3);
loadPic("an_p2.alg", extraSurface);
diff --git a/engines/drascula/configure.engine b/engines/drascula/configure.engine
new file mode 100644
index 0000000000..b9b76638fd
--- /dev/null
+++ b/engines/drascula/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine drascula "Drascula: The Vampire Strikes Back" yes
diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp
index 426b2ade67..c0d2748ec3 100644
--- a/engines/drascula/console.cpp
+++ b/engines/drascula/console.cpp
@@ -41,7 +41,7 @@ bool Console::Cmd_Room(int argc, const char **argv) {
int roomNum = atoi(argv[1]);
- _vm->loadedDifferentChapter = 0;
+ _vm->_loadedDifferentChapter = false;
_vm->enterRoom(roomNum);
_vm->selectVerb(kVerbNone);
_vm->clearRoom();
diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp
index d045d683fc..b3749445ec 100644
--- a/engines/drascula/converse.cpp
+++ b/engines/drascula/converse.cpp
@@ -168,19 +168,19 @@ void DrasculaEngine::converse(int index) {
// delete stream;
if (currentChapter == 2 && !strcmp(fileName, "op_5.cal") && flags[38] == 1 && flags[33] == 1) {
- strcpy(phrase3, _text[405]);
+ Common::strlcpy(phrase3, _text[405], 128);
strcpy(sound3, "405.als");
answer3 = 31;
}
if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[7] == 1) {
- strcpy(phrase3, _text[273]);
+ Common::strlcpy(phrase3, _text[273], 128);
strcpy(sound3, "273.als");
answer3 = 14;
}
if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[10] == 1) {
- strcpy(phrase3, _text[274]);
+ Common::strlcpy(phrase3, _text[274], 128);
strcpy(sound3, "274.als");
answer3 = 15;
}
@@ -216,7 +216,7 @@ void DrasculaEngine::converse(int index) {
phrase3_bottom = phrase2_bottom + 8 * print_abc_opc(phrase3, phrase2_bottom + 2, game3);
phrase4_bottom = phrase3_bottom + 8 * print_abc_opc(phrase4, phrase3_bottom + 2, kDialogOptionUnselected);
- if (mouseY > 0 && mouseY < phrase1_bottom) {
+ if (_mouseY > 0 && _mouseY < phrase1_bottom) {
if (game1 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
else if (game1 != kDialogOptionClicked && _color != kColorLightGreen)
@@ -224,13 +224,13 @@ void DrasculaEngine::converse(int index) {
print_abc_opc(phrase1, 2, kDialogOptionSelected);
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
delay(100);
game1 = kDialogOptionClicked;
talk(phrase1, sound1);
response(answer1);
}
- } else if (mouseY > phrase1_bottom && mouseY < phrase2_bottom) {
+ } else if (_mouseY > phrase1_bottom && _mouseY < phrase2_bottom) {
if (game2 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
else if (game2 != kDialogOptionClicked && _color != kColorLightGreen)
@@ -238,13 +238,13 @@ void DrasculaEngine::converse(int index) {
print_abc_opc(phrase2, phrase1_bottom + 2, kDialogOptionSelected);
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
delay(100);
game2 = kDialogOptionClicked;
talk(phrase2, sound2);
response(answer2);
}
- } else if (mouseY > phrase2_bottom && mouseY < phrase3_bottom) {
+ } else if (_mouseY > phrase2_bottom && _mouseY < phrase3_bottom) {
if (game3 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
else if (game3 != kDialogOptionClicked && _color != kColorLightGreen)
@@ -252,16 +252,16 @@ void DrasculaEngine::converse(int index) {
print_abc_opc(phrase3, phrase2_bottom + 2, kDialogOptionSelected);
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
delay(100);
game3 = kDialogOptionClicked;
talk(phrase3, sound3);
response(answer3);
}
- } else if (mouseY > phrase3_bottom && mouseY < phrase4_bottom) {
+ } else if (_mouseY > phrase3_bottom && _mouseY < phrase4_bottom) {
print_abc_opc(phrase4, phrase3_bottom + 2, kDialogOptionSelected);
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
delay(100);
talk(phrase4, sound4);
breakOut = 1;
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 8764b82a04..1917bc879d 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -68,33 +68,57 @@ static const PlainGameDescriptor drasculaGames[] = {
namespace Drascula {
static const DrasculaGameDescription gameDescriptions[] = {
+
+ //// Packed versions //////////////////////////////////////////////////////
+
{
- // Drascula English version
+ // Drascula English version (original packed files)
{
"drascula",
0,
- AD_ENTRY1s("14.ald", "09b2735953edcd43af115c65ae00b10e", 1595),
+ {
+ {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
+ // HACK: List packet.001 twice to ensure this detector entry
+ // is ranked just as high as the others (which each have two
+ // detection files).
+ {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
+ {NULL, 0, NULL, 0}
+ },
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
+ GF_PACKED,
GUIO0()
},
},
{
- // Drascula English version (original packed files)
+ // Drascula French version (original packed files)
{
"drascula",
0,
{
{"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- // HACK: List packet.001 twice to ensure this detector entry
- // is ranked just as high as the others (which each have two
- // detection files).
+ {"packet.002", 1, "4401123400f22f212b89f15fb4b43013", 721122},
+ {NULL, 0, NULL, 0}
+ },
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ GF_PACKED,
+ GUIO0()
+ },
+ },
+
+ {
+ // Drascula French version (ScummVM repacked files)
+ {
+ "drascula",
+ 0,
+ {
{"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
+ {"packet.002", 1, "7b83cedb9bb326ed5143e5c459508d43", 722383},
{NULL, 0, NULL, 0}
},
- Common::EN_ANY,
+ Common::FR_FRA,
Common::kPlatformDOS,
GF_PACKED,
GUIO0()
@@ -119,16 +143,29 @@ static const DrasculaGameDescription gameDescriptions[] = {
},
{
- // Drascula French version (original packed files)
+ // Drascula Italian version (original packed version)
+ {
+ "drascula",
+ 0,
+ AD_ENTRY1s("packet.001", "0253e924af223f5fe52537023385159b", 32564209),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ GF_PACKED,
+ GUIO0()
+ },
+ },
+
+ {
+ // Drascula Italian version (ScummVM repacked files)
{
"drascula",
0,
{
{"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- {"packet.002", 1, "4401123400f22f212b89f15fb4b43013", 721122},
+ {"packet.005", 1, "58caac54b891f5d7f335e710e45e5d29", 16209623},
{NULL, 0, NULL, 0}
},
- Common::FR_FRA,
+ Common::IT_ITA,
Common::kPlatformDOS,
GF_PACKED,
GUIO0()
@@ -149,25 +186,31 @@ static const DrasculaGameDescription gameDescriptions[] = {
},
{
- // Drascula Spanish version
+ // Drascula Spanish version (ScummVM repacked files)
{
"drascula",
0,
- AD_ENTRY1s("14.ald", "0746ed1a5cc8d9728f790c29813f4b43", 23059),
+ {
+ {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
+ {"packet.004", 1, "a289d3cf80d50f25ec569b653248437e", 17205838},
+ {NULL, 0, NULL, 0}
+ },
Common::ES_ESP,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
+ GF_PACKED,
GUIO0()
},
},
+ //// Unpacked versions ////////////////////////////////////////////////////
+
{
- // Drascula German version
+ // Drascula English version
{
"drascula",
0,
- AD_ENTRY1s("14.ald", "72e46089033d56bad1c179ac36e2a9d2", 610),
- Common::DE_DEU,
+ AD_ENTRY1s("14.ald", "09b2735953edcd43af115c65ae00b10e", 1595),
+ Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO0()
@@ -188,24 +231,25 @@ static const DrasculaGameDescription gameDescriptions[] = {
},
{
- // Drascula Italian version (original packed version)
+ // Drascula French version (updated - bug #3612236)
{
"drascula",
0,
- AD_ENTRY1s("packet.001", "0253e924af223f5fe52537023385159b", 32564209),
- Common::IT_ITA,
+ AD_ENTRY1s("14.ald", "1f9fbded768bee061cc22bc5bdeab540", 611),
+ Common::FR_FRA,
Common::kPlatformDOS,
- GF_PACKED,
+ ADGF_NO_FLAGS,
GUIO0()
},
},
+
{
- // Drascula Italian version
+ // Drascula German version
{
"drascula",
0,
- AD_ENTRY1s("14.ald", "02b49a18328d0bf2efe6ba658c9c7a1d", 2098),
- Common::IT_ITA,
+ AD_ENTRY1s("14.ald", "72e46089033d56bad1c179ac36e2a9d2", 610),
+ Common::DE_DEU,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO0()
@@ -213,52 +257,40 @@ static const DrasculaGameDescription gameDescriptions[] = {
},
{
- // Drascula Spanish version (ScummVM repacked files)
+ // Drascula Italian version
{
"drascula",
0,
- {
- {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- {"packet.004", 1, "a289d3cf80d50f25ec569b653248437e", 17205838},
- {NULL, 0, NULL, 0}
- },
- Common::ES_ESP,
+ AD_ENTRY1s("14.ald", "02b49a18328d0bf2efe6ba658c9c7a1d", 2098),
+ Common::IT_ITA,
Common::kPlatformDOS,
- GF_PACKED,
+ ADGF_NO_FLAGS,
GUIO0()
},
},
{
- // Drascula Italian version (ScummVM repacked files)
+ // Drascula Italian version (updated - bug #3612236)
{
"drascula",
0,
- {
- {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- {"packet.005", 1, "58caac54b891f5d7f335e710e45e5d29", 16209623},
- {NULL, 0, NULL, 0}
- },
+ AD_ENTRY1s("14.ald", "ccaee939bb3b344c048f28f9205710d1", 2925),
Common::IT_ITA,
Common::kPlatformDOS,
- GF_PACKED,
+ ADGF_NO_FLAGS,
GUIO0()
},
},
{
- // Drascula French version (ScummVM repacked files)
+ // Drascula Spanish version
{
"drascula",
0,
- {
- {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- {"packet.002", 1, "7b83cedb9bb326ed5143e5c459508d43", 722383},
- {NULL, 0, NULL, 0}
- },
- Common::FR_FRA,
+ AD_ENTRY1s("14.ald", "0746ed1a5cc8d9728f790c29813f4b43", 23059),
+ Common::ES_ESP,
Common::kPlatformDOS,
- GF_PACKED,
+ ADGF_NO_FLAGS,
GUIO0()
},
},
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 804881cf9a..163f0077fc 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -89,14 +89,107 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
_talkSequences = 0;
_currentSaveSlot = 0;
+ bjX = 0;
+ bjY = 0;
+ trackBJ = 0;
+ framesWithoutAction = 0;
+ term_int = 0;
+ currentChapter = 0;
+ _loadedDifferentChapter = 0;
+ musicStopped = 0;
+ FrameSSN = 0;
+ globalSpeed = 0;
+ LastFrame = 0;
+ flag_tv = 0;
+ _charMapSize = 0;
+ _itemLocationsSize = 0;
+ _polXSize = 0;
+ _verbBarXSize = 0;
+ _x1dMenuSize = 0;
+ _frameXSize = 0;
+ _candleXSize = 0;
+ _pianistXSize = 0;
+ _drunkXSize = 0;
+ _roomPreUpdatesSize = 0;
+ _roomUpdatesSize = 0;
+ _roomActionsSize = 0;
+ _talkSequencesSize = 0;
+ _numLangs = 0;
+ feetHeight = 0;
+ floorX1 = 0;
+ floorY1 = 0;
+ floorX2 = 0;
+ floorY2 = 0;
+ lowerLimit = 0;
+ upperLimit = 0;
+ trackFinal = 0;
+ walkToObject = 0;
+ objExit = 0;
+ _startTime = 0;
+ hasAnswer = 0;
+ savedTime = 0;
+ breakOut = 0;
+ vonBraunX = 0;
+ trackVonBraun = 0;
+ vonBraunHasMoved = 0;
+ newHeight = 0;
+ newWidth = 0;
+ color_solo = 0;
+ igorX = 0;
+ igorY = 0;
+ trackIgor = 0;
+ drasculaX = 0;
+ drasculaY = 0;
+ trackDrascula = 0;
+ _roomNumber = 0;
+ numRoomObjs = 0;
+ takeObject = 0;
+ pickedObject = 0;
+ _subtitlesDisabled = 0;
+ _menuBar = 0;
+ _menuScreen = 0;
+ _hasName = 0;
+ curExcuseLook = 0;
+ curExcuseAction = 0;
+ frame_y = 0;
+ curX = 0;
+ curY = 0;
+ characterMoved = 0;
+ curDirection = 0;
+ trackProtagonist = 0;
+ _characterFrame = 0;
+ hare_se_ve = 0;
+ roomX = 0;
+ roomY = 0;
+ checkFlags = 0;
+ doBreak = 0;
+ stepX = 0;
+ stepY = 0;
+ curHeight = 0;
+ curWidth = 0;
+
_color = 0;
blinking = 0;
- mouseX = 0;
- mouseY = 0;
- leftMouseButton = 0;
- rightMouseButton = 0;
+ _mouseX = 0;
+ _mouseY = 0;
+ _leftMouseButton = 0;
+ _rightMouseButton = 0;
*textName = 0;
+ crosshairCursor = 0;
+ mouseCursor = 0;
+ bgSurface = 0;
+ backSurface = 0;
+ cursorSurface = 0;
+ drawSurface3 = 0;
+ drawSurface2 = 0;
+ tableSurface = 0;
+ extraSurface = 0;
+ screenSurface = 0;
+ frontSurface = 0;
+ previousMusic = 0;
+ roomMusic = 0;
+
_rnd = new Common::RandomSource("drascula");
_console = 0;
@@ -197,7 +290,7 @@ Common::Error DrasculaEngine::run() {
syncSoundSettings();
currentChapter = 1; // values from 1 to 6 will start each part of game
- loadedDifferentChapter = 0;
+ _loadedDifferentChapter = false;
setTotalPlayTime(0);
// Check if a save is loaded from the launcher
@@ -218,7 +311,7 @@ Common::Error DrasculaEngine::run() {
curX = -1;
characterMoved = 0;
trackProtagonist = 3;
- num_frame = 0;
+ _characterFrame = 0;
hare_se_ve = 1;
checkFlags = 1;
doBreak = 0;
@@ -231,9 +324,6 @@ Common::Error DrasculaEngine::run() {
curWidth = CHARACTER_WIDTH;
feetHeight = FEET_HEIGHT;
- talkHeight = TALK_HEIGHT;
- talkWidth = TALK_WIDTH;
-
hasAnswer = 0;
savedTime = 0;
breakOut = 0;
@@ -246,7 +336,7 @@ Common::Error DrasculaEngine::run() {
globalSpeed = 0;
curExcuseLook = 0;
curExcuseAction = 0;
- roomNumber = 0;
+ _roomNumber = 0;
for (i = 0; i < 8; i++)
actorFrames[i] = 0;
@@ -268,7 +358,7 @@ Common::Error DrasculaEngine::run() {
loadPic("aux13.alg", bgSurface, COMPLETE_PAL);
loadPic(96, frontSurface);
} else if (currentChapter == 4) {
- if (loadedDifferentChapter == 0)
+ if (!_loadedDifferentChapter)
animation_castle();
loadPic(96, frontSurface);
clearRoom();
@@ -300,7 +390,7 @@ Common::Error DrasculaEngine::run() {
memset(iconName, 0, sizeof(iconName));
for (i = 0; i < 6; i++)
- strcpy(iconName[i + 1], _textverbs[i]);
+ Common::strlcpy(iconName[i + 1], _textverbs[i], 13);
assignPalette(defaultPalette);
@@ -330,7 +420,7 @@ void DrasculaEngine::endChapter() {
bool DrasculaEngine::runCurrentChapter() {
int n;
- rightMouseButton = 0;
+ _rightMouseButton = 0;
previousMusic = -1;
@@ -360,14 +450,14 @@ bool DrasculaEngine::runCurrentChapter() {
if (currentChapter == 1) {
pickObject(28);
- if (loadedDifferentChapter == 0)
+ if (!_loadedDifferentChapter)
animation_1_1();
selectVerb(kVerbNone);
loadPic("2aux62.alg", drawSurface2);
trackProtagonist = 1;
objExit = 104;
- if (loadedDifferentChapter != 0) {
+ if (_loadedDifferentChapter) {
if (!loadGame(_currentSaveSlot)) {
return true;
}
@@ -383,7 +473,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(kItemPhone);
trackProtagonist = 3;
objExit = 162;
- if (loadedDifferentChapter == 0)
+ if (!_loadedDifferentChapter)
enterRoom(14);
else {
if (!loadGame(_currentSaveSlot)) {
@@ -401,7 +491,7 @@ bool DrasculaEngine::runCurrentChapter() {
flags[1] = 1;
trackProtagonist = 1;
objExit = 99;
- if (loadedDifferentChapter == 0)
+ if (!_loadedDifferentChapter)
enterRoom(20);
else {
if (!loadGame(_currentSaveSlot)) {
@@ -415,7 +505,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(kItemReefer2);
addObject(kItemOneCoin2);
objExit = 100;
- if (loadedDifferentChapter == 0) {
+ if (!_loadedDifferentChapter) {
enterRoom(21);
trackProtagonist = 0;
curX = 235;
@@ -437,7 +527,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(20);
trackProtagonist = 1;
objExit = 100;
- if (loadedDifferentChapter == 0) {
+ if (!_loadedDifferentChapter) {
enterRoom(45);
} else {
if (!loadGame(_currentSaveSlot)) {
@@ -450,7 +540,7 @@ bool DrasculaEngine::runCurrentChapter() {
trackProtagonist = 1;
objExit = 104;
- if (loadedDifferentChapter == 0) {
+ if (!_loadedDifferentChapter) {
enterRoom(58);
animation_1_6();
} else {
@@ -480,13 +570,13 @@ bool DrasculaEngine::runCurrentChapter() {
// lead to an incorrect setting of the protagonist's tracking flag (above). This
// made the character start walking off screen, as his actual position was
// different than the displayed one
- if (roomNumber == 3 && (curX == 279) && (curY + curHeight == 101)) {
+ if (_roomNumber == 3 && (curX == 279) && (curY + curHeight == 101)) {
gotoObject(178, 121);
gotoObject(169, 135);
- } else if (roomNumber == 14 && (curX == 214) && (curY + curHeight == 121)) {
+ } else if (_roomNumber == 14 && (curX == 214) && (curY + curHeight == 121)) {
walkToObject = 1;
gotoObject(190, 130);
- } else if (roomNumber == 14 && (curX == 246) && (curY + curHeight == 112)) {
+ } else if (_roomNumber == 14 && (curX == 246) && (curY + curHeight == 112)) {
walkToObject = 1;
gotoObject(190, 130);
}
@@ -518,12 +608,12 @@ bool DrasculaEngine::runCurrentChapter() {
checkObjects();
#ifdef _WIN32_WCE
- if (rightMouseButton) {
+ if (_rightMouseButton) {
if (_menuScreen) {
#else
- if (rightMouseButton == 1 && _menuScreen) {
+ if (_rightMouseButton == 1 && _menuScreen) {
#endif
- rightMouseButton = 0;
+ _rightMouseButton = 0;
delay(100);
if (currentChapter == 2) {
loadPic(menuBackground, cursorSurface);
@@ -549,10 +639,10 @@ bool DrasculaEngine::runCurrentChapter() {
// Do not show the inventory screen in chapter 5, if the right mouse button is clicked
// while the plug (object 16) is held
// Fixes bug #2059621 - "DRASCULA: Plug bug"
- if (rightMouseButton == 1 && !_menuScreen &&
+ if (_rightMouseButton == 1 && !_menuScreen &&
!(currentChapter == 5 && pickedObject == 16)) {
#endif
- rightMouseButton = 0;
+ _rightMouseButton = 0;
delay(100);
characterMoved = 0;
if (trackProtagonist == 2)
@@ -580,19 +670,19 @@ bool DrasculaEngine::runCurrentChapter() {
}
#endif
- if (leftMouseButton == 1 && _menuBar) {
+ if (_leftMouseButton == 1 && _menuBar) {
delay(100);
selectVerbFromBar();
- } else if (leftMouseButton == 1 && takeObject == 0) {
+ } else if (_leftMouseButton == 1 && takeObject == 0) {
delay(100);
if (verify1())
return true;
- } else if (leftMouseButton == 1 && takeObject == 1) {
+ } else if (_leftMouseButton == 1 && takeObject == 1) {
if (verify2())
return true;
}
- _menuBar = (mouseY < 24 && !_menuScreen) ? true : false;
+ _menuBar = (_mouseY < 24 && !_menuScreen) ? true : false;
Common::KeyCode key = getScan();
if (key == Common::KEYCODE_F1 && !_menuScreen) {
@@ -644,11 +734,11 @@ bool DrasculaEngine::runCurrentChapter() {
} else if (key == Common::KEYCODE_TILDE || key == Common::KEYCODE_BACKQUOTE) {
_console->attach();
_console->onFrame();
- } else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) {
+ } else if (currentChapter == 6 && key == Common::KEYCODE_0 && _roomNumber == 61) {
loadPic("alcbar.alg", bgSurface, 255);
}
- if (leftMouseButton != 0 || rightMouseButton != 0 || key != 0)
+ if (_leftMouseButton != 0 || _rightMouseButton != 0 || key != 0)
framesWithoutAction = 0;
if (framesWithoutAction == 15000) {
@@ -670,8 +760,8 @@ bool DrasculaEngine::verify1() {
removeObject();
else {
for (l = 0; l < numRoomObjs; l++) {
- if (mouseX >= _objectX1[l] && mouseY >= _objectY1[l]
- && mouseX <= _objectX2[l] && mouseY <= _objectY2[l] && doBreak == 0) {
+ if (_mouseX >= _objectX1[l] && _mouseY >= _objectY1[l]
+ && _mouseX <= _objectX2[l] && _mouseY <= _objectY2[l] && doBreak == 0) {
if (exitRoom(l))
return true;
if (doBreak == 1)
@@ -679,13 +769,13 @@ bool DrasculaEngine::verify1() {
}
}
- if (mouseX > curX && mouseY > curY
- && mouseX < curX + curWidth && mouseY < curY + curHeight)
+ if (_mouseX > curX && _mouseY > curY
+ && _mouseX < curX + curWidth && _mouseY < curY + curHeight)
doBreak = 1;
for (l = 0; l < numRoomObjs; l++) {
- if (mouseX > _objectX1[l] && mouseY > _objectY1[l]
- && mouseX < _objectX2[l] && mouseY < _objectY2[l] && doBreak == 0) {
+ if (_mouseX > _objectX1[l] && _mouseY > _objectY1[l]
+ && _mouseX < _objectX2[l] && _mouseY < _objectY2[l] && doBreak == 0) {
roomX = roomObjX[l];
roomY = roomObjY[l];
trackFinal = trackObj[l];
@@ -696,8 +786,8 @@ bool DrasculaEngine::verify1() {
}
if (doBreak == 0) {
- roomX = CLIP(mouseX, floorX1, floorX2);
- roomY = CLIP(mouseY, floorY1 + feetHeight, floorY2);
+ roomX = CLIP(_mouseX, floorX1, floorX2);
+ roomY = CLIP(_mouseY, floorY1 + feetHeight, floorY2);
startWalking();
}
doBreak = 0;
@@ -718,8 +808,8 @@ bool DrasculaEngine::verify2() {
return true;
} else {
for (l = 0; l < numRoomObjs; l++) {
- if (mouseX > _objectX1[l] && mouseY > _objectY1[l]
- && mouseX < _objectX2[l] && mouseY < _objectY2[l] && visible[l] == 1) {
+ if (_mouseX > _objectX1[l] && _mouseY > _objectY1[l]
+ && _mouseX < _objectX2[l] && _mouseY < _objectY2[l] && visible[l] == 1) {
trackFinal = trackObj[l];
walkToObject = 1;
gotoObject(roomObjX[l], roomObjY[l]);
@@ -779,20 +869,20 @@ void DrasculaEngine::updateEvents() {
case Common::EVENT_KEYUP:
break;
case Common::EVENT_MOUSEMOVE:
- mouseX = event.mouse.x;
- mouseY = event.mouse.y;
+ _mouseX = event.mouse.x;
+ _mouseY = event.mouse.y;
break;
case Common::EVENT_LBUTTONDOWN:
- leftMouseButton = 1;
+ _leftMouseButton = 1;
break;
case Common::EVENT_LBUTTONUP:
- leftMouseButton = 0;
+ _leftMouseButton = 0;
break;
case Common::EVENT_RBUTTONDOWN:
// We changed semantic and react only on button up event
break;
case Common::EVENT_RBUTTONUP:
- rightMouseButton = 1;
+ _rightMouseButton = 1;
break;
default:
break;
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index e547503bee..944191b5fb 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -403,7 +403,7 @@ public:
int actorFrames[8];
int previousMusic, roomMusic;
- int roomNumber;
+ int _roomNumber;
char roomDisk[20];
char currentData[20];
int numRoomObjs;
@@ -428,18 +428,17 @@ public:
int flags[NUM_FLAGS];
int frame_y;
- int curX, curY, characterMoved, curDirection, trackProtagonist, num_frame;
+ int curX, curY, characterMoved, curDirection, trackProtagonist, _characterFrame;
int hare_se_ve; // TODO: what is this for?
int roomX, roomY, checkFlags;
int doBreak;
int stepX, stepY;
int curHeight, curWidth, feetHeight;
- int talkHeight, talkWidth;
int floorX1, floorY1, floorX2, floorY2;
int lowerLimit, upperLimit;
int trackFinal, walkToObject;
int objExit;
- int timeDiff, startTime;
+ int _startTime;
int hasAnswer;
int savedTime;
int breakOut;
@@ -454,14 +453,11 @@ public:
int framesWithoutAction;
int term_int;
int currentChapter;
- int loadedDifferentChapter;
+ bool _loadedDifferentChapter;
int _currentSaveSlot;
int _color;
int musicStopped;
- int mouseX;
- int mouseY;
- int leftMouseButton;
- int rightMouseButton;
+ int _mouseX, _mouseY, _leftMouseButton, _rightMouseButton;
Common::KeyState _keyBuffer[KEYBUFSIZE];
int _keyBufferHead;
@@ -661,7 +657,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/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 3bdf724670..fe954279c3 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -82,7 +82,7 @@ void DrasculaEngine::moveCursor() {
} else if (!_menuScreen && _color != kColorLightGreen)
color_abc(kColorLightGreen);
if (_hasName && !_menuScreen)
- centerText(textName, mouseX, mouseY);
+ centerText(textName, _mouseX, _mouseY);
if (_menuScreen)
showMenu();
else if (_menuBar)
@@ -132,7 +132,7 @@ void DrasculaEngine::showFrame(Common::SeekableReadStream *stream, bool firstFra
byte *prevFrame = (byte *)malloc(64000);
Graphics::Surface *screenSurf = _system->lockScreen();
- byte *screenBuffer = (byte *)screenSurf->pixels;
+ byte *screenBuffer = (byte *)screenSurf->getPixels();
uint16 screenPitch = screenSurf->pitch;
for (int y = 0; y < 200; y++) {
memcpy(prevFrame+y*320, screenBuffer+y*screenPitch, 320);
@@ -336,7 +336,7 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
// original starts printing 4 lines above textY
int y = CLIP<int>(textY - (4 * CHAR_HEIGHT), 0, 320);
- strcpy(msg, message);
+ Common::strlcpy(msg, message, 200);
// If the message fits on screen as-is, just print it here
if (textFitsCentered(msg, textX)) {
@@ -363,8 +363,8 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
while (curWord != NULL) {
// Check if the word and the current line fit on screen
if (tmpMessageLine[0] != '\0')
- strcat(tmpMessageLine, " ");
- strcat(tmpMessageLine, curWord);
+ Common::strlcat(tmpMessageLine, " ", 200);
+ Common::strlcat(tmpMessageLine, curWord, 200);
if (textFitsCentered(tmpMessageLine, textX)) {
// Line fits, so add the word to the current message line
strcpy(messageLine, tmpMessageLine);
@@ -374,8 +374,8 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
// If it goes off screen, print_abc will adjust it
x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255);
print_abc(messageLine, x, y + curLine * CHAR_HEIGHT);
- strcpy(messageLine, curWord);
- strcpy(tmpMessageLine, curWord);
+ Common::strlcpy(messageLine, curWord, 200);
+ Common::strlcpy(tmpMessageLine, curWord, 200);
curLine++;
}
@@ -417,8 +417,8 @@ void DrasculaEngine::screenSaver() {
delete stream;
updateEvents();
- xr = mouseX;
- yr = mouseY;
+ xr = _mouseX;
+ yr = _mouseY;
while (!shouldQuit()) {
// efecto(bgSurface);
@@ -449,7 +449,7 @@ void DrasculaEngine::screenSaver() {
int x1_, y1_, off1, off2;
Graphics::Surface *screenSurf = _system->lockScreen();
- byte *screenBuffer = (byte *)screenSurf->pixels;
+ byte *screenBuffer = (byte *)screenSurf->getPixels();
uint16 screenPitch = screenSurf->pitch;
for (int i = 0; i < 200; i++) {
for (int j = 0; j < 320; j++) {
@@ -480,18 +480,18 @@ void DrasculaEngine::screenSaver() {
// end of efecto()
updateEvents();
- if (rightMouseButton == 1 || leftMouseButton == 1)
+ if (_rightMouseButton == 1 || _leftMouseButton == 1)
break;
- if (mouseX != xr)
+ if (_mouseX != xr)
break;
- if (mouseY != yr)
+ if (_mouseY != yr)
break;
}
// fin_ghost();
free(copia);
free(ghost);
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
showCursor();
}
@@ -538,7 +538,7 @@ int DrasculaEngine::playFrameSSN(Common::SeekableReadStream *stream) {
waitFrameSSN();
Graphics::Surface *screenSurf = _system->lockScreen();
- byte *screenBuffer = (byte *)screenSurf->pixels;
+ byte *screenBuffer = (byte *)screenSurf->getPixels();
uint16 screenPitch = screenSurf->pitch;
if (FrameSSN)
mixVideo(screenBuffer, screenSurface, screenPitch);
@@ -557,7 +557,7 @@ int DrasculaEngine::playFrameSSN(Common::SeekableReadStream *stream) {
free(BufferSSN);
waitFrameSSN();
Graphics::Surface *screenSurf = _system->lockScreen();
- byte *screenBuffer = (byte *)screenSurf->pixels;
+ byte *screenBuffer = (byte *)screenSurf->getPixels();
uint16 screenPitch = screenSurf->pitch;
if (FrameSSN)
mixVideo(screenBuffer, screenSurface, screenPitch);
diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp
index fca8040f59..f0b6d12027 100644
--- a/engines/drascula/interface.cpp
+++ b/engines/drascula/interface.cpp
@@ -51,7 +51,7 @@ bool DrasculaEngine::isCursorVisible() {
void DrasculaEngine::selectVerbFromBar() {
for (int n = 0; n < 7; n++) {
- if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1] && n > 0) {
+ if (_mouseX > _verbBarX[n] && _mouseX < _verbBarX[n + 1] && n > 0) {
selectVerb(n);
return;
}
@@ -143,7 +143,7 @@ void DrasculaEngine::clearMenu() {
int n, verbActivated = 1;
for (n = 0; n < 7; n++) {
- if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1])
+ if (_mouseX > _verbBarX[n] && _mouseX < _verbBarX[n + 1])
verbActivated = 0;
copyRect(OBJWIDTH * n, OBJHEIGHT * verbActivated, _verbBarX[n], 2,
OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface);
@@ -165,8 +165,8 @@ void DrasculaEngine::showMap() {
_hasName = false;
for (int l = 0; l < numRoomObjs; l++) {
- if (mouseX > _objectX1[l] && mouseY > _objectY1[l]
- && mouseX < _objectX2[l] && mouseY < _objectY2[l]
+ if (_mouseX > _objectX1[l] && _mouseY > _objectY1[l]
+ && _mouseX < _objectX2[l] && _mouseY < _objectY2[l]
&& visible[l] == 1) {
strcpy(textName, objName[l]);
_hasName = true;
diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp
index f9f68c3317..519e919433 100644
--- a/engines/drascula/objects.cpp
+++ b/engines/drascula/objects.cpp
@@ -91,8 +91,8 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) {
updateRoom();
updateScreen();
- // roomNumber -2 is end credits. Do not show cursor there
- if (cursorVisible && roomNumber != -2)
+ // _roomNumber -2 is end credits. Do not show cursor there
+ if (cursorVisible && _roomNumber != -2)
showCursor();
}
@@ -100,8 +100,8 @@ void DrasculaEngine::checkObjects() {
int l, veo = 0;
for (l = 0; l < numRoomObjs; l++) {
- if (mouseX > _objectX1[l] && mouseY > _objectY1[l]
- && mouseX < _objectX2[l] && mouseY < _objectY2[l]
+ if (_mouseX > _objectX1[l] && _mouseY > _objectY1[l]
+ && _mouseX < _objectX2[l] && _mouseY < _objectY2[l]
&& visible[l] == 1 && isDoor[l] == 0) {
strcpy(textName, objName[l]);
_hasName = true;
@@ -109,8 +109,8 @@ void DrasculaEngine::checkObjects() {
}
}
- if (mouseX > curX + 2 && mouseY > curY + 2
- && mouseX < curX + curWidth - 2 && mouseY < curY + curHeight - 2) {
+ if (_mouseX > curX + 2 && _mouseY > curY + 2
+ && _mouseX < curX + curWidth - 2 && _mouseY < curY + curHeight - 2) {
if (currentChapter == 2 || veo == 0) {
strcpy(textName, "hacker");
_hasName = true;
@@ -223,9 +223,9 @@ int DrasculaEngine::whichObject() {
int n;
for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) {
- if (mouseX > _itemLocations[n].x && mouseY > _itemLocations[n].y &&
- mouseX < _itemLocations[n].x + OBJWIDTH &&
- mouseY < _itemLocations[n].y + OBJHEIGHT) {
+ if (_mouseX > _itemLocations[n].x && _mouseY > _itemLocations[n].y &&
+ _mouseX < _itemLocations[n].x + OBJWIDTH &&
+ _mouseY < _itemLocations[n].y + OBJHEIGHT) {
return n;
}
}
@@ -237,69 +237,70 @@ void DrasculaEngine::updateVisible() {
if (currentChapter == 1) {
// nothing
} else if (currentChapter == 2) {
- if (roomNumber == 2 && flags[40] == 0)
+ if (_roomNumber == 2 && flags[40] == 0)
visible[3] = 0;
- else if (roomNumber == 3 && flags[3] == 1)
+ else if (_roomNumber == 3 && flags[3] == 1)
visible[8] = 0;
- else if (roomNumber == 6 && flags[1] == 1 && flags[10] == 0) {
+ else if (_roomNumber == 6 && flags[1] == 1 && flags[10] == 0) {
visible[2] = 0;
visible[4] = 1;
- } else if (roomNumber == 7 && flags[35] == 1)
+ } else if (_roomNumber == 7 && flags[35] == 1)
visible[3] = 0;
- else if (roomNumber == 14 && flags[5] == 1)
+ else if (_roomNumber == 14 && flags[5] == 1)
visible[4] = 0;
- else if (roomNumber == 18 && flags[28] == 1)
+ else if (_roomNumber == 18 && flags[28] == 1)
visible[2] = 0;
} else if (currentChapter == 3) {
// nothing
} else if (currentChapter == 4) {
- if (roomNumber == 23 && flags[0] == 0 && flags[11] == 0)
+ if (_roomNumber == 23 && flags[0] == 0 && flags[11] == 0)
visible[2] = 1;
- if (roomNumber == 23 && flags[0] == 1 && flags[11] == 0)
+ if (_roomNumber == 23 && flags[0] == 1 && flags[11] == 0)
visible[2] = 0;
- if (roomNumber == 21 && flags[10] == 1)
+ if (_roomNumber == 21 && flags[10] == 1)
visible[2] = 0;
- if (roomNumber == 22 && flags[26] == 1) {
+ if (_roomNumber == 22 && flags[26] == 1) {
visible[2] = 0;
visible[1] = 1;
}
- if (roomNumber == 22 && flags[27] == 1)
+ if (_roomNumber == 22 && flags[27] == 1)
visible[3] = 0;
- if (roomNumber == 26 && flags[21] == 0)
- strcpy(objName[2], _textmisc[0]);
- if (roomNumber == 26 && flags[18] == 1)
+ if (_roomNumber == 26 && flags[21] == 0) {
+ Common::strlcpy(objName[2], _textmisc[0], 20);
+ }
+ if (_roomNumber == 26 && flags[18] == 1)
visible[2] = 0;
- if (roomNumber == 26 && flags[12] == 1)
+ if (_roomNumber == 26 && flags[12] == 1)
visible[1] = 0;
- if (roomNumber == 35 && flags[14] == 1)
+ if (_roomNumber == 35 && flags[14] == 1)
visible[2] = 0;
- if (roomNumber == 35 && flags[17] == 1)
+ if (_roomNumber == 35 && flags[17] == 1)
visible[3] = 1;
- if (roomNumber == 35 && flags[15] == 1)
+ if (_roomNumber == 35 && flags[15] == 1)
visible[1] = 0;
} else if (currentChapter == 5) {
- if (roomNumber == 49 && flags[6] == 1)
+ if (_roomNumber == 49 && flags[6] == 1)
visible[2] = 0;
- if (roomNumber == 49 && flags[6] == 0)
+ if (_roomNumber == 49 && flags[6] == 0)
visible[1] = 0;
- if (roomNumber == 49 && flags[6] == 1)
+ if (_roomNumber == 49 && flags[6] == 1)
visible[1] = 1;
- if (roomNumber == 45 && flags[6] == 1)
+ if (_roomNumber == 45 && flags[6] == 1)
visible[3] = 1;
- if (roomNumber == 53 && flags[2] == 1)
+ if (_roomNumber == 53 && flags[2] == 1)
visible[3] = 0;
- if (roomNumber == 54 && flags[13] == 1)
+ if (_roomNumber == 54 && flags[13] == 1)
visible[3] = 0;
- if (roomNumber == 55 && flags[8] == 1)
+ if (_roomNumber == 55 && flags[8] == 1)
visible[1] = 0;
} else if (currentChapter == 6) {
- if (roomNumber == 58 && flags[8] == 0)
+ if (_roomNumber == 58 && flags[8] == 0)
isDoor[1] = 0;
- if (roomNumber == 58 && flags[8] == 1)
+ if (_roomNumber == 58 && flags[8] == 1)
isDoor[1] = 1;
- if (roomNumber == 59)
+ if (_roomNumber == 59)
isDoor[1] = 0;
- if (roomNumber == 60) {
+ if (_roomNumber == 60) {
trackDrascula = 0;
drasculaX = 155;
drasculaY = 69;
diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp
index 9f707eaa07..25f3da0080 100644
--- a/engines/drascula/rooms.cpp
+++ b/engines/drascula/rooms.cpp
@@ -1087,7 +1087,7 @@ bool DrasculaEngine::room_102(int fl) {
void DrasculaEngine::updateRefresh() {
// Check generic updaters
for (int i = 0; i < _roomUpdatesSize; i++) {
- if (_roomUpdates[i].roomNum == roomNumber) {
+ if (_roomUpdates[i].roomNum == _roomNumber) {
if (_roomUpdates[i].flag < 0 ||
flags[_roomUpdates[i].flag] == _roomUpdates[i].flagValue) {
if (_roomUpdates[i].type == 0) {
@@ -1107,25 +1107,25 @@ void DrasculaEngine::updateRefresh() {
// Call room-specific updater
char rm[20];
- sprintf(rm, "update_%d", roomNumber);
+ sprintf(rm, "update_%d", _roomNumber);
for (uint i = 0; i < _roomHandlers->roomUpdaters.size(); i++) {
if (!strcmp(rm, _roomHandlers->roomUpdaters[i]->desc)) {
- debug(8, "Calling room updater %d", roomNumber);
+ debug(8, "Calling room updater %d", _roomNumber);
(this->*(_roomHandlers->roomUpdaters[i]->proc))();
break;
}
}
- if (roomNumber == 10)
+ if (_roomNumber == 10)
showMap();
- else if (roomNumber == 45)
+ else if (_roomNumber == 45)
showMap();
}
void DrasculaEngine::updateRefresh_pre() {
// Check generic preupdaters
for (int i = 0; i < _roomPreUpdatesSize; i++) {
- if (_roomPreUpdates[i].roomNum == roomNumber) {
+ if (_roomPreUpdates[i].roomNum == _roomNumber) {
if (_roomPreUpdates[i].flag < 0 ||
flags[_roomPreUpdates[i].flag] == _roomPreUpdates[i].flagValue) {
if (_roomPreUpdates[i].type == 0) {
@@ -1145,16 +1145,16 @@ void DrasculaEngine::updateRefresh_pre() {
// Call room-specific preupdater
char rm[20];
- sprintf(rm, "update_%d_pre", roomNumber);
+ sprintf(rm, "update_%d_pre", _roomNumber);
for (uint i = 0; i < _roomHandlers->roomPreupdaters.size(); i++) {
if (!strcmp(rm, _roomHandlers->roomPreupdaters[i]->desc)) {
- debug(8, "Calling room preupdater %d", roomNumber);
+ debug(8, "Calling room preupdater %d", _roomNumber);
(this->*(_roomHandlers->roomPreupdaters[i]->proc))();
break;
}
}
- if (currentChapter == 1 && roomNumber == 16)
+ if (currentChapter == 1 && _roomNumber == 16)
placeBJ();
}
@@ -1577,12 +1577,12 @@ bool DrasculaEngine::checkAction(int fl) {
hasAnswer = 0;
} else if (currentChapter == 2) {
// Note: the original check was strcmp(num_room, "18.alg")
- if (pickedObject == 11 && fl == 50 && flags[22] == 0 && roomNumber != 18)
+ if (pickedObject == 11 && fl == 50 && flags[22] == 0 && _roomNumber != 18)
talk(315);
else
hasAnswer = 0;
} else if (currentChapter == 3) {
- if (roomNumber == 13) {
+ if (_roomNumber == 13) {
if (room(13, fl)) {
showCursor();
return true;
@@ -1590,13 +1590,13 @@ bool DrasculaEngine::checkAction(int fl) {
} else
hasAnswer = 0;
} else if (currentChapter == 4) {
- if (roomNumber == 28)
+ if (_roomNumber == 28)
talk(178);
else if (pickedObject == 8 && fl == 50 && flags[18] == 0)
talk(481);
else if (pickedObject == 12 && fl == 50 && flags[18] == 0)
talk(487);
- else if (roomNumber == 21) {
+ else if (_roomNumber == 21) {
if (room(21, fl)) {
showCursor();
return true;
@@ -1604,7 +1604,7 @@ bool DrasculaEngine::checkAction(int fl) {
} else
hasAnswer = 0;
} else if (currentChapter == 5) {
- if (roomNumber == 56) {
+ if (_roomNumber == 56) {
if (room(56, fl)) {
showCursor();
return true;
@@ -1616,9 +1616,9 @@ bool DrasculaEngine::checkAction(int fl) {
talk(308);
else if (pickedObject == kVerbLook && fl == 50 && flags[0] == 0)
talk(310);
- else if (roomNumber == 102)
+ else if (_roomNumber == 102)
room(102, fl);
- else if (roomNumber == 60) {
+ else if (_roomNumber == 60) {
if (room(60, fl)) {
showCursor();
return true;
@@ -1632,7 +1632,7 @@ bool DrasculaEngine::checkAction(int fl) {
if (hasAnswer == 0) {
hasAnswer = 1;
- room(roomNumber, fl);
+ room(_roomNumber, fl);
}
if (hasAnswer == 0 && (_hasName || _menuScreen))
@@ -1684,7 +1684,7 @@ void DrasculaEngine::enterRoom(int roomIndex) {
TextResourceParser p(stream, DisposeAfterUse::YES);
- p.parseInt(roomNumber);
+ p.parseInt(_roomNumber);
p.parseInt(roomMusic);
p.parseString(roomDisk);
p.parseInt(palLevel);
@@ -1778,7 +1778,7 @@ void DrasculaEngine::enterRoom(int roomIndex) {
}
loadPic(roomDisk, drawSurface3);
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
copyBackground(0, 171, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3);
@@ -1808,14 +1808,14 @@ void DrasculaEngine::enterRoom(int roomIndex) {
}
}
- if (roomNumber == 24) {
+ if (_roomNumber == 24) {
for (l = floorY1 - 1; l > 74; l--) {
factor_red[l] = (int)(upperLimit - pequegnez);
pequegnez = pequegnez + chiquez;
}
}
- if (currentChapter == 5 && roomNumber == 54) {
+ if (currentChapter == 5 && _roomNumber == 54) {
for (l = floorY1 - 1; l > 84; l--) {
factor_red[l] = (int)(upperLimit - pequegnez);
pequegnez = pequegnez + chiquez;
@@ -1853,13 +1853,13 @@ void DrasculaEngine::enterRoom(int roomIndex) {
isDoor[7] = 0;
if (currentChapter == 2) {
- if (roomNumber == 14 && flags[39] == 1)
+ if (_roomNumber == 14 && flags[39] == 1)
roomMusic = 16;
- else if (roomNumber == 15 && flags[39] == 1)
+ else if (_roomNumber == 15 && flags[39] == 1)
roomMusic = 16;
- if (roomNumber == 14 && flags[5] == 1)
+ if (_roomNumber == 14 && flags[5] == 1)
roomMusic = 0;
- else if (roomNumber == 15 && flags[5] == 1)
+ else if (_roomNumber == 15 && flags[5] == 1)
roomMusic = 0;
if (previousMusic != roomMusic && roomMusic != 0)
@@ -1872,21 +1872,21 @@ void DrasculaEngine::enterRoom(int roomIndex) {
}
if (currentChapter == 2) {
- if (roomNumber == 9 || roomNumber == 2 || roomNumber == 14 || roomNumber == 18)
+ if (_roomNumber == 9 || _roomNumber == 2 || _roomNumber == 14 || _roomNumber == 18)
savedTime = getTime();
}
if (currentChapter == 4) {
- if (roomNumber == 26)
+ if (_roomNumber == 26)
savedTime = getTime();
}
- if (currentChapter == 4 && roomNumber == 24 && flags[29] == 1)
+ if (currentChapter == 4 && _roomNumber == 24 && flags[29] == 1)
animation_7_4();
if (currentChapter == 5) {
- if (roomNumber == 45)
+ if (_roomNumber == 45)
hare_se_ve = 0;
- if (roomNumber == 49 && flags[7] == 0) {
+ if (_roomNumber == 49 && flags[7] == 0) {
playTalkSequence(4); // sequence 4, chapter 5
}
}
diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp
index 996c9d3f03..61d6f0b4af 100644
--- a/engines/drascula/saveload.cpp
+++ b/engines/drascula/saveload.cpp
@@ -263,7 +263,7 @@ bool DrasculaEngine::loadGame(int slot) {
if (savedChapter != currentChapter) {
_currentSaveSlot = slot;
currentChapter = savedChapter - 1;
- loadedDifferentChapter = 1;
+ _loadedDifferentChapter = true;
delete in;
return false;
}
@@ -283,7 +283,7 @@ bool DrasculaEngine::loadGame(int slot) {
takeObject = in->readSint32LE();
pickedObject = in->readSint32LE();
- loadedDifferentChapter = 0;
+ _loadedDifferentChapter = false;
if (!sscanf(currentData, "%d.ald", &roomNum)) {
error("Bad save format");
}
@@ -383,10 +383,10 @@ bool DrasculaEngine::saveLoadScreen() {
updateScreen();
updateEvents();
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
// Check if the user has clicked on a save slot
for (n = 0; n < NUM_SAVES; n++) {
- if (mouseX > 115 && mouseY > 27 + (9 * n) && mouseX < 115 + 175 && mouseY < 27 + 10 + (9 * n)) {
+ if (_mouseX > 115 && _mouseY > 27 + (9 * n) && _mouseX < 115 + 175 && _mouseY < 27 + 10 + (9 * n)) {
selectedSlot = n;
selectedName = _saveNames[selectedSlot];
if (selectedName.empty()) {
@@ -399,14 +399,14 @@ bool DrasculaEngine::saveLoadScreen() {
}
// Check if the user has clicked in the text area above the save slots
- if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && !selectedName.empty()) {
+ if (_mouseX > 117 && _mouseY > 15 && _mouseX < 295 && _mouseY < 24 && !selectedName.empty()) {
selectedName = enterName(selectedName);
if (!selectedName.empty())
_saveNames[selectedSlot] = selectedName; // update save name
}
// Check if the user has clicked a button
- if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149) {
+ if (_mouseX > 208 && _mouseY > 123 && _mouseX < 282 && _mouseY < 149) {
// "Save" button
if (selectedName.empty()) {
print_abc("Please select a slot", 117, 15);
@@ -415,14 +415,14 @@ bool DrasculaEngine::saveLoadScreen() {
} else {
selectVerb(kVerbNone);
clearRoom();
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
updateRoom();
updateScreen();
saveGame(selectedSlot + 1, _saveNames[selectedSlot]);
return true;
}
- } else if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149) {
+ } else if (_mouseX > 125 && _mouseY > 123 && _mouseX < 199 && _mouseY < 149) {
// "Load" button
if (selectedName.empty()) {
print_abc("Please select a slot", 117, 15);
@@ -431,19 +431,19 @@ bool DrasculaEngine::saveLoadScreen() {
} else {
return loadGame(selectedSlot + 1);
}
- } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) {
+ } else if (_mouseX > 168 && _mouseY > 154 && _mouseX < 242 && _mouseY < 180) {
// "Play" button
break;
}
- } // if (leftMouseButton == 1)
+ } // if (_leftMouseButton == 1)
- leftMouseButton = 0;
+ _leftMouseButton = 0;
delay(10);
}
selectVerb(kVerbNone);
clearRoom();
- loadPic(roomNumber, bgSurface, HALF_PAL);
+ loadPic(_roomNumber, bgSurface, HALF_PAL);
return true;
}
diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp
index 112f6fd06c..59b5e1d237 100644
--- a/engines/drascula/sound.cpp
+++ b/engines/drascula/sound.cpp
@@ -36,9 +36,9 @@ namespace Drascula {
void DrasculaEngine::updateVolume(Audio::Mixer::SoundType soundType, int prevVolume) {
int vol = _mixer->getVolumeForSoundType(soundType) / 16;
- if (mouseY < prevVolume && vol < 15)
+ if (_mouseY < prevVolume && vol < 15)
vol++;
- if (mouseY > prevVolume && vol > 0)
+ if (_mouseY > prevVolume && vol > 0)
vol--;
_mixer->setVolumeForSoundType(soundType, vol * 16);
}
@@ -78,23 +78,23 @@ void DrasculaEngine::volumeControls() {
while (getScan())
;
- if (rightMouseButton == 1) {
+ if (_rightMouseButton == 1) {
// Clear this to avoid going straight to the inventory
- rightMouseButton = 0;
+ _rightMouseButton = 0;
delay(100);
break;
}
- if (leftMouseButton == 1) {
+ if (_leftMouseButton == 1) {
delay(100);
- if (mouseX > 80 && mouseX < 121) {
+ if (_mouseX > 80 && _mouseX < 121) {
updateVolume(Audio::Mixer::kPlainSoundType, masterVolumeY);
}
- if (mouseX > 136 && mouseX < 178) {
+ if (_mouseX > 136 && _mouseX < 178) {
updateVolume(Audio::Mixer::kSpeechSoundType, voiceVolumeY);
}
- if (mouseX > 192 && mouseX < 233) {
+ if (_mouseX > 192 && _mouseX < 233) {
updateVolume(Audio::Mixer::kMusicSoundType, musicVolumeY);
}
}
diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp
index a326852e96..6aabd91c6a 100644
--- a/engines/drascula/talk.cpp
+++ b/engines/drascula/talk.cpp
@@ -381,11 +381,11 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
int face;
if (currentChapter == 6) {
- if (flags[0] == 0 && roomNumber == 102) {
+ if (flags[0] == 0 && _roomNumber == 102) {
talk_pen(said, filename, 0);
return;
}
- if (flags[0] == 0 && roomNumber == 58) {
+ if (flags[0] == 0 && _roomNumber == 58) {
talk_pen(said, filename, 1);
return;
}
@@ -397,7 +397,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
}
if (currentChapter == 4) {
- if (roomNumber == 24 || flags[29] == 0) {
+ if (_roomNumber == 24 || flags[29] == 0) {
color_abc(kColorYellow);
}
} else {
@@ -413,59 +413,59 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
updateRefresh_pre();
if (currentChapter == 2)
- copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, talkHeight - 1, screenSurface, drawSurface3);
+ copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, TALK_HEIGHT - 1, screenSurface, drawSurface3);
else
copyBackground(curX, curY, OBJWIDTH + 1, 0, (int)(((float)curWidth / 100) * factor_red[MIN(201, curY + curHeight)]),
- (int)(((float)(talkHeight - 1) / 100) * factor_red[MIN(201, curY + curHeight)]),
+ (int)(((float)(TALK_HEIGHT - 1) / 100) * factor_red[MIN(201, curY + curHeight)]),
screenSurface, drawSurface3);
moveCharacters();
if (currentChapter == 2) {
if (!strcmp(menuBackground, "99.alg") || !strcmp(menuBackground, "994.alg"))
- copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, talkHeight - 1, drawSurface3, screenSurface);
+ copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, TALK_HEIGHT - 1, drawSurface3, screenSurface);
} else {
copyBackground(OBJWIDTH + 1, 0, curX, curY, (int)(((float)curWidth / 100) * factor_red[MIN(201, curY + curHeight)]),
- (int)(((float)(talkHeight - 1) / 100) * factor_red[MIN(201, curY + curHeight)]),
+ (int)(((float)(TALK_HEIGHT - 1) / 100) * factor_red[MIN(201, curY + curHeight)]),
drawSurface3, screenSurface);
}
if (trackProtagonist == 0) {
if (currentChapter == 2)
- copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, talkWidth, talkHeight,
+ copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, TALK_WIDTH, TALK_HEIGHT,
extraSurface, screenSurface);
else
reduce_hare_chico(x_talk_izq[face], y_mask_talk, curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]),
- curY, talkWidth, talkHeight, factor_red[MIN(201, curY + curHeight)],
+ curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)],
extraSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 1) {
if (currentChapter == 2)
- copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight,
+ copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT,
extraSurface, screenSurface);
else
reduce_hare_chico(x_talk_dch[face], y_mask_talk, curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]),
- curY, talkWidth, talkHeight, factor_red[MIN(201, curY + curHeight)], extraSurface, screenSurface);
+ curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], extraSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 2) {
if (currentChapter == 2)
- copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight,
+ copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT,
frontSurface, screenSurface);
else
reduce_hare_chico(x_talk_izq[face], y_mask_talk,
talkOffset + curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]),
- curY, talkWidth, talkHeight, factor_red[MIN(201, curY + curHeight)],
+ curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)],
frontSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 3) {
if (currentChapter == 2)
- copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, talkWidth, talkHeight,
+ copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, TALK_WIDTH, TALK_HEIGHT,
frontSurface, screenSurface);
else
reduce_hare_chico(x_talk_dch[face], y_mask_talk,
talkOffset + curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]),
- curY, talkWidth,talkHeight, factor_red[MIN(201, curY + curHeight)],
+ curY, TALK_WIDTH,TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)],
frontSurface, screenSurface);
updateRefresh();
}
@@ -827,47 +827,47 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
updateRefresh_pre();
if (currentChapter == 2)
- copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, talkHeight - 1, screenSurface, drawSurface3);
+ copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, TALK_HEIGHT - 1, screenSurface, drawSurface3);
else
copyBackground(curX, curY, OBJWIDTH + 1, 0, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]),
- (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), screenSurface, drawSurface3);
+ (int)(((float)(TALK_HEIGHT - 1) / 100) * factor_red[curY + curHeight]), screenSurface, drawSurface3);
moveCharacters();
if (currentChapter == 2) {
if (curHeight != 56)
- copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, talkHeight - 1, drawSurface3, screenSurface);
+ copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, TALK_HEIGHT - 1, drawSurface3, screenSurface);
} else
copyBackground(OBJWIDTH + 1, 0, curX, curY, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]),
- (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), drawSurface3, screenSurface);
+ (int)(((float)(TALK_HEIGHT - 1) / 100) * factor_red[curY + curHeight]), drawSurface3, screenSurface);
if (trackProtagonist == 0) {
if (currentChapter == 2)
- copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, talkWidth, talkHeight, extraSurface, screenSurface);
+ copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, TALK_WIDTH, TALK_HEIGHT, extraSurface, screenSurface);
else
reduce_hare_chico(x_talk_izq[face], y_mask_talk, (int)(curX + (8.0f / 100) * factor_red[curY + curHeight]),
- curY, talkWidth, talkHeight, factor_red[curY + curHeight], extraSurface, screenSurface);
+ curY, TALK_WIDTH, TALK_HEIGHT, factor_red[curY + curHeight], extraSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 1) {
if (currentChapter == 2)
- copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, extraSurface, screenSurface);
+ copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT, extraSurface, screenSurface);
else
reduce_hare_chico(x_talk_dch[face], y_mask_talk, (int)(curX + (12.0f / 100) * factor_red[curY + curHeight]),
- curY, talkWidth, talkHeight, factor_red[curY + curHeight], extraSurface, screenSurface);
+ curY, TALK_WIDTH, TALK_HEIGHT, factor_red[curY + curHeight], extraSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 2) {
if (currentChapter == 2)
- copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, frontSurface, screenSurface);
+ copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT, frontSurface, screenSurface);
else
reduce_hare_chico(x_talk_izq[face], y_mask_talk,
(int)(talkOffset + curX + (12.0f / 100) * factor_red[curY + curHeight]), curY,
- talkWidth, talkHeight, factor_red[curY + curHeight], frontSurface, screenSurface);
+ TALK_WIDTH, TALK_HEIGHT, factor_red[curY + curHeight], frontSurface, screenSurface);
updateRefresh();
} else if (trackProtagonist == 3) {
if (currentChapter == 2)
- copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, talkWidth, talkHeight, frontSurface, screenSurface);
+ copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, TALK_WIDTH, TALK_HEIGHT, frontSurface, screenSurface);
else
reduce_hare_chico(x_talk_dch[face], y_mask_talk,
(int)(talkOffset + curX + (8.0f / 100) * factor_red[curY + curHeight]), curY,
- talkWidth, talkHeight, factor_red[curY + curHeight], frontSurface, screenSurface);
+ TALK_WIDTH, TALK_HEIGHT, factor_red[curY + curHeight], frontSurface, screenSurface);
updateRefresh();
}
diff --git a/engines/dreamweb/POTFILES b/engines/dreamweb/POTFILES
new file mode 100644
index 0000000000..d05d239bb7
--- /dev/null
+++ b/engines/dreamweb/POTFILES
@@ -0,0 +1 @@
+engines/dreamweb/detection.cpp
diff --git a/engines/dreamweb/configure.engine b/engines/dreamweb/configure.engine
new file mode 100644
index 0000000000..27506e650f
--- /dev/null
+++ b/engines/dreamweb/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine dreamweb "Dreamweb" yes
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index c3ede46df2..7323dfc4a8 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"
@@ -226,6 +225,49 @@ DreamWebEngine::DreamWebEngine(OSystem *syst, const DreamWebGameDescription *gam
_linePointer = 0;
_lineDirection = 0;
_lineLength = 0;
+
+ _subtitles = 0;
+ _foreignRelease = 0;
+ _wonGame = 0;
+ _hasSpeech = 0;
+ _roomsSample = 0;
+ _copyProtection = 0;
+
+ for (uint i = 0; i < 128; i++)
+ memset(&_setDat[i], 0, sizeof(SetObject));
+
+ for (uint i = 0; i < 80; i++)
+ memset(&_freeDat[i], 0, sizeof(DynObject));
+
+ for (uint i = 0; i < kNumExObjects; i++)
+ memset(&_exData[i], 0, sizeof(DynObject));
+
+ memset(&_vars, 0, sizeof(GameVars));
+
+ for (uint i = 0; i < 96; i++)
+ memset(&_backdropFlags[i], 0, sizeof(BackdropMapFlag));
+
+ for (uint i = 0; i < kNumReelRoutines+1; i++)
+ memset(&_reelRoutines[i], 0, sizeof(ReelRoutine));
+
+ _personData = 0;
+
+ for (uint i = 0; i < 16; i++)
+ memset(&_openInvList[i], 0, sizeof(ObjectRef));
+
+ for (uint i = 0; i < 30; i++)
+ memset(&_ryanInvList[i], 0, sizeof(ObjectRef));
+
+ for (uint i = 0; i < 11*10; i++)
+ memset(&_mapFlags[i], 0, sizeof(MapFlag));
+
+ for (uint i = 0; i < kNumChanges; i++)
+ memset(&_listOfChanges[i], 0, sizeof(Change));
+
+ _currentCharset = 0;
+
+ for (uint i = 0; i < 36; i++)
+ memset(&_pathData[i], 0, sizeof(RoomPaths));
}
DreamWebEngine::~DreamWebEngine() {
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index 5746568e4e..010f3883b0 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -144,8 +144,6 @@ public:
bool loadSpeech(const Common::String &filename);
- void enableSavingOrLoading(bool enable = true) { _enableSavingOrLoading = enable; }
-
Common::Language getLanguage() const;
uint8 modifyChar(uint8 c) const;
Common::String modifyFileName(const char *);
@@ -171,7 +169,6 @@ private:
uint _speed;
bool _turbo;
uint _oldMouseState;
- bool _enableSavingOrLoading;
protected:
GameVars _vars; // saved variables
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/engine.cpp b/engines/engine.cpp
index c84404cc68..52020c772e 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -183,7 +183,7 @@ void initCommonGFX(bool defaultTo1XScaler) {
g_system->setGraphicsMode(gfxMode.c_str());
// HACK: For OpenGL modes, we will still honor the graphics scale override
- if (defaultTo1XScaler && (gfxMode.equalsIgnoreCase("gl1") || gfxMode.equalsIgnoreCase("gl2") || gfxMode.equalsIgnoreCase("gl4")))
+ if (defaultTo1XScaler && (gfxMode.equalsIgnoreCase("opengl_linear") || gfxMode.equalsIgnoreCase("opengl_nearest")))
g_system->resetGraphicsScale();
}
}
diff --git a/engines/engines.mk b/engines/engines.mk
deleted file mode 100644
index 595b0ae3a2..0000000000
--- a/engines/engines.mk
+++ /dev/null
@@ -1,248 +0,0 @@
-ifdef ENABLE_SCUMM
-DEFINES += -DENABLE_SCUMM=$(ENABLE_SCUMM)
-MODULES += engines/scumm
-
-ifdef ENABLE_SCUMM_7_8
-DEFINES += -DENABLE_SCUMM_7_8
-endif
-
-ifdef ENABLE_HE
-DEFINES += -DENABLE_HE
-endif
-
-endif
-
-ifdef ENABLE_AGI
-DEFINES += -DENABLE_AGI=$(ENABLE_AGI)
-MODULES += engines/agi
-endif
-
-ifdef ENABLE_AGOS
-DEFINES += -DENABLE_AGOS=$(ENABLE_AGOS)
-MODULES += engines/agos
-
-ifdef ENABLE_AGOS2
-DEFINES += -DENABLE_AGOS2
-endif
-endif
-
-ifdef ENABLE_CGE
-DEFINES += -DENABLE_CGE=$(ENABLE_CGE)
-MODULES += engines/cge
-endif
-
-ifdef ENABLE_CINE
-DEFINES += -DENABLE_CINE=$(ENABLE_CINE)
-MODULES += engines/cine
-endif
-
-ifdef ENABLE_COMPOSER
-DEFINES += -DENABLE_COMPOSER=$(ENABLE_COMPOSER)
-MODULES += engines/composer
-endif
-
-ifdef ENABLE_CRUISE
-DEFINES += -DENABLE_CRUISE=$(ENABLE_CRUISE)
-MODULES += engines/cruise
-endif
-
-ifdef ENABLE_DRACI
-DEFINES += -DENABLE_DRACI=$(ENABLE_DRACI)
-MODULES += engines/draci
-endif
-
-ifdef ENABLE_DRASCULA
-DEFINES += -DENABLE_DRASCULA=$(ENABLE_DRASCULA)
-MODULES += engines/drascula
-endif
-
-ifdef ENABLE_DREAMWEB
-DEFINES += -DENABLE_DREAMWEB=$(ENABLE_DREAMWEB)
-MODULES += engines/dreamweb
-endif
-
-ifdef ENABLE_GOB
-DEFINES += -DENABLE_GOB=$(ENABLE_GOB)
-MODULES += engines/gob
-endif
-
-ifdef ENABLE_GROOVIE
-DEFINES += -DENABLE_GROOVIE=$(ENABLE_GROOVIE)
-MODULES += engines/groovie
-
-ifdef ENABLE_GROOVIE2
-DEFINES += -DENABLE_GROOVIE2
-endif
-endif
-
-ifdef ENABLE_HOPKINS
-DEFINES += -DENABLE_HOPKINS=$(ENABLE_HOPKINS)
-MODULES += engines/hopkins
-endif
-
-ifdef ENABLE_HUGO
-DEFINES += -DENABLE_HUGO=$(ENABLE_HUGO)
-MODULES += engines/hugo
-endif
-
-ifdef ENABLE_KYRA
-DEFINES += -DENABLE_KYRA=$(ENABLE_KYRA)
-MODULES += engines/kyra
-
-ifdef ENABLE_LOL
-DEFINES += -DENABLE_LOL
-endif
-
-ifdef ENABLE_EOB
-DEFINES += -DENABLE_EOB
-endif
-endif
-
-ifdef ENABLE_LASTEXPRESS
-DEFINES += -DENABLE_LASTEXPRESS=$(ENABLE_LASTEXPRESS)
-MODULES += engines/lastexpress
-endif
-
-ifdef ENABLE_LURE
-DEFINES += -DENABLE_LURE=$(ENABLE_LURE)
-MODULES += engines/lure
-endif
-
-ifdef ENABLE_MADE
-DEFINES += -DENABLE_MADE=$(ENABLE_MADE)
-MODULES += engines/made
-endif
-
-ifdef ENABLE_MOHAWK
-DEFINES += -DENABLE_MOHAWK=$(ENABLE_MOHAWK)
-MODULES += engines/mohawk
-
-ifdef ENABLE_CSTIME
-DEFINES += -DENABLE_CSTIME
-endif
-
-ifdef ENABLE_MYST
-DEFINES += -DENABLE_MYST
-endif
-
-ifdef ENABLE_RIVEN
-DEFINES += -DENABLE_RIVEN
-endif
-endif
-
-ifdef ENABLE_NEVERHOOD
-DEFINES += -DENABLE_NEVERHOOD=$(ENABLE_NEVERHOOD)
-MODULES += engines/neverhood
-endif
-
-ifdef ENABLE_PARALLACTION
-DEFINES += -DENABLE_PARALLACTION=$(ENABLE_PARALLACTION)
-MODULES += engines/parallaction
-endif
-
-ifdef ENABLE_PEGASUS
-DEFINES += -DENABLE_PEGASUS=$(ENABLE_PEGASUS)
-MODULES += engines/pegasus
-endif
-
-ifdef ENABLE_QUEEN
-DEFINES += -DENABLE_QUEEN=$(ENABLE_QUEEN)
-MODULES += engines/queen
-endif
-
-ifdef ENABLE_SAGA
-DEFINES += -DENABLE_SAGA=$(ENABLE_SAGA)
-MODULES += engines/saga
-
-ifdef ENABLE_IHNM
-DEFINES += -DENABLE_IHNM
-endif
-
-ifdef ENABLE_SAGA2
-DEFINES += -DENABLE_SAGA2
-endif
-endif
-
-ifdef ENABLE_SCI
-DEFINES += -DENABLE_SCI=$(ENABLE_SCI)
-MODULES += engines/sci
-
-ifdef ENABLE_SCI32
-DEFINES += -DENABLE_SCI32
-endif
-endif
-
-ifdef ENABLE_SKY
-DEFINES += -DENABLE_SKY=$(ENABLE_SKY)
-MODULES += engines/sky
-endif
-
-ifdef ENABLE_SWORD1
-DEFINES += -DENABLE_SWORD1=$(ENABLE_SWORD1)
-MODULES += engines/sword1
-endif
-
-ifdef ENABLE_SWORD2
-DEFINES += -DENABLE_SWORD2=$(ENABLE_SWORD2)
-MODULES += engines/sword2
-endif
-
-ifdef ENABLE_SWORD25
-DEFINES += -DENABLE_SWORD25=$(ENABLE_SWORD25)
-MODULES += engines/sword25
-endif
-
-ifdef ENABLE_TESTBED
-DEFINES += -DENABLE_TESTBED=$(ENABLE_TESTBED)
-MODULES += engines/testbed
-endif
-
-ifdef ENABLE_TEENAGENT
-DEFINES += -DENABLE_TEENAGENT=$(ENABLE_TEENAGENT)
-MODULES += engines/teenagent
-endif
-
-ifdef ENABLE_TINSEL
-DEFINES += -DENABLE_TINSEL=$(ENABLE_TINSEL)
-MODULES += engines/tinsel
-endif
-
-ifdef ENABLE_TOLTECS
-DEFINES += -DENABLE_TOLTECS=$(ENABLE_TOLTECS)
-MODULES += engines/toltecs
-endif
-
-ifdef ENABLE_TONY
-DEFINES += -DENABLE_TONY=$(ENABLE_TONY)
-MODULES += engines/tony
-endif
-
-ifdef ENABLE_TOON
-DEFINES += -DENABLE_TOON=$(ENABLE_TOON)
-MODULES += engines/toon
-endif
-
-ifdef ENABLE_TOUCHE
-DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE)
-MODULES += engines/touche
-endif
-
-ifdef ENABLE_TSAGE
-DEFINES += -DENABLE_TSAGE=$(ENABLE_TSAGE)
-MODULES += engines/tsage
-endif
-
-ifdef ENABLE_TUCKER
-DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
-MODULES += engines/tucker
-endif
-
-ifdef ENABLE_WINTERMUTE
-DEFINES += -DENABLE_WINTERMUTE=$(ENABLE_WINTERMUTE)
-MODULES += engines/wintermute
-endif
-
-ifdef ENABLE_VOYEUR
-DEFINES += -DENABLE_VOYEUR=$(ENABLE_VOYEUR)
-MODULES += engines/voyeur
-endif
diff --git a/engines/fullpipe/behavior.cpp b/engines/fullpipe/behavior.cpp
new file mode 100644
index 0000000000..c27f1082f5
--- /dev/null
+++ b/engines/fullpipe/behavior.cpp
@@ -0,0 +1,334 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/behavior.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/messages.h"
+
+namespace Fullpipe {
+
+BehaviorManager::BehaviorManager() {
+ _scene = 0;
+ _isActive = 1;
+}
+
+BehaviorManager::~BehaviorManager() {
+ clear();
+}
+
+void BehaviorManager::clear() {
+ for (uint i = 0; i < _behaviors.size(); i++) {
+ for (int j = 0; j < _behaviors[i]->_itemsCount; j++)
+ delete _behaviors[i]->_bheItems[j];
+
+ delete _behaviors[i];
+ }
+ _behaviors.clear();
+}
+
+void BehaviorManager::initBehavior(Scene *sc, GameVar *var) {
+ clear();
+ _scene = sc;
+
+ BehaviorInfo *behinfo;
+
+ GameVar *behvar = var->getSubVarByName("BEHAVIOR");
+ if (!behvar)
+ return;
+
+ for (GameVar *subvar = behvar->_subVars; subvar; subvar = subvar->_nextVarObj) {
+ if (!strcmp(subvar->_varName, "AMBIENT")) {
+ behinfo = new BehaviorInfo;
+ behinfo->initAmbientBehavior(subvar, sc);
+
+ _behaviors.push_back(behinfo);
+ } else {
+ StaticANIObject *ani = sc->getStaticANIObject1ByName(subvar->_varName, -1);
+ if (ani)
+ for (uint i = 0; i < sc->_staticANIObjectList1.size(); i++)
+ if (((StaticANIObject *)sc->_staticANIObjectList1[i])->_id == ani->_id) {
+ behinfo = new BehaviorInfo;
+ behinfo->initObjectBehavior(subvar, sc, ani);
+ behinfo->_ani = (StaticANIObject *)sc->_staticANIObjectList1[i];
+
+ _behaviors.push_back(behinfo);
+ }
+ }
+ }
+}
+
+void BehaviorManager::updateBehaviors() {
+ if (!_isActive)
+ return;
+
+ debug(0, "BehaviorManager::updateBehaviors()");
+ for (uint i = 0; i < _behaviors.size(); i++) {
+ BehaviorInfo *beh = _behaviors[i];
+
+ if (!beh->_ani) {
+ beh->_counter++;
+ if (beh->_counter >= beh->_counterMax)
+ updateBehavior(beh, beh->_bheItems[0]);
+
+ continue;
+ }
+
+ if (beh->_ani->_movement || !(beh->_ani->_flags & 4) || (beh->_ani->_flags & 2)) {
+ beh->_staticsId = 0;
+ continue;
+ }
+
+ if (beh->_ani->_statics->_staticsId == beh->_staticsId) {
+ beh->_counter++;
+ if (beh->_counter >= beh->_counterMax) {
+ if (beh->_subIndex >= 0 && !(beh->_flags & 1) && beh->_ani->_messageQueueId <= 0)
+ updateStaticAniBehavior(beh->_ani, beh->_counter, beh->_bheItems[beh->_subIndex]);
+ }
+ } else {
+ beh->_staticsId = beh->_ani->_statics->_staticsId;
+ beh->_counter = 0;
+ beh->_subIndex = -1;
+
+ for (int j = 0; j < beh->_itemsCount; j++)
+ if (beh->_bheItems[j]->_staticsId == beh->_staticsId) {
+ beh->_subIndex = j;
+ break;
+ }
+
+ }
+ }
+}
+
+void BehaviorManager::updateBehavior(BehaviorInfo *behaviorInfo, BehaviorEntry *entry) {
+ debug(0, "BehaviorManager::updateBehavior() %d", entry->_itemsCount);
+ for (int i = 0; i < entry->_itemsCount; i++) {
+ BehaviorEntryInfo *bhi = entry->_items[i];
+ if (!(bhi->_flags & 1)) {
+ if (bhi->_flags & 2) {
+ MessageQueue *mq = new MessageQueue(bhi->_messageQueue, 0, 1);
+
+ mq->sendNextCommand();
+
+ bhi->_flags &= 0xFFFFFFFD;
+ } else if (behaviorInfo->_counter >= bhi->_delay && bhi->_percent && g_fullpipe->_rnd->getRandomNumber(32767) <= entry->_items[i]->_percent) {
+ MessageQueue *mq = new MessageQueue(bhi->_messageQueue, 0, 1);
+
+ mq->sendNextCommand();
+
+ behaviorInfo->_counter = 0;
+ }
+ }
+ }
+}
+
+void BehaviorManager::updateStaticAniBehavior(StaticANIObject *ani, int delay, BehaviorEntry *bhe) {
+ debug(0, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName));
+
+ MessageQueue *mq = 0;
+
+ if (bhe->_flags & 1) {
+ uint rnd = g_fullpipe->_rnd->getRandomNumber(32767);
+ uint runPercent = 0;
+ for (int i = 0; i < bhe->_itemsCount; i++) {
+ if (!(bhe->_items[i]->_flags & 1) && bhe->_items[i]->_percent) {
+ if ((rnd >= runPercent && rnd <= runPercent + bhe->_items[i]->_percent) || i == bhe->_itemsCount - 1) {
+ mq = new MessageQueue(bhe->_items[i]->_messageQueue, 0, 1);
+ break;
+ }
+ runPercent += bhe->_items[i]->_percent;
+ }
+ }
+ } else {
+ for (int i = 0; i < bhe->_itemsCount; i++) {
+ if (!(bhe->_items[i]->_flags & 1) && delay >= bhe->_items[i]->_delay) {
+ if (bhe->_items[i]->_percent) {
+ if (g_fullpipe->_rnd->getRandomNumber(32767) <= bhe->_items[i]->_percent) {
+ mq = new MessageQueue(bhe->_items[i]->_messageQueue, 0, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (mq) {
+ mq->replaceKeyCode(-1, ani->_okeyCode);
+ mq->chain(ani);
+ }
+}
+
+bool BehaviorManager::setBehaviorEnabled(StaticANIObject *obj, int aniId, int quId, int flag) {
+ warning("STUB: BehaviorManager::setBehaviorEnabled()");
+
+ return true;
+}
+
+void BehaviorManager::setFlagByStaticAniObject(StaticANIObject *ani, int flag) {
+ for (uint i = 0; i < _behaviors.size(); i++) {
+ BehaviorInfo *beh = _behaviors[i];
+
+ if (ani == beh->_ani) {
+ if (flag)
+ beh->_flags &= 0xfe;
+ else
+ beh->_flags |= 1;
+ }
+ }
+}
+
+void BehaviorInfo::clear() {
+ _ani = 0;
+ _staticsId = 0;
+ _counter = 0;
+ _counterMax = 0;
+ _flags = 0;
+ _subIndex = 0;
+ _itemsCount = 0;
+
+ _bheItems.clear();
+}
+
+void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) {
+ debug(0, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName));
+
+ clear();
+ _itemsCount = 1;
+ _counterMax = -1;
+
+ BehaviorEntry *bi = new BehaviorEntry();
+
+ _bheItems.push_back(bi);
+
+ bi->_itemsCount = var->getSubVarsCount();
+
+ bi->_items = (BehaviorEntryInfo**)calloc(bi->_itemsCount, sizeof(BehaviorEntryInfo *));
+
+ for (int i = 0; i < bi->_itemsCount; i++) {
+ int delay;
+ bi->_items[i] = new BehaviorEntryInfo(var->getSubVarByIndex(i), sc, &delay);
+
+ if (bi->_items[i]->_delay <_counterMax)
+ _counterMax = bi->_items[i]->_delay;
+ }
+}
+
+void BehaviorInfo::initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani) {
+ debug(0, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName));
+
+ clear();
+
+ _itemsCount = var->getSubVarsCount();
+ _counterMax = -1;
+
+ while (var->_varType == 2) {
+ if (strcmp(var->_value.stringValue, "ROOT"))
+ break;
+
+ GameVar *v1 = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("BEHAVIOR")->getSubVarByName(ani->getName());
+ if (v1 == var)
+ return;
+
+ sc = g_fullpipe->accessScene(ani->_sceneId);
+ clear();
+ var = v1;
+ _itemsCount = var->getSubVarsCount();
+ _counterMax = -1;
+ }
+
+ for (int i = 0; i < _itemsCount; i++) {
+ int maxDelay = 0;
+
+ _bheItems.push_back(new BehaviorEntry(var->getSubVarByIndex(i), sc, ani, &maxDelay));
+
+ if (maxDelay < _counterMax)
+ _counterMax = maxDelay;
+ }
+}
+
+BehaviorEntry::BehaviorEntry() {
+ _staticsId = 0;
+ _itemsCount = 0;
+ _flags = 0;
+ _items = 0;
+}
+
+BehaviorEntry::BehaviorEntry(GameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay) {
+ _staticsId = 0;
+ _itemsCount = 0;
+
+ *minDelay = 100000000;
+
+ int totalPercent = 0;
+ _flags = 0;
+ _items = 0;
+
+ Statics *st = ani->getStaticsByName(var->_varName);
+ if (st)
+ _staticsId = st->_staticsId;
+
+ _itemsCount = var->getSubVarsCount();
+ if (_itemsCount) {
+ _items = (BehaviorEntryInfo**)calloc(_itemsCount, sizeof(BehaviorEntryInfo *));
+
+ for (int i = 0; i < _itemsCount; i++) {
+ GameVar *subvar = var->getSubVarByIndex(i);
+ int delay = 0;
+
+ _items[i] = new BehaviorEntryInfo(subvar, sc, &delay);
+ totalPercent += delay;
+
+ if (_items[i]->_delay < *minDelay)
+ *minDelay = _items[i]->_delay;
+ }
+
+ if (!*minDelay && totalPercent == 1000)
+ _flags |= 1;
+ }
+}
+
+BehaviorEntryInfo::BehaviorEntryInfo(GameVar *subvar, Scene *sc, int *delay) {
+ _messageQueue = 0;
+ _delay = 0;
+ _percent = 0;
+ _flags = 0;
+ _messageQueue = sc->getMessageQueueByName(subvar->_varName);
+
+ GameVar *vart = subvar->getSubVarByName("dwDelay");
+ if (vart)
+ _delay = vart->_value.intValue;
+
+ *delay = 0;
+ vart = subvar->getSubVarByName("dwPercent");
+ if (vart) {
+ _percent = 0x7FFF * vart->_value.intValue / 1000;
+ *delay = vart->_value.intValue;
+ }
+
+ vart = subvar->getSubVarByName("dwFlags");
+ if (vart && vart->_varType == 2 && strstr(vart->_value.stringValue, "QDESC_AUTOSTART"))
+ _flags |= 2;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/behavior.h b/engines/fullpipe/behavior.h
new file mode 100644
index 0000000000..1ac0b5bbfe
--- /dev/null
+++ b/engines/fullpipe/behavior.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.
+ *
+ */
+
+#ifndef FULLPIPE_BEHAVIOR_H
+#define FULLPIPE_BEHAVIOR_H
+
+namespace Fullpipe {
+
+struct BehaviorEntryInfo {
+ MessageQueue *_messageQueue;
+ int _delay;
+ uint32 _percent;
+ int _flags;
+
+ BehaviorEntryInfo(GameVar *subvar, Scene *sc, int *delay);
+};
+
+struct BehaviorEntry {
+ int _staticsId;
+ int _itemsCount;
+ int _flags;
+ BehaviorEntryInfo **_items;
+
+ BehaviorEntry();
+ BehaviorEntry(GameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay);
+};
+
+struct BehaviorInfo {
+ StaticANIObject *_ani;
+ int _staticsId;
+ int _counter;
+ int _counterMax;
+ int _flags;
+ int _subIndex;
+ int _itemsCount;
+ Common::Array<BehaviorEntry *> _bheItems;
+
+ BehaviorInfo() { clear(); }
+
+ void clear();
+ void initAmbientBehavior(GameVar *var, Scene *sc);
+ void initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani);
+};
+
+class BehaviorManager : public CObject {
+ Common::Array<BehaviorInfo *> _behaviors;
+ Scene *_scene;
+ bool _isActive;
+
+ public:
+ BehaviorManager();
+ ~BehaviorManager();
+
+ void clear();
+
+ void initBehavior(Scene *scene, GameVar *var);
+
+ void updateBehaviors();
+ void updateBehavior(BehaviorInfo *behaviorInfo, BehaviorEntry *entry);
+ void updateStaticAniBehavior(StaticANIObject *ani, int delay, BehaviorEntry *beh);
+
+ bool setBehaviorEnabled(StaticANIObject *obj, int aniId, int quId, int flag);
+
+ void setFlagByStaticAniObject(StaticANIObject *ani, int flag);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_BEHAVIOR_H */
diff --git a/engines/fullpipe/configure.engine b/engines/fullpipe/configure.engine
new file mode 100644
index 0000000000..fce5951e26
--- /dev/null
+++ b/engines/fullpipe/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine fullpipe "Full Pipe" no
diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h
new file mode 100644
index 0000000000..e1ec51a947
--- /dev/null
+++ b/engines/fullpipe/constants.h
@@ -0,0 +1,296 @@
+/* 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 FULLPIPE_CONSTANTS_H
+#define FULLPIPE_CONSTANTS_H
+
+namespace Fullpipe {
+
+#define ANI_BIGBALL 4923
+#define ANI_BOOT_1 4231
+#define ANI_BUTTON 598
+#define ANI_CLOCK 588
+#define ANI_DOMINO_3 2732
+#define ANI_DADAYASHIK 306
+#define ANI_EGGEATER 334
+#define ANI_HAND 601
+#define ANI_IN1MAN 5110
+#define ANI_INV_COIN 875
+#define ANI_INV_EGGAPL 1564
+#define ANI_INV_EGGBOOT 1570
+#define ANI_INV_EGGCOIN 1567
+#define ANI_INV_EGGDOM 1561
+#define ANI_INV_EGGGLS 1573
+#define ANI_INV_MAP 5321
+#define ANI_KOZAWKA 495
+#define ANI_LIFTBUTTON 2751
+#define ANI_MAMASHA_4 660
+#define ANI_MAN 322
+#define ANI_PLANK 501
+#define ANI_SC2_BOX 1020
+#define ANI_SC4_BOOT 1035
+#define ANI_SC4_COIN 690
+#define ANI_SPEAKER_4 3275
+#define ANI_SPRING 542
+#define MSG_CLICKBOTTLE 569
+#define MSG_CLICKBUTTON 609
+#define MSG_CLICKPLANK 549
+#define MSG_CMN_WINARCADE 4778
+#define MSG_DISABLESAVES 5201
+#define MSG_ENABLESAVES 5202
+#define MSG_HMRKICK_METAL 4764
+#define MSG_HMRKICK_STUCCO 4765
+#define MSG_INTR_ENDINTRO 5139
+#define MSG_INTR_GETUPMAN 5135
+#define MSG_INTR_SWITCHTO1 5145
+#define MSG_INTR_SWITCHTO2 5134
+#define MSG_KOZAWRESTART 546
+#define MSG_LIFT_CLICKBUTTON 2780
+#define MSG_LIFT_CLOSEDOOR 5194
+#define MSG_LIFT_EXITLIFT 5187
+#define MSG_LIFT_GO 1065
+#define MSG_LIFT_STARTEXITQUEUE 5186
+#define MSG_LOWERPLANK 540
+#define MSG_MANSHADOWSOFF 5196
+#define MSG_MANSHADOWSON 5197
+#define MSG_RAISEPLANK 547
+#define MSG_RESTARTGAME 4767
+#define MSG_SC1_SHOWOSK 1019
+#define MSG_SC1_SHOWOSK2 468
+#define MSG_SC1_UTRUBACLICK 1100
+#define MSG_SC2_HIDELADDER 1023
+#define MSG_SC2_LADDERCLICK 1101
+#define MSG_SC2_PUTMANUP 1026
+#define MSG_SC2_SHOWLADDER 1027
+#define MSG_SC3_HIDEDOMINO 3177
+#define MSG_SC3_ONTAKECOIN 5338
+#define MSG_SC3_RELEASEEGG 2681
+#define MSG_SC3_TAKEEGG 1583
+#define MSG_SC3_TESTFAT 1582
+#define MSG_SC3_UTRUBACLICK 1103
+#define MSG_SC4_COINOUT 2895
+#define MSG_SC4_COINPUT 1032
+#define MSG_SC4_CLICKLADDER 1439
+#define MSG_SC4_DROPBOTTLE 2896
+#define MSG_SC4_HANDOVER 2960
+#define MSG_SC4_HIDEBOOT 4563
+#define MSG_SC4_KOZAWFALL 2858
+#define MSG_SC4_MANFROMBOTTLE 2854
+#define MSG_SC4_MANTOBOTTLE 2852
+#define PIC_SC4_LADDER 1438
+#define MSG_GOTOLADDER 618
+#define MSG_SHAKEBOTTLE 584
+#define MSG_SHOOTKOZAW 557
+#define MSG_SHOWCOIN 1033
+#define MSG_STARTHAND 612
+#define MSG_TAKEBOTTLE 614
+#define MSG_TAKEKOZAW 611
+#define MSG_TESTPLANK 538
+#define MSG_UPDATEBOTTLE 613
+#define MV_EGTR_FATASK 5332
+#define MV_IN1MAN_SLEEP 5111
+#define MV_KZW_JUMP 558
+#define MV_KZW_JUMPROTATE 561
+#define MV_BDG_OPEN 1379
+#define MV_BTN_CLICK 599
+#define MV_CLK_GO 589
+#define MV_HND_POINT 602
+#define MV_MAN_GOD 481
+#define MV_MAN_GOLADDER 451
+#define MV_MAN_GOLADDER2 2844
+#define MV_MAN_GOU 460
+#define MV_MAN_LOOKUP 4773
+#define MV_MAN_STARTLADDER 452
+#define MV_MAN_STARTLADDER2 2842
+#define MV_MAN_STOPLADDER 454
+#define MV_MAN_STOPLADDER2 2845
+#define MV_MAN_TOLADDER 448
+#define MV_MAN_TOLADDER2 2841
+#define MV_MAN_TURN_LU 486
+#define MV_PNK_WEIGHTLEFT 541
+#define MV_PNK_WEIGHTRIGHT 502
+#define MV_SC4_COIN_default 1029
+#define MV_SPK4_PLAY 3276
+#define PIC_CMN_EVAL 3468
+#define PIC_CSR_DEFAULT 4891
+#define PIC_CSR_DEFAULT_INV 4892
+#define PIC_CSR_ITN 4893
+#define PIC_CSR_ITN_INV 4894
+#define PIC_CSR_GOFAR_L 4895
+#define PIC_CSR_GOFAR_R 4896
+#define PIC_CSR_ARCADE1 4901
+#define PIC_CSR_ARCADE2 4902
+#define PIC_CSR_ARCADE2_D 4903
+#define PIC_CSR_ARCADE3 4904
+#define PIC_CSR_ARCADE4 4905
+#define PIC_CSR_ARCADE5 4906
+#define PIC_CSR_ARCADE6 4907
+#define PIC_CSR_ARCADE6_D 4908
+#define PIC_CSR_ARCADE7 4909
+#define PIC_CSR_ARCADE7_D 4910
+#define PIC_CSR_ARCADE8 4911
+#define PIC_CSR_DEFAULT 4891
+#define PIC_CSR_DEFAULT_INV 4892
+#define PIC_CSR_GOD 4900
+#define PIC_CSR_GOFAR_L 4895
+#define PIC_CSR_GOFAR_R 4896
+#define PIC_CSR_GOL 4897
+#define PIC_CSR_GOR 4898
+#define PIC_CSR_GOU 4899
+#define PIC_CSR_HELPERBGR 5331
+#define PIC_CSR_ITN 4893
+#define PIC_CSR_ITN_GREEN 5330
+#define PIC_CSR_ITN_INV 4894
+#define PIC_CSR_ITN_RED 5329
+#define PIC_CSR_LIFT 5176
+#define PIC_CSR_MAP 5339
+#define PIC_IN1_GAMETITLE 5169
+#define PIC_IN1_PIPETITLE 5167
+#define PIC_INV_MENU 991
+#define PIC_MAP_A13 5275
+#define PIC_MAP_S01 5223
+#define PIC_SC1_KUCHKA 1321
+#define PIC_SC1_LADDER 1091
+#define PIC_SC1_OSK 1018
+#define PIC_SC1_OSK2 2932
+#define PIC_SC2_DTRUBA 841
+#define PIC_SC2_LADDER 412
+#define PIC_SC3_DOMIN 5182
+#define PIC_SC3_LADDER 1102
+#define PIC_SC4_BOTTLE 568
+#define PIC_SC4_BOTTLE2 2936
+#define PIC_SC4_DOWNTRUBA 619
+#define PIC_SC4_LADDER 1438
+#define PIC_SC4_LRTRUBA 616
+#define PIC_SC4_MASK 585
+#define PIC_SC4_PLANK 5183
+#define PIC_SCD_SEL 734
+#define QU_EGTR_MD2_SHOW 4698
+#define QU_EGTR_MD1_SHOW 4697
+#define QU_EGTR_SLIMSHOW 4883
+#define QU_IN2_DO 5144
+#define QU_INTR_FINISH 5138
+#define QU_INTR_GETUPMAN 5136
+#define QU_INTR_STARTINTRO 5133
+#define QU_KOZAW_WALK 505
+#define QU_PNK_CLICK 550
+#define QU_SC3_ENTERLIFT 2779
+#define QU_SC3_EXITLIFT 2808
+#define QU_SC4_MANFROMBOTTLE 2851
+#define SC_1 301
+#define SC_10 653
+#define SC_11 654
+#define SC_12 655
+#define SC_13 1137
+#define SC_14 1138
+#define SC_15 1139
+#define SC_16 1140
+#define SC_17 1141
+#define SC_18 1142
+#define SC_19 1143
+#define SC_2 302
+#define SC_20 1144
+#define SC_21 1546
+#define SC_22 1547
+#define SC_23 1548
+#define SC_24 1549
+#define SC_25 1550
+#define SC_26 1551
+#define SC_27 1552
+#define SC_28 2062
+#define SC_29 2063
+#define SC_3 303
+#define SC_30 2064
+#define SC_31 2065
+#define SC_32 2066
+#define SC_33 2067
+#define SC_34 2068
+#define SC_35 2069
+#define SC_36 2070
+#define SC_37 2071
+#define SC_38 2072
+#define SC_4 304
+#define SC_5 305
+#define SC_6 649
+#define SC_7 650
+#define SC_8 651
+#define SC_9 652
+#define SC_COMMON 321
+#define SC_DBGMENU 726
+#define SC_FINAL1 4999
+#define SC_FINAL2 5000
+#define SC_FINAL3 5001
+#define SC_FINAL4 2460
+#define SC_INTRO1 3896
+#define SC_INTRO2 3907
+#define SC_INV 858
+#define SC_LDR 635
+#define SC_MAINMENU 4620
+#define SC_MAP 5222
+#define SC_TEST 903
+#define SC_TITLES 5166
+#define SND_4_010 3125
+#define SND_4_012 3127
+#define SND_4_033 4990
+#define SND_CMN_031 3516
+#define SND_CMN_070 5199
+#define SND_INTR_019 5220
+#define ST_CLK_CLOSED 590
+#define ST_DYAS_LIES 318
+#define ST_EGTR_MID1 2863
+#define ST_EGTR_MID2 2869
+#define ST_EGTR_SLIM 336
+#define ST_HND_EMPTY 603
+#define ST_IN1MAN_SLEEP 5112
+#define ST_KZW_EMPTY 498
+#define ST_LBN_0N 2832
+#define ST_LBN_0P 2833
+#define ST_LBN_1N 2753
+#define ST_LBN_1P 2754
+#define ST_LBN_2N 2756
+#define ST_LBN_2P 2757
+#define ST_LBN_3N 2759
+#define ST_LBN_3P 2760
+#define ST_LBN_4N 2762
+#define ST_LBN_4P 2763
+#define ST_LBN_5N 2765
+#define ST_LBN_5P 2766
+#define ST_LBN_6N 2768
+#define ST_LBN_6P 2769
+#define ST_LBN_7N 2771
+#define ST_LBN_7P 2772
+#define ST_LBN_8N 2774
+#define ST_LBN_8P 2775
+#define ST_LBN_9N 2777
+#define ST_LBN_9P 2778
+#define ST_MAN_EMPTY 476
+#define ST_MAN_RIGHT 325
+#define ST_MAN_SIT 1164
+#define TrubaDown 697
+#define TrubaLeft 474
+#define TrubaRight 696
+#define TrubaUp 680
+#define rMV_MAN_LOOKUP 4775
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_CONSTANTS_H */
diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp
new file mode 100644
index 0000000000..8c4a422333
--- /dev/null
+++ b/engines/fullpipe/detection.cpp
@@ -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.
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+#include "common/file.h"
+
+#include "fullpipe/fullpipe.h"
+
+
+namespace Fullpipe {
+
+const char *FullpipeEngine::getGameId() const {
+ return _gameDescription->gameid;
+}
+
+}
+
+static const PlainGameDescriptor fullpipeGames[] = {
+ {"fullpipe", "Full Pipe"},
+ {0, 0}
+};
+
+namespace Fullpipe {
+
+static const ADGameDescription gameDescriptions[] = {
+
+ // Fullpipe Russian version
+ {
+ "fullpipe",
+ 0,
+ AD_ENTRY1s("0654.sc2", "099f54f86d33ad2395f3b854b7e05058", 2272),
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ ADGF_DROPPLATFORM,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Fullpipe German version
+ {
+ "fullpipe",
+ 0,
+ AD_ENTRY1s("0654.sc2", "d8743351fc53d205f42d91f6d791e51b", 2272),
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ ADGF_DROPPLATFORM,
+ GUIO1(GUIO_NONE)
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+} // End of namespace Fullpipe
+
+class FullpipeMetaEngine : public AdvancedMetaEngine {
+public:
+ FullpipeMetaEngine() : AdvancedMetaEngine(Fullpipe::gameDescriptions, sizeof(ADGameDescription), fullpipeGames) {
+ _singleid = "fullpipe";
+ }
+
+ virtual const char *getName() const {
+ return "Fullpipe Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Fullpipe Engine (C) Pipe Studio";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+};
+
+bool FullpipeMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+}
+
+bool Fullpipe::FullpipeEngine::hasFeature(EngineFeature f) const {
+ return false;
+}
+
+bool FullpipeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new Fullpipe::FullpipeEngine(syst, desc);
+ }
+ return desc != 0;
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(FULLPIPE)
+ REGISTER_PLUGIN_DYNAMIC(FULLPIPE, PLUGIN_TYPE_ENGINE, FullpipeMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(FULLPIPE, PLUGIN_TYPE_ENGINE, FullpipeMetaEngine);
+#endif
diff --git a/engines/fullpipe/floaters.cpp b/engines/fullpipe/floaters.cpp
new file mode 100644
index 0000000000..384bfa2150
--- /dev/null
+++ b/engines/fullpipe/floaters.cpp
@@ -0,0 +1,45 @@
+/* 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 "fullpipe/fullpipe.h"
+#include "fullpipe/floaters.h"
+
+namespace Fullpipe {
+
+void Floaters::init(GameVar *var) {
+ warning("STUB: Floaters::init()");
+}
+
+void Floaters::genFlies(Scene *sc, int x, int y, int a5, int a6) {
+ warning("STUB: Floaters::genFlies()");
+}
+
+void Floaters::update() {
+ warning("STUB: Floaters::update()");
+}
+
+void Floaters::stopAll() {
+ warning("STUB: Floaters::stopAll()");
+}
+
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/floaters.h b/engines/fullpipe/floaters.h
new file mode 100644
index 0000000000..a4d64dd79d
--- /dev/null
+++ b/engines/fullpipe/floaters.h
@@ -0,0 +1,67 @@
+/* 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 FULLPIPE_FLOATERS_H
+#define FULLPIPE_FLOATERS_H
+
+namespace Fullpipe {
+
+class StaticANIObject;
+class Scene;
+
+struct FloaterArray1 {
+ int val1;
+ int val2;
+};
+
+struct FloaterArray2 {
+ StaticANIObject *ani;
+ int val2;
+ int val3;
+ int val4;
+ int val5;
+ int val6;
+ int val7;
+ int val8;
+ double val9;
+ double val11;
+ int val13;
+ int countdown;
+ int val15;
+ int fflags;
+};
+
+class Floaters {
+public:
+ //HRGN hRgn;
+ Common::Array<FloaterArray1 *> _array1;
+ Common::Array<FloaterArray2 *> _array2;
+
+ void init(GameVar *var);
+ void genFlies(Scene *sc, int x, int y, int a5, int a6);
+ void update();
+ void stopAll();
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_FLOATERS_H */
diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp
new file mode 100644
index 0000000000..7dedaf3109
--- /dev/null
+++ b/engines/fullpipe/fullpipe.cpp
@@ -0,0 +1,451 @@
+/* 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 "common/archive.h"
+#include "common/config-manager.h"
+
+#include "engines/util.h"
+
+#include "fullpipe/fullpipe.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/behavior.h"
+#include "fullpipe/modal.h"
+#include "fullpipe/input.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/floaters.h"
+
+namespace Fullpipe {
+
+FullpipeEngine *g_fullpipe = 0;
+Vars *g_vars = 0;
+
+FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+ // Setup mixer
+ if (!_mixer->isReady()) {
+ warning("Sound initialization failed.");
+ }
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+
+ _rnd = new Common::RandomSource("fullpipe");
+
+ _gameProjectVersion = 0;
+ _pictureScale = 8;
+ _scrollSpeed = 0;
+ _currSoundListCount = 0;
+ _globalPalette = 0;
+
+ _updateTicks = 0;
+ _lastInputTicks = 0;
+ _lastButtonUpTicks = 0;
+
+ _currArchive = 0;
+
+ _soundEnabled = true;
+ _flgSoundList = true;
+
+ _sfxVolume = 0;
+
+ _inputController = 0;
+ _inputDisabled = false;
+
+ _normalSpeed = true;
+
+ _currentCheat = -1;
+ _currentCheatPos = 0;
+
+ _modalObject = 0;
+
+ _gameContinue = true;
+ _needRestart = false;
+ _flgPlayIntro = true;
+ _gamePaused = false;
+ _inputArFlag = false;
+ _recordEvents = false;
+
+ _flgGameIsRunning = true;
+
+ _isProcessingMessages = false;
+
+ _musicAllowed = -1;
+
+ _aniMan = 0;
+ _aniMan2 = 0;
+ _currentScene = 0;
+ _scene2 = 0;
+ _movTable = 0;
+ _floaters = 0;
+
+ _globalMessageQueueList = 0;
+ _messageHandlers = 0;
+
+ _updateScreenCallback = 0;
+ _updateCursorCallback = 0;
+
+ _msgX = 0;
+ _msgY = 0;
+ _msgObjectId2 = 0;
+ _msgId = 0;
+ _mouseVirtX = 0;
+ _mouseVirtY = 0;
+
+ _currSelectedInventoryItemId = 0;
+
+ _behaviorManager = 0;
+
+ _cursorId = 0;
+
+ _keyState = Common::KEYCODE_INVALID;
+ _buttonState = 0;
+
+ _gameLoader = 0;
+ _gameProject = 0;
+
+ _updateFlag = true;
+ _flgCanOpenMap = true;
+
+ _sceneWidth = 1;
+ _sceneHeight = 1;
+
+ for (int i = 0; i < 11; i++)
+ _currSoundList1[i] = 0;
+
+ for (int i = 0; i < 200; i++)
+ _mapTable[i] = 0;
+
+ _inventoryScene = 0;
+ _inventory = 0;
+
+ _minCursorId = 0xffff;
+ _maxCursorId = 0;
+ _objectAtCursor = 0;
+ _objectIdAtCursor = 0;
+
+ _isSaveAllowed = true;
+
+ g_fullpipe = this;
+ g_vars = new Vars;
+}
+
+FullpipeEngine::~FullpipeEngine() {
+ delete _rnd;
+ delete _globalMessageQueueList;
+}
+
+void FullpipeEngine::initialize() {
+ _globalMessageQueueList = new GlobalMessageQueueList;
+ _behaviorManager = new BehaviorManager;
+
+ _sceneRect.left = 0;
+ _sceneRect.top = 0;
+ _sceneRect.right = 799;
+ _sceneRect.bottom = 599;
+
+ _floaters = new Floaters;
+}
+
+Common::Error FullpipeEngine::run() {
+ const Graphics::PixelFormat format(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ // Initialize backend
+ initGraphics(800, 600, true, &format);
+
+ _backgroundSurface.create(800, 600, format);
+
+ initialize();
+
+ _isSaveAllowed = false;
+
+ int scene = 0;
+ if (ConfMan.hasKey("boot_param"))
+ scene = convertScene(ConfMan.getInt("boot_param"));
+
+ if (!loadGam("fullpipe.gam", scene))
+ return Common::kNoGameDataFoundError;
+
+#if 0
+ loadAllScenes();
+#endif
+
+ _gameContinue = true;
+
+ while (_gameContinue) {
+ updateEvents();
+
+ updateScreen();
+
+ if (_needRestart) {
+ if (_modalObject) {
+ delete _modalObject;
+ _modalObject = 0;
+ }
+
+ freeGameLoader();
+ _currentScene = 0;
+ _updateTicks = 0;
+
+ loadGam("fullpipe.gam");
+ _needRestart = false;
+ }
+
+ if (_normalSpeed)
+ _system->delayMillis(10);
+ _system->updateScreen();
+ }
+
+ freeGameLoader();
+
+ cleanup();
+
+ return Common::kNoError;
+}
+
+void FullpipeEngine::updateEvents() {
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ ExCommand *ex;
+
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _keyState = event.kbd.keycode;
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_SPACE:
+ if (_gamePaused) {
+ if (_modalObject) {
+ if (_modalObject->init(42)) {
+ _modalObject->update();
+ } else {
+ _modalObject->saveload();
+ BaseModalObject *obj = _modalObject->_parentObj;
+ if (obj)
+ delete _modalObject;
+ _modalObject = obj;
+ }
+ } else {
+ _gameLoader->updateSystems(42);
+ }
+ return;
+ }
+
+ ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = 32;
+ ex->_excFlags |= 3;
+ ex->handle();
+ break;
+ case Common::KEYCODE_s:
+ if (_gamePaused) {
+ _gamePaused = 0;
+ _flgGameIsRunning = true;
+ return;
+ }
+
+ ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = event.kbd.keycode;
+ ex->_excFlags |= 3;
+ ex->handle();
+ break;
+ case Common::KEYCODE_q:
+ return;
+ break;
+ default:
+ ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = event.kbd.keycode;
+ ex->_excFlags |= 3;
+ ex->handle();
+ break;
+ }
+ break;
+ case Common::EVENT_KEYUP:
+ if (!_inputArFlag) {
+ ex = new ExCommand(0, 17, 37, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ ex->handle();
+ }
+ _keyState = Common::KEYCODE_INVALID;
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ if (_recordEvents) {
+ ex = new ExCommand(0, 17, 31, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ ex->handle();
+ }
+
+ _mouseScreenPos = event.mouse;
+ break;
+ case Common::EVENT_QUIT:
+ _gameContinue = false;
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) {
+ ex = new ExCommand(0, 17, 107, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ _lastInputTicks = _updateTicks;
+ ex->handle();
+ }
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) {
+ ex = new ExCommand(0, 17, 29, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0);
+
+ ex->_sceneClickX = _sceneRect.left + ex->_x;
+ ex->_sceneClickY = _sceneRect.top + ex->_y;
+ ex->_keyCode = getGameLoaderInventory()->getSelectedItemId();
+ ex->_excFlags |= 3;
+ _lastInputTicks = _updateTicks;
+ ex->handle();
+ }
+ break;
+ case Common::EVENT_LBUTTONUP:
+ if (!_inputArFlag && (_updateTicks - _lastButtonUpTicks) >= 2) {
+ ex = new ExCommand(0, 17, 30, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ _lastButtonUpTicks = _updateTicks;
+ ex->handle();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+
+#if 0
+ warning("STUB: FullpipeEngine::updateEvents() <mainWindowProc>");
+ if (Msg == MSG_SC11_SHOWSWING && _modalObject) {
+ _modalObject->method14();
+ }
+#endif
+}
+
+void FullpipeEngine::freeGameLoader() {
+ warning("STUB: FullpipeEngine::freeGameLoader()");
+}
+
+void FullpipeEngine::cleanup() {
+ warning("STUB: FullpipeEngine::cleanup()");
+}
+
+void FullpipeEngine::updateScreen() {
+ debug(4, "FullpipeEngine::updateScreen()");
+
+ _mouseVirtX = _mouseScreenPos.x + _sceneRect.left;
+ _mouseVirtY = _mouseScreenPos.y + _sceneRect.top;
+
+ //if (inputArFlag)
+ // updateGame_inputArFlag();
+
+ if (_modalObject || (_flgGameIsRunning && (_gameLoader->updateSystems(42), _modalObject != 0))) {
+ if (_flgGameIsRunning) {
+ if (_modalObject->init(42)) {
+ _modalObject->update();
+ } else {
+ _modalObject->saveload();
+ BaseModalObject *tmp = _modalObject->_parentObj;
+
+ delete _modalObject;
+
+ _modalObject = tmp;
+ }
+ }
+ } else if (_currentScene) {
+ _currentScene->draw();
+
+ if (_inventoryScene)
+ _inventory->draw();
+
+ if (_updateScreenCallback)
+ _updateScreenCallback();
+
+ //if (inputArFlag && _currentScene) {
+ // vrtTextOut(*(_DWORD *)g_vrtHandle, smallNftData, "DEMO", 4, 380, 580);
+ // vrtTextOut(*(_DWORD *)g_vrtHandle, smallNftData, "Alt+F4 - exit", 14, 695, 580);
+ //}
+ } else {
+ //vrtRectangle(*(_DWORD *)g_vrtHandle, 0, 0, 0, 800, 600);
+ }
+ _inputController->drawCursor(_mouseScreenPos.x, _mouseScreenPos.y);
+
+ ++_updateTicks;
+}
+
+int FullpipeEngine::getObjectEnumState(const char *name, const char *state) {
+ GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
+
+ if (!var) {
+ var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0);
+ }
+
+ var = var->getSubVarByName(name);
+ if (var) {
+ var = var->getSubVarByName("ENUMSTATES");
+ if (var)
+ return var->getSubVarAsInt(state);
+ }
+
+ return 0;
+}
+
+int FullpipeEngine::getObjectState(const char *objname) {
+ GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
+
+ if (var)
+ return var->getSubVarAsInt(objname);
+
+ return 0;
+}
+
+void FullpipeEngine::setObjectState(const char *name, int state) {
+ GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
+
+ if (!var) {
+ var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0);
+ }
+
+ var->setSubVarAsInt(name, state);
+}
+
+void FullpipeEngine::updateMapPiece(int mapId, int update) {
+ for (int i = 0; i < 200; i++) {
+ int hiWord = (_mapTable[i] >> 16) & 0xffff;
+
+ if (hiWord == mapId) {
+ _mapTable[i] |= update;
+ return;
+ }
+ if (!hiWord) {
+ _mapTable[i] = (mapId << 16) | update;
+ return;
+ }
+ }
+}
+
+void FullpipeEngine::disableSaves(ExCommand *ex) {
+ warning("STUB: FullpipeEngine::disableSaves()");
+}
+
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h
new file mode 100644
index 0000000000..63dde5042b
--- /dev/null
+++ b/engines/fullpipe/fullpipe.h
@@ -0,0 +1,262 @@
+/* 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 FULLPIPE_FULLPIPE_H
+#define FULLPIPE_FULLPIPE_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/system.h"
+
+#include "audio/mixer.h"
+
+#include "graphics/surface.h"
+
+#include "engines/engine.h"
+
+struct ADGameDescription;
+
+namespace Fullpipe {
+
+enum FullpipeGameFeatures {
+};
+
+class BehaviorManager;
+class BaseModalObject;
+class GameLoader;
+class GameVar;
+class InputController;
+class Inventory2;
+struct CursorInfo;
+struct EntranceInfo;
+class ExCommand;
+class Floaters;
+class GameProject;
+class GameObject;
+class GlobalMessageQueueList;
+struct MessageHandler;
+struct MovTable;
+class NGIArchive;
+class Scene;
+class SoundList;
+class StaticANIObject;
+class Vars;
+
+int global_messageHandler1(ExCommand *cmd);
+int global_messageHandler2(ExCommand *cmd);
+int global_messageHandler3(ExCommand *cmd);
+int global_messageHandler4(ExCommand *cmd);
+void global_messageHandler_handleSound(ExCommand *cmd);
+
+
+class FullpipeEngine : public ::Engine {
+protected:
+
+ Common::Error run();
+
+public:
+ FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc);
+ virtual ~FullpipeEngine();
+
+ void initialize();
+
+ void setMusicAllowed(int val) { _musicAllowed = val; }
+
+ // Detection related functions
+ const ADGameDescription *_gameDescription;
+ const char *getGameId() const;
+ Common::Platform getPlatform() const;
+ bool hasFeature(EngineFeature f) const;
+
+ Common::RandomSource *_rnd;
+
+ Common::KeyCode _keyState;
+ uint16 _buttonState;
+
+ void updateEvents();
+
+ Graphics::Surface _backgroundSurface;
+
+ GameLoader *_gameLoader;
+ GameProject *_gameProject;
+ bool loadGam(const char *fname, int scene = 0);
+
+ GameVar *getGameLoaderGameVar();
+ InputController *getGameLoaderInputController();
+
+ int _gameProjectVersion;
+ int _pictureScale;
+ int _scrollSpeed;
+ bool _updateFlag;
+ bool _flgCanOpenMap;
+ bool _gamePaused;
+ bool _flgGameIsRunning;
+ bool _inputArFlag;
+ bool _recordEvents;
+
+ Common::Rect _sceneRect;
+ int _sceneWidth;
+ int _sceneHeight;
+ Scene *_currentScene;
+ Scene *_scene2;
+ StaticANIObject *_aniMan;
+ StaticANIObject *_aniMan2;
+ byte *_globalPalette;
+
+ InputController *_inputController;
+ bool _inputDisabled;
+
+ int _currentCheat;
+ int _currentCheatPos;
+
+ void defHandleKeyDown(int key);
+
+ SoundList *_currSoundList1[11];
+ int _currSoundListCount;
+ bool _soundEnabled;
+ bool _flgSoundList;
+
+ void stopAllSounds();
+ void toggleMute();
+ void playSound(int id, int flag);
+ void startSceneTrack();
+
+ int _sfxVolume;
+
+ GlobalMessageQueueList *_globalMessageQueueList;
+ MessageHandler *_messageHandlers;
+
+ int _msgX;
+ int _msgY;
+ int _msgObjectId2;
+ int _msgId;
+
+ Common::List<ExCommand *> _exCommandList;
+ bool _isProcessingMessages;
+
+ int _mouseVirtX;
+ int _mouseVirtY;
+ Common::Point _mouseScreenPos;
+
+ BehaviorManager *_behaviorManager;
+
+ MovTable *_movTable;
+
+ Floaters *_floaters;
+
+ void initMap();
+ void updateMapPiece(int mapId, int update);
+ void updateScreen();
+
+ void freeGameLoader();
+ void cleanup();
+
+ bool _gameContinue;
+ bool _needRestart;
+ bool _flgPlayIntro;
+ int _musicAllowed;
+ bool _normalSpeed;
+
+ void enableSaves() { _isSaveAllowed = true; }
+ void disableSaves(ExCommand *ex);
+
+ void initObjectStates();
+ void setLevelStates();
+ void setSwallowedEggsState();
+ void loadAllScenes();
+
+ void initCursors();
+ void addCursor(CursorInfo *cursorInfo, Scene *inv, int pictureId, int hotspotX, int hotspotY, int itemPictureOffsX, int itemPictureOffsY);
+
+ int32 _mapTable[200];
+
+ Scene *_inventoryScene;
+ Inventory2 *_inventory;
+ int _currSelectedInventoryItemId;
+
+ int32 _updateTicks;
+ int32 _lastInputTicks;
+ int32 _lastButtonUpTicks;
+
+ BaseModalObject *_modalObject;
+
+ int (*_updateScreenCallback)();
+ int (*_updateCursorCallback)();
+
+ int _cursorId;
+ int _minCursorId;
+ int _maxCursorId;
+ Common::Array<int> _objectIdCursors;
+ GameObject *_objectAtCursor;
+ int _objectIdAtCursor;
+
+ void setCursor(int id);
+ void updateCursorCommon();
+
+ int getObjectState(const char *objname);
+ void setObjectState(const char *name, int state);
+ int getObjectEnumState(const char *name, const char *state);
+
+ bool sceneSwitcher(EntranceInfo *entrance);
+ Scene *accessScene(int sceneId);
+ void setSceneMusicParameters(GameVar *var);
+ int convertScene(int scene);
+
+ NGIArchive *_currArchive;
+
+ void openMap();
+ void openHelp();
+ void openMainMenu();
+
+ void initArcadeKeys(const char *varname);
+ void winArcade();
+ void getAllInventory();
+
+ int lift_getButtonIdP(int objid);
+ void lift_setButton(const char *name, int state);
+ void lift_sub5(Scene *sc, int qu1, int qu2);
+ void lift_exitSeq(ExCommand *ex);
+ void lift_closedoorSeq();
+ void lift_animation3();
+ void lift_goAnimation();
+ void lift_sub1(StaticANIObject *ani);
+ void lift_startExitQueue();
+ void lift_sub05(ExCommand *ex);
+
+public:
+
+ bool _isSaveAllowed;
+
+ bool canLoadGameStateCurrently() { return _isSaveAllowed; }
+ bool canSaveGameStateCurrently() { return _isSaveAllowed; }
+
+};
+
+extern FullpipeEngine *g_fullpipe;
+extern Vars *g_vars;
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_FULLPIPE_H */
diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp
new file mode 100644
index 0000000000..a2ab71d7e3
--- /dev/null
+++ b/engines/fullpipe/gameloader.cpp
@@ -0,0 +1,513 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/input.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/motion.h"
+
+namespace Fullpipe {
+
+Inventory2 *getGameLoaderInventory() {
+ return &g_fullpipe->_gameLoader->_inventory;
+}
+
+MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId) {
+ for (uint i = 0; i < g_fullpipe->_gameLoader->_sc2array.size(); i++)
+ if (g_fullpipe->_gameLoader->_sc2array[i]._sceneId == sceneId)
+ return (MctlCompound *)g_fullpipe->_gameLoader->_sc2array[i]._motionController;
+
+ return 0;
+}
+
+InteractionController *getGameLoaderInteractionController() {
+ return g_fullpipe->_gameLoader->_interactionController;
+}
+
+GameLoader::GameLoader() {
+ _interactionController = new InteractionController();
+ _inputController = new InputController();
+
+ _gameProject = 0;
+ _gameName = 0;
+
+ addMessageHandlerByIndex(global_messageHandler2, 0, 0);
+ insertMessageHandler(global_messageHandler3, 0, 128);
+ insertMessageHandler(global_messageHandler4, 0, 1);
+
+ _field_FA = 0;
+ _field_F8 = 0;
+ _sceneSwitcher = 0;
+ _preloadCallback = 0;
+ _readSavegameCallback = 0;
+ _gameVar = 0;
+ _preloadSceneId = 0;
+ _preloadEntranceId = 0;
+ _updateCounter = 0;
+
+ g_fullpipe->_msgX = 0;
+ g_fullpipe->_msgY = 0;
+ g_fullpipe->_msgObjectId2 = 0;
+ g_fullpipe->_msgId = 0;
+}
+
+GameLoader::~GameLoader() {
+ free(_gameName);
+ delete _gameProject;
+ delete _interactionController;
+ delete _inputController;
+}
+
+bool GameLoader::load(MfcArchive &file) {
+ debug(5, "GameLoader::load()");
+
+ _gameName = file.readPascalString();
+ debug(6, "_gameName: %s", _gameName);
+
+ _gameProject = new GameProject();
+
+ _gameProject->load(file);
+
+ g_fullpipe->_gameProject = _gameProject;
+
+ if (g_fullpipe->_gameProjectVersion < 12) {
+ error("Old gameProjectVersion: %d", g_fullpipe->_gameProjectVersion);
+ }
+
+ _gameName = file.readPascalString();
+ debug(6, "_gameName: %s", _gameName);
+
+ _inventory.load(file);
+
+ _interactionController->load(file);
+
+ debug(6, "sceneTag count: %d", _gameProject->_sceneTagList->size());
+
+ _sc2array.resize(_gameProject->_sceneTagList->size());
+
+ int i = 0;
+ for (SceneTagList::const_iterator it = _gameProject->_sceneTagList->begin(); it != _gameProject->_sceneTagList->end(); ++it, i++) {
+ char tmp[12];
+
+ snprintf(tmp, 11, "%04d.sc2", it->_sceneId);
+
+ debug(2, "sc: %s", tmp);
+
+ _sc2array[i].loadFile((const char *)tmp);
+ }
+
+ _preloadItems.load(file);
+
+ _field_FA = file.readUint16LE();
+ _field_F8 = file.readUint16LE();
+
+ _gameVar = (GameVar *)file.readClass();
+
+ return true;
+}
+
+bool GameLoader::loadScene(int sceneId) {
+ SceneTag *st;
+
+ int idx = getSceneTagBySceneId(sceneId, &st);
+
+ if (idx < 0)
+ return false;
+
+ if (!st->_scene)
+ st->loadScene();
+
+ if (st->_scene) {
+ st->_scene->init();
+
+ applyPicAniInfos(st->_scene, _sc2array[idx]._defPicAniInfos, _sc2array[idx]._defPicAniInfosCount);
+ applyPicAniInfos(st->_scene, _sc2array[idx]._picAniInfos, _sc2array[idx]._picAniInfosCount);
+
+ _sc2array[idx]._scene = st->_scene;
+ _sc2array[idx]._isLoaded = 1;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool GameLoader::gotoScene(int sceneId, int entranceId) {
+ SceneTag *st;
+
+ int sc2idx = getSceneTagBySceneId(sceneId, &st);
+
+ if (sc2idx < 0)
+ return false;
+
+ if (!_sc2array[sc2idx]._isLoaded)
+ return false;
+
+ if (_sc2array[sc2idx]._entranceDataCount < 1) {
+ g_fullpipe->_currentScene = st->_scene;
+ return true;
+ }
+
+ if (_sc2array[sc2idx]._entranceDataCount <= 0)
+ return false;
+
+ int entranceIdx = 0;
+ if (sceneId != 726) // WORKAROUND
+ for (entranceIdx = 0; _sc2array[sc2idx]._entranceData[entranceIdx]->_field_4 != entranceId; entranceIdx++) {
+ if (entranceIdx >= _sc2array[sc2idx]._entranceDataCount)
+ return false;
+ }
+
+ GameVar *sg = _gameVar->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
+
+ if (sg || (sg = _gameVar->getSubVarByName("OBJSTATES")->addSubVarAsInt("SAVEGAME", 0)) != 0)
+ sg->setSubVarAsInt("Entrance", entranceId);
+
+ if (!g_fullpipe->sceneSwitcher(_sc2array[sc2idx]._entranceData[entranceIdx]))
+ return false;
+
+ g_fullpipe->_msgObjectId2 = 0;
+ g_fullpipe->_msgY = -1;
+ g_fullpipe->_msgX = -1;
+
+ g_fullpipe->_currentScene = st->_scene;
+
+ MessageQueue *mq1 = g_fullpipe->_currentScene->getMessageQueueById(_sc2array[sc2idx]._entranceData[entranceIdx]->_messageQueueId);
+ if (mq1) {
+ MessageQueue *mq = new MessageQueue(mq1, 0, 0);
+
+ StaticANIObject *stobj = g_fullpipe->_currentScene->getStaticANIObject1ById(_field_FA, -1);
+ if (stobj) {
+ stobj->_flags &= 0x100;
+
+ ExCommand *ex = new ExCommand(stobj->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = 256;
+ ex->_messageNum = 0;
+ ex->_excFlags |= 3;
+
+ mq->_exCommands.push_back(ex);
+ }
+
+ mq->setFlags(mq->getFlags() | 1);
+
+ if (!mq->chain(0)) {
+ delete mq;
+
+ return false;
+ }
+ } else {
+ StaticANIObject *stobj = g_fullpipe->_currentScene->getStaticANIObject1ById(_field_FA, -1);
+ if (stobj)
+ stobj->_flags &= 0xfeff;
+ }
+
+ return true;
+}
+
+bool preloadCallback(const PreloadItem &pre, int flag) {
+ warning("STUB: preloadCallback");
+
+ return true;
+}
+
+bool GameLoader::preloadScene(int sceneId, int entranceId) {
+ debug(0, "preloadScene(%d, %d), ", sceneId, entranceId);
+
+ if (_preloadSceneId != sceneId || _preloadEntranceId != entranceId) {
+ _preloadSceneId = sceneId;
+ _preloadEntranceId = entranceId;
+ return true;
+ }
+
+ int idx = -1;
+
+ for (uint i = 0; i < _preloadItems.size(); i++)
+ if (_preloadItems[i]->preloadId1 == sceneId && _preloadItems[i]->preloadId2 == entranceId) {
+ idx = i;
+ break;
+ }
+
+ if (idx == -1) {
+ _preloadSceneId = 0;
+ _preloadEntranceId = 0;
+ return false;
+ }
+
+ if (_preloadCallback) {
+ if (!_preloadCallback(*_preloadItems[idx], 0))
+ return false;
+ }
+
+ if (g_fullpipe->_currentScene && g_fullpipe->_currentScene->_sceneId == sceneId)
+ g_fullpipe->_currentScene = 0;
+
+ saveScenePicAniInfos(sceneId);
+ clearGlobalMessageQueueList1();
+ unloadScene(sceneId);
+
+ if (_preloadCallback)
+ _preloadCallback(*_preloadItems[idx], 50);
+
+ loadScene(_preloadItems[idx]->sceneId);
+
+ ExCommand *ex = new ExCommand(_preloadItems[idx]->sceneId, 17, 62, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags = 2;
+ ex->_keyCode = _preloadItems[idx]->keyCode;
+
+ _preloadSceneId = 0;
+ _preloadEntranceId = 0;
+
+ if (_preloadCallback)
+ _preloadCallback(*_preloadItems[idx], 100);
+
+ ex->postMessage();
+
+ return true;
+}
+
+bool GameLoader::unloadScene(int sceneId) {
+ SceneTag *tag;
+ int sceneTag = getSceneTagBySceneId(sceneId, &tag);
+
+ if (sceneTag < 0)
+ return false;
+
+ if (_sc2array[sceneTag]._isLoaded)
+ saveScenePicAniInfos(sceneId);
+
+ _sc2array[sceneTag]._motionController->freeItems();
+
+ delete tag->_scene;
+ tag->_scene = 0;
+
+ _sc2array[sceneTag]._isLoaded = 0;
+ _sc2array[sceneTag]._scene = 0;
+
+ return true;
+}
+
+int GameLoader::getSceneTagBySceneId(int sceneId, SceneTag **st) {
+ if (_sc2array.size() > 0 && _gameProject->_sceneTagList->size() > 0) {
+ for (uint i = 0; i < _sc2array.size(); i++) {
+ if (_sc2array[i]._sceneId == sceneId) {
+ int num = 0;
+ for (SceneTagList::iterator s = _gameProject->_sceneTagList->begin(); s != _gameProject->_sceneTagList->end(); ++s, num++) {
+ if (s->_sceneId == sceneId) {
+ *st = &(*s);
+ return num;
+ }
+ }
+ }
+ }
+ }
+
+ *st = 0;
+ return -1;
+}
+
+void GameLoader::applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount) {
+ if (picAniInfoCount <= 0)
+ return;
+
+ debug(0, "GameLoader::applyPicAniInfos(sc, ptr, %d)", picAniInfoCount);
+
+ PictureObject *pict;
+ StaticANIObject *ani;
+
+ for (int i = 0; i < picAniInfoCount; i++) {
+ debug(7, "PicAniInfo: id: %d type: %d", picAniInfo[i]->objectId, picAniInfo[i]->type);
+ if (picAniInfo[i]->type & 2) {
+ pict = sc->getPictureObjectById(picAniInfo[i]->objectId, picAniInfo[i]->field_8);
+ if (pict) {
+ pict->setPicAniInfo(picAniInfo[i]);
+ continue;
+ }
+ pict = sc->getPictureObjectById(picAniInfo[i]->objectId, 0);
+ if (pict) {
+ PictureObject *pictNew = new PictureObject(pict);
+
+ sc->_picObjList.push_back(pictNew);
+ pictNew->setPicAniInfo(picAniInfo[i]);
+ continue;
+ }
+ } else {
+ if (!(picAniInfo[i]->type & 1))
+ continue;
+
+ Scene *scNew = g_fullpipe->accessScene(picAniInfo[i]->sceneId);
+ if (!scNew)
+ continue;
+
+ ani = sc->getStaticANIObject1ById(picAniInfo[i]->objectId, picAniInfo[i]->field_8);
+ if (ani) {
+ ani->setPicAniInfo(picAniInfo[i]);
+ continue;
+ }
+
+ ani = scNew->getStaticANIObject1ById(picAniInfo[i]->objectId, 0);
+ if (ani) {
+ StaticANIObject *aniNew = new StaticANIObject(ani);
+
+ sc->addStaticANIObject(aniNew, 1);
+
+ aniNew->setPicAniInfo(picAniInfo[i]);
+ continue;
+ }
+ }
+ }
+}
+
+void GameLoader::saveScenePicAniInfos(int sceneId) {
+ warning("STUB: GameLoader::saveScenePicAniInfos(%d)", sceneId);
+}
+
+void GameLoader::updateSystems(int counterdiff) {
+ if (g_fullpipe->_currentScene) {
+ g_fullpipe->_currentScene->update(counterdiff);
+
+ _exCommand._messageKind = 17;
+ _updateCounter++;
+ _exCommand._messageNum = 33;
+ _exCommand._excFlags = 0;
+ _exCommand.postMessage();
+ }
+
+ processMessages();
+
+ if (_preloadSceneId) {
+ processMessages();
+ preloadScene(_preloadSceneId, _preloadEntranceId);
+ }
+}
+
+Sc2::Sc2() {
+ _sceneId = 0;
+ _field_2 = 0;
+ _scene = 0;
+ _motionController = 0;
+ _data1 = 0;
+ _count1 = 0;
+ _defPicAniInfos = 0;
+ _defPicAniInfosCount = 0;
+ _picAniInfos = 0;
+ _picAniInfosCount = 0;
+ _isLoaded = 0;
+ _entranceData = 0;
+ _entranceDataCount = 0;
+}
+
+bool Sc2::load(MfcArchive &file) {
+ debug(5, "Sc2::load()");
+
+ _sceneId = file.readUint16LE();
+
+ _motionController = (MotionController *)file.readClass();
+
+ _count1 = file.readUint32LE();
+ debug(4, "count1: %d", _count1);
+ if (_count1 > 0) {
+ _data1 = (int32 *)malloc(_count1 * sizeof(int32));
+
+ for (int i = 0; i < _count1; i++) {
+ _data1[i] = file.readUint32LE();
+ }
+ } else {
+ _data1 = 0;
+ }
+
+ _defPicAniInfosCount = file.readUint32LE();
+ debug(4, "defPicAniInfos: %d", _defPicAniInfosCount);
+ if (_defPicAniInfosCount > 0) {
+ _defPicAniInfos = (PicAniInfo **)malloc(_defPicAniInfosCount * sizeof(PicAniInfo *));
+
+ for (int i = 0; i < _defPicAniInfosCount; i++) {
+ _defPicAniInfos[i] = new PicAniInfo();
+
+ _defPicAniInfos[i]->load(file);
+ }
+ } else {
+ _defPicAniInfos = 0;
+ }
+
+ _picAniInfos = 0;
+ _picAniInfosCount = 0;
+
+ _entranceDataCount = file.readUint32LE();
+ debug(4, "_entranceData: %d", _entranceDataCount);
+
+ if (_entranceDataCount > 0) {
+ _entranceData = (EntranceInfo **)malloc(_entranceDataCount * sizeof(EntranceInfo *));
+
+ for (int i = 0; i < _entranceDataCount; i++) {
+ _entranceData[i] = new EntranceInfo();
+ _entranceData[i]->load(file);
+ }
+ } else {
+ _entranceData = 0;
+ }
+
+ if (file.size() - file.pos() > 0)
+ error("Sc2::load(): (%d bytes left)", file.size() - file.pos());
+
+ return true;
+}
+
+bool PreloadItems::load(MfcArchive &file) {
+ debug(5, "PreloadItems::load()");
+
+ int count = file.readCount();
+
+ clear();
+
+ for (int i = 0; i < count; i++) {
+ PreloadItem *t = new PreloadItem();
+ t->preloadId1 = file.readUint32LE();
+ t->preloadId2 = file.readUint32LE();
+ t->sceneId = file.readUint32LE();
+ t->keyCode = file.readUint32LE();
+
+ push_back(t);
+ }
+
+ return true;
+}
+
+GameVar *FullpipeEngine::getGameLoaderGameVar() {
+ if (_gameLoader)
+ return _gameLoader->_gameVar;
+ else
+ return 0;
+}
+
+InputController *FullpipeEngine::getGameLoaderInputController() {
+ if (_gameLoader)
+ return _gameLoader->_inputController;
+ else
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/gameloader.h b/engines/fullpipe/gameloader.h
new file mode 100644
index 0000000000..4f5462671d
--- /dev/null
+++ b/engines/fullpipe/gameloader.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.
+ *
+ */
+
+#ifndef FULLPIPE_GAMELOADER_H
+#define FULLPIPE_GAMELOADER_H
+
+#include "fullpipe/objects.h"
+#include "fullpipe/inventory.h"
+#include "fullpipe/messages.h"
+
+namespace Fullpipe {
+
+class SceneTag;
+class MctlCompound;
+class InputController;
+class InteractionController;
+class MotionController;
+
+class Sc2 : public CObject {
+ public:
+ int16 _sceneId;
+ int16 _field_2;
+ Scene *_scene;
+ MotionController *_motionController;
+ int32 *_data1; // FIXME, could be a struct
+ int _count1;
+ PicAniInfo **_defPicAniInfos;
+ int _defPicAniInfosCount;
+ PicAniInfo **_picAniInfos;
+ int _picAniInfosCount;
+ int _isLoaded;
+ EntranceInfo **_entranceData;
+ int _entranceDataCount;
+
+ public:
+ Sc2();
+ virtual bool load(MfcArchive &file);
+};
+
+typedef Common::Array<Sc2> Sc2Array;
+
+struct PreloadItem {
+ int preloadId1;
+ int preloadId2;
+ int sceneId;
+ int keyCode;
+};
+
+bool preloadCallback(const PreloadItem &pre, int flag);
+
+class PreloadItems : public Common::Array<PreloadItem *>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+class GameLoader : public CObject {
+ public:
+ GameLoader();
+ virtual ~GameLoader();
+
+ virtual bool load(MfcArchive &file);
+ bool loadScene(int sceneId);
+ bool gotoScene(int sceneId, int entranceId);
+ bool preloadScene(int sceneId, int entranceId);
+ bool unloadScene(int sceneId);
+
+ void updateSystems(int counterdiff);
+
+ int getSceneTagBySceneId(int sceneId, SceneTag **st);
+ void applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount);
+ void saveScenePicAniInfos(int sceneId);
+
+ GameProject *_gameProject;
+ InteractionController *_interactionController;
+ InputController *_inputController;
+ Inventory2 _inventory;
+ Sc2Array _sc2array;
+ void *_sceneSwitcher;
+ bool (*_preloadCallback)(const PreloadItem &pre, int flag);
+ void *_readSavegameCallback;
+ int16 _field_F8;
+ int16 _field_FA;
+ PreloadItems _preloadItems;
+ GameVar *_gameVar;
+ char *_gameName;
+ ExCommand _exCommand;
+ int _updateCounter;
+ int _preloadSceneId;
+ int _preloadEntranceId;
+};
+
+Inventory2 *getGameLoaderInventory();
+InteractionController *getGameLoaderInteractionController();
+MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId);
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_GAMELOADER_H */
diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp
new file mode 100644
index 0000000000..fba7e402d2
--- /dev/null
+++ b/engines/fullpipe/gfx.cpp
@@ -0,0 +1,1250 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/gfx.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/gameloader.h"
+
+#include "common/memstream.h"
+
+namespace Fullpipe {
+
+Bitmap::Bitmap() {
+ _x = 0;
+ _y = 0;
+ _width = 0;
+ _height = 0;
+ _pixels = 0;
+ _type = 0;
+ _dataSize = 0;
+ _flags = 0;
+}
+
+Bitmap::Bitmap(Bitmap *src) {
+ _x = src->_x;
+ _y = src->_y;
+ _flags = src->_flags;
+ _dataSize = src->_dataSize;
+ _type = src->_type;
+ _width = src->_width;
+ _height = src->_height;
+ _pixels = src->_pixels;
+}
+
+Bitmap::~Bitmap() {
+ if (_pixels)
+ free(_pixels);
+}
+
+void Bitmap::load(Common::ReadStream *s) {
+ debug(5, "Bitmap::load()");
+
+ _x = s->readUint32LE();
+ _y = s->readUint32LE();
+ _width = s->readUint32LE();
+ _height = s->readUint32LE();
+ s->readUint32LE(); // pixels
+ _type = s->readUint32LE();
+ _dataSize = s->readUint32LE();
+ _flags = s->readUint32LE();
+
+ debug(8, "Bitmap: x: %d y: %d w: %d h: %d dataSize: 0x%x", _x, _y, _width, _height, _dataSize);
+ debug(8, "Bitmap: type: %s (0x%04x) flags: 0x%x", Common::tag2string(_type).c_str(), _type, _flags);
+}
+
+Background::Background() {
+ _x = 0;
+ _y = 0;
+ _messageQueueId = 0;
+ _bigPictureArray1Count = 0;
+ _bigPictureArray2Count = 0;
+ _bigPictureArray = 0;
+ _bgname = 0;
+ _palette = 0;
+}
+
+bool Background::load(MfcArchive &file) {
+ debug(5, "Background::load()");
+ _bgname = file.readPascalString();
+
+ int count = file.readUint16LE();
+
+ for (int i = 0; i < count; i++) {
+ PictureObject *pct = new PictureObject();
+
+ pct->load(file, i == 0);
+ addPictureObject(pct);
+ }
+
+ assert(g_fullpipe->_gameProjectVersion >= 4);
+
+ _bigPictureArray1Count = file.readUint32LE();
+
+ assert(g_fullpipe->_gameProjectVersion >= 5);
+
+ _bigPictureArray2Count = file.readUint32LE();
+
+ _bigPictureArray = (BigPicture ***)calloc(_bigPictureArray1Count, sizeof(BigPicture **));
+
+ debug(6, "bigPictureArray[%d][%d]", _bigPictureArray1Count, _bigPictureArray2Count);
+
+ for (int i = 0; i < _bigPictureArray1Count; i++) {
+ _bigPictureArray[i] = (BigPicture **)calloc(_bigPictureArray2Count, sizeof(BigPicture *));
+ for (int j = 0; j < _bigPictureArray2Count; j++) {
+ _bigPictureArray[i][j] = new BigPicture();
+
+ _bigPictureArray[i][j]->load(file);
+ }
+ }
+
+ return true;
+}
+
+void Background::addPictureObject(PictureObject *pct) {
+ if (pct->_okeyCode)
+ pct->renumPictures(&_picObjList);
+
+ bool inserted = false;
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ if (((PictureObject *)_picObjList[i])->_priority == pct->_priority) {
+ _picObjList.insert_at(i, pct);
+ inserted = true;
+ break;
+ }
+ }
+
+ if (!inserted) {
+ _picObjList.push_back(pct);
+ }
+}
+
+PictureObject::PictureObject() {
+ _ox = 0;
+ _oy = 0;
+ _picture = 0;
+ _ox2 = 0;
+ _oy2 = 0;
+ _pictureObject2List = 0;
+ _objtype = kObjTypePictureObject;
+}
+
+PictureObject::PictureObject(PictureObject *src) : GameObject(src) {
+ _picture = src->_picture;
+ _ox2 = _ox;
+ _oy2 = _oy;
+ _pictureObject2List = src->_pictureObject2List;
+ _objtype = kObjTypePictureObject;
+}
+
+bool PictureObject::load(MfcArchive &file, bool bigPicture) {
+ debug(5, "PictureObject::load()");
+ GameObject::load(file);
+
+ if (bigPicture)
+ _picture = new BigPicture();
+ else
+ _picture = new Picture();
+
+ _picture->load(file);
+
+ _pictureObject2List = new PtrList();
+
+ int count = file.readUint16LE();
+
+ if (count > 0) {
+ GameObject *o = new GameObject();
+
+ o->load(file);
+ _pictureObject2List->push_back(o);
+ }
+
+ _ox2 = _ox;
+ _oy2 = _oy;
+
+#if 0
+ _picture->displayPicture();
+#endif
+
+ return true;
+}
+
+Common::Point *PictureObject::getDimensions(Common::Point *p) {
+ _picture->getDimensions(p);
+
+ return p;
+}
+
+void PictureObject::draw() {
+ if (_flags & 1)
+ _picture->draw(_ox, _oy, 2, 0);
+ else
+ _picture->draw(_ox, _oy, 0, 0);
+}
+
+void PictureObject::drawAt(int x, int y) {
+ if (x == -1)
+ x = _ox;
+ if (y == -1)
+ y = _oy;
+
+ _picture->_x = x;
+ _picture->_y = y;
+
+ if (_flags & 1)
+ _picture->draw(x, y, 2, 0);
+ else
+ _picture->draw(x, y, 0, 0);
+}
+
+bool PictureObject::setPicAniInfo(PicAniInfo *picAniInfo) {
+ if (!(picAniInfo->type & 2) || (picAniInfo->type & 1)) {
+ error("Picture::setPicAniInfo(): Wrong type: %d", picAniInfo->type);
+
+ return false;
+ }
+
+ if (picAniInfo->type & 2) {
+ setOXY(picAniInfo->ox, picAniInfo->oy);
+ _priority = picAniInfo->priority;
+ _okeyCode = picAniInfo->field_8;
+ setFlags(picAniInfo->flags);
+ _field_8 = picAniInfo->field_24;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool PictureObject::isPointInside(int x, int y) {
+ bool res;
+ int oldx = _picture->_x;
+ int oldy = _picture->_y;
+
+ _picture->_x = _ox;
+ _picture->_y = _oy;
+
+ res = _picture->isPointInside(x, y);
+
+ _picture->_x = oldx;
+ _picture->_y = oldy;
+
+ return res;
+}
+
+bool PictureObject::isPixelHitAtPos(int x, int y) {
+ int oldx = _picture->_x;
+ int oldy = _picture->_y;
+
+ _picture->_x = _ox;
+ _picture->_y = _oy;
+ bool res = _picture->isPixelHitAtPos(x, y);
+ _picture->_x = oldx;
+ _picture->_y = oldy;
+
+ return res;
+}
+
+GameObject::GameObject() {
+ _okeyCode = 0;
+ _flags = 0;
+ _id = 0;
+ _ox = 0;
+ _oy = 0;
+ _priority = 0;
+ _field_20 = 0;
+ _field_8 = 0;
+ _objectName = 0;
+}
+
+GameObject::GameObject(GameObject *src) {
+ _okeyCode = 1;
+ _flags = 0;
+ _id = src->_id;
+
+ _objectName = (char *)calloc(strlen(src->_objectName) + 1, 1);
+ strncpy(_objectName, src->_objectName, strlen(src->_objectName));
+
+ _ox = src->_ox;
+ _oy = src->_oy;
+ _priority = src->_priority;
+ _field_20 = 1;
+ _field_8 = src->_field_8;
+}
+
+GameObject::~GameObject() {
+ free(_objectName);
+}
+
+bool GameObject::load(MfcArchive &file) {
+ debug(5, "GameObject::load()");
+ _okeyCode = 0;
+ _flags = 0;
+ _field_20 = 0;
+
+ _id = file.readUint16LE();
+
+ _objectName = file.readPascalString();
+ _ox = file.readUint32LE();
+ _oy = file.readUint32LE();
+ _priority = file.readUint16LE();
+
+ if (g_fullpipe->_gameProjectVersion >= 11) {
+ _field_8 = file.readUint32LE();
+ }
+
+ return true;
+}
+
+void GameObject::setOXY(int x, int y) {
+ _ox = x;
+ _oy = y;
+}
+
+void GameObject::renumPictures(PtrList *lst) {
+ int *buf = (int *)calloc(lst->size() + 2, sizeof(int));
+
+ for (uint i = 0; i < lst->size(); i++) {
+ if (_id == ((PictureObject *)((*lst)[i]))->_id)
+ buf[((PictureObject *)((*lst)[i]))->_okeyCode] = 1;
+ }
+
+ if (buf[_okeyCode]) {
+ uint count;
+ for (count = 1; buf[count] && count < lst->size() + 2; count++)
+ ;
+ _okeyCode = count;
+ }
+
+ free(buf);
+}
+
+bool GameObject::getPicAniInfo(PicAniInfo *info) {
+ if (_objtype == kObjTypePictureObject) {
+ info->type = 2;
+ info->objectId = _id;
+ info->sceneId = 0;
+ info->field_8 = _okeyCode;
+ info->flags = _flags;
+ info->field_24 = _field_8;
+ info->ox = _ox;
+ info->oy = _oy;
+ info->priority = _priority;
+
+ return true;
+ }
+
+ if (_objtype == kObjTypeStaticANIObject) {
+ StaticANIObject *ani = (StaticANIObject *)this;
+
+ info->type = (ani->_messageQueueId << 16) | 1;
+ info->objectId = ani->_id;
+ info->field_8 = ani->_okeyCode;
+ info->sceneId = ani->_sceneId;
+ info->flags = ani->_flags;
+ info->field_24 = ani->_field_8;
+ if (ani->_movement) {
+ info->ox = ani->_movement->_ox;
+ info->oy = ani->_movement->_oy;
+ } else {
+ info->ox = ani->_ox;
+ info->oy = ani->_oy;
+ }
+ info->priority = ani->_priority;
+
+ if (ani->_statics)
+ info->staticsId = ani->_statics->_staticsId;
+
+ if (ani->_movement) {
+ info->movementId = ani->_movement->_id;
+ info->dynamicPhaseIndex = ani->_movement->_currDynamicPhaseIndex;
+ }
+
+ info->someDynamicPhaseIndex = ani->_someDynamicPhaseIndex;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool GameObject::setPicAniInfo(PicAniInfo *picAniInfo) {
+ if (!(picAniInfo->type & 3)) {
+ warning("StaticANIObject::setPicAniInfo(): Wrong type: %d", picAniInfo->type);
+
+ return false;
+ }
+
+ if (picAniInfo->type & 3) {
+ setOXY(picAniInfo->ox, picAniInfo->oy);
+ _priority = picAniInfo->priority;
+ _okeyCode = picAniInfo->field_8;
+ setFlags(picAniInfo->flags);
+ _field_8 = picAniInfo->field_24;
+ }
+
+ if (picAniInfo->type & 1) {
+ StaticANIObject *ani = (StaticANIObject *)this;
+
+ ani->_messageQueueId = (picAniInfo->type >> 16) & 0xffff;
+
+ if (picAniInfo->staticsId) {
+ ani->_statics = ani->getStaticsById(picAniInfo->staticsId);
+ } else {
+ ani->_statics = 0;
+ }
+
+ if (picAniInfo->movementId) {
+ ani->_movement = ani->getMovementById(picAniInfo->movementId);
+ if (ani->_movement)
+ ani->_movement->setDynamicPhaseIndex(picAniInfo->dynamicPhaseIndex);
+ } else {
+ ani->_movement = 0;
+ }
+
+ ani->setSomeDynamicPhaseIndex(picAniInfo->someDynamicPhaseIndex);
+ }
+
+ return true;
+}
+
+Picture::Picture() {
+ _x = 0;
+ _y = 0;
+ _field_44 = 0;
+ _field_54 = 0;
+ _bitmap = 0;
+ _alpha = -1;
+ _paletteData = 0;
+ _convertedBitmap = 0;
+ _memoryObject2 = 0;
+ _width = 0;
+ _height = 0;
+}
+
+Picture::~Picture() {
+ freePicture();
+
+ _bitmap = 0;
+
+ if (_memoryObject2)
+ delete _memoryObject2;
+
+ if (_paletteData)
+ free(_paletteData);
+
+ if (_convertedBitmap) {
+ delete _convertedBitmap;
+ _convertedBitmap = 0;
+ }
+}
+
+void Picture::freePicture() {
+ debug(5, "Picture::freePicture(): file: %s", _memfilename);
+
+ if (_bitmap) {
+ if (testFlags() && !_field_54) {
+ freeData();
+ delete _bitmap;
+ _bitmap = 0;
+ }
+ }
+
+ if (_bitmap) {
+ _bitmap = 0;
+ _data = 0;
+ }
+
+ if (_convertedBitmap) {
+ free(_convertedBitmap->_pixels);
+ delete _convertedBitmap;
+ _convertedBitmap = 0;
+ }
+}
+
+bool Picture::load(MfcArchive &file) {
+ debug(5, "Picture::load()");
+ MemoryObject::load(file);
+
+ _x = file.readUint32LE();
+ _y = file.readUint32LE();
+ _field_44 = file.readUint16LE();
+
+ assert(g_fullpipe->_gameProjectVersion >= 2);
+
+ _width = file.readUint32LE();
+ _height = file.readUint32LE();
+
+ _mflags |= 1;
+
+ _memoryObject2 = new MemoryObject2;
+ _memoryObject2->load(file);
+
+ if (_memoryObject2->_data) {
+ setAOIDs();
+ }
+
+ assert (g_fullpipe->_gameProjectVersion >= 12);
+
+ _alpha = file.readUint32LE() & 0xff;
+
+ int havePal = file.readUint32LE();
+
+ if (havePal > 0) {
+ _paletteData = (byte *)calloc(1024, 1);
+ file.read(_paletteData, 1024);
+ }
+
+ getData();
+
+ debug(5, "Picture::load: loaded <%s>", _memfilename);
+
+ return true;
+}
+
+void Picture::setAOIDs() {
+ int w = (g_fullpipe->_pictureScale + _width - 1) / g_fullpipe->_pictureScale;
+ int h = (g_fullpipe->_pictureScale + _height - 1) / g_fullpipe->_pictureScale;
+
+ _memoryObject2->_rows = (byte **)malloc(w * sizeof(int *));
+
+ int pitch = 2 * h;
+ byte *ptr = _memoryObject2->getData();
+ for (int i = 0; i < w; i++) {
+ _memoryObject2->_rows[i] = ptr;
+ ptr += pitch;
+ }
+}
+
+void Picture::init() {
+ debug(5, "Picture::init(), %s", _memfilename);
+
+ MemoryObject::getData();
+
+ _bitmap = new Bitmap();
+
+ getDibInfo();
+
+ _bitmap->_flags |= 0x1000000;
+}
+
+Common::Point *Picture::getDimensions(Common::Point *p) {
+ p->x = _width;
+ p->y = _height;
+
+ return p;
+}
+
+void Picture::getDibInfo() {
+ int off = _dataSize & ~0xf;
+
+ debug(9, "Picture::getDibInfo: _dataSize: %d", _dataSize);
+
+ if (!_dataSize) {
+ warning("Picture::getDibInfo(): Empty data size");
+ return;
+ }
+
+ if (_dataSize != off) {
+ warning("Uneven data size: 0x%x", _dataSize);
+ }
+
+ if (!_data) {
+ warning("Picture::getDibInfo: data is empty <%s>", _memfilename);
+
+ MemoryObject::load();
+ }
+
+ Common::MemoryReadStream *s = new Common::MemoryReadStream(_data + off - 32, 32);
+
+ _bitmap->load(s);
+ _bitmap->_pixels = _data;
+}
+
+Bitmap *Picture::getPixelData() {
+ if (!_bitmap)
+ init();
+
+ return _bitmap;
+}
+
+void Picture::draw(int x, int y, int style, int angle) {
+ int x1 = x;
+ int y1 = y;
+
+ debug(0, "Picture::draw(%d, %d, %d, %d) (%s)", x, y, style, angle, _memfilename);
+
+ if (x != -1)
+ x1 = x;
+
+ if (y != -1)
+ y1 = y;
+
+ if (!_bitmap)
+ init();
+
+ if (!_bitmap)
+ return;
+
+ if ((_alpha & 0xff) < 0xff) {
+ debug(0, "Picture:draw: alpha = %0x", _alpha);
+ }
+
+ byte *pal = _paletteData;
+
+ if (!pal) {
+ //warning("Picture:draw: using global palette");
+ pal = g_fullpipe->_globalPalette;
+ }
+
+ Common::Point point;
+
+ switch (style) {
+ case 1:
+ //flip
+ getDimensions(&point);
+ _bitmap->flipVertical()->drawShaded(1, x1, y1 + 30 + point.y, pal);
+ break;
+ case 2:
+ //vrtSetFadeRatio(g_vrtDrawHandle, 0.34999999);
+ //vrtSetFadeTable(g_vrtDrawHandle, &unk_477F88, 1.0, 1000.0, 0, 0);
+ _bitmap->drawShaded(2, x1, y1, pal);
+ //vrtSetFadeRatio(g_vrtDrawHandle, 0.0);
+ //vrtSetFadeTable(g_vrtDrawHandle, &unk_477F90, 1.0, 1000.0, 0, 0);
+ break;
+ default:
+ if (angle)
+ drawRotated(x1, y1, angle);
+ else {
+ _bitmap->putDib(x1, y1, (int32 *)pal);
+ }
+ }
+}
+
+void Picture::drawRotated(int x, int y, int angle) {
+ warning("STUB: Picture::drawRotated(%d, %d, %d)", x, y, angle);
+}
+
+void Picture::displayPicture() {
+ if (!g_fullpipe->_gameContinue)
+ return;
+
+ getData();
+ init();
+
+ if (!_dataSize)
+ return;
+
+ g_fullpipe->_backgroundSurface.fillRect(Common::Rect(0, 0, 799, 599), 0);
+ g_fullpipe->_system->copyRectToScreen(g_fullpipe->_backgroundSurface.getBasePtr(0, 0), g_fullpipe->_backgroundSurface.pitch, 0, 0, 799, 599);
+
+ draw(0, 0, 0, 0);
+
+ g_fullpipe->updateEvents();
+ g_fullpipe->_system->delayMillis(10);
+ g_fullpipe->_system->updateScreen();
+
+ while (g_fullpipe->_gameContinue) {
+ g_fullpipe->updateEvents();
+ g_fullpipe->_system->delayMillis(10);
+ g_fullpipe->_system->updateScreen();
+
+ if (g_fullpipe->_keyState == ' ') {
+ g_fullpipe->_keyState = Common::KEYCODE_INVALID;
+ break;
+ }
+ }
+}
+
+void Picture::setPaletteData(byte *pal) {
+ if (_paletteData)
+ free(_paletteData);
+
+ if (pal) {
+ _paletteData = (byte *)malloc(1024);
+ memcpy(_paletteData, pal, 1024);
+ }
+}
+
+void Picture::copyMemoryObject2(Picture *src) {
+ if (_width == src->_width && _height == src->_height) {
+ if (src->_memoryObject2 && src->_memoryObject2->_rows && _memoryObject2) {
+ byte *data = loadData();
+ _memoryObject2->copyData(data, _dataSize);
+ setAOIDs();
+ }
+ }
+}
+
+bool Picture::isPointInside(int x, int y) {
+ if (x >= _x) {
+ if (y >= _y && x < _x + _width && y < _y + _height)
+ return true;
+ }
+ return false;
+}
+
+bool Picture::isPixelHitAtPos(int x, int y) {
+ if (x < _x || y < _y || x >= _x + _width || y >= _y + _height)
+ return false;
+
+ if (!_bitmap)
+ init();
+
+ _bitmap->_x = _x;
+ _bitmap->_y = _y;
+
+ return _bitmap->isPixelHitAtPos(x, y);
+}
+
+int Picture::getPixelAtPos(int x, int y) {
+ return getPixelAtPosEx(x / g_fullpipe->_pictureScale, y / g_fullpipe->_pictureScale);
+
+ return false;
+}
+
+int Picture::getPixelAtPosEx(int x, int y) {
+ if (x < 0 || y < 0)
+ return 0;
+
+ if (x < (g_fullpipe->_pictureScale + _width - 1) / g_fullpipe->_pictureScale &&
+ y < (g_fullpipe->_pictureScale + _height - 1) / g_fullpipe->_pictureScale &&
+ _memoryObject2 != 0 && _memoryObject2->_rows != 0)
+ return _memoryObject2->_rows[x][2 * y];
+
+ return 0;
+}
+
+bool Bitmap::isPixelHitAtPos(int x, int y) {
+ if (x < _x || x >= _width + _x || y < _y || y >= _y + _height)
+ return false;
+
+ int off;
+
+ if (_type == 'CB\x05e')
+ off = 2 * ((_width + 1) / 2);
+ else
+ off = 4 * ((_width + 3) / 4);
+
+ off = x + off * (_y + _height - y - 1) - _x;
+
+ if (_flags & 0x1000000) {
+ switch (_type) {
+ case 'CB\0\0':
+ if (_pixels[off] == (_flags & 0xff))
+ return false;
+ break;
+ case 'CB\x05e':
+ if (!*(int16 *)&_pixels[2 * off])
+ return false;
+ break;
+ case 'RB\0\0':
+ return isPixelAtHitPosRB(x, y);
+ }
+ }
+ return true;
+}
+
+bool Bitmap::isPixelAtHitPosRB(int x, int y) {
+ int ox = _x;
+ int oy = _y;
+
+ _x = _y = 0;
+
+ bool res = putDibRB(0, x, y);
+ _x = ox;
+ _y = oy;
+
+ return res;
+}
+
+void Bitmap::putDib(int x, int y, int32 *palette) {
+ debug(0, "Bitmap::putDib(%d, %d)", x, y);
+
+ _x = x - g_fullpipe->_sceneRect.left;
+ _y = y - g_fullpipe->_sceneRect.top;
+
+ if (_type == MKTAG('R', 'B', '\0', '\0'))
+ putDibRB(palette);
+ else
+ putDibCB(palette);
+}
+
+bool Bitmap::putDibRB(int32 *palette, int pX, int pY) {
+ uint16 *curDestPtr;
+ int endy;
+ int x;
+ int start1;
+ int fillLen;
+ uint16 pixel;
+ int endx;
+ int y;
+ uint16 *srcPtr2;
+ uint16 *srcPtr;
+
+ if (!palette && pX == -1) {
+ warning("Bitmap::putDibRB(): Both global and local palettes are empty");
+ return false;
+ }
+
+ debug(8, "Bitmap::putDibRB()");
+
+ endx = _width + _x - 1;
+ endy = _height + _y - 1;
+
+ if (_x > 799 || endx < 0 || _y > 599 || endy < 0)
+ return false;
+
+ if (pX == -1) {
+ if (endy > 599)
+ endy = 599;
+
+ if (endx > 799)
+ endx = 799;
+ }
+
+ int startx = _x;
+ if (startx < 0)
+ startx = 0;
+
+ int starty = _y;
+ if (starty < 0)
+ starty = 0;
+
+ y = endy;
+
+ srcPtr = (uint16 *)_pixels;
+
+ bool breakup = false;
+ for (y = endy; y >= starty && !breakup; y--) {
+ x = startx;
+
+ while ((pixel = *srcPtr++) != 0) {
+ if (pixel == 0x100) {
+ breakup = true;
+ break;
+ }
+
+ while (pixel == 0x200 && y >= starty) {
+ uint16 value = *srcPtr++;
+
+ x += (byte)(value & 0xff);
+ y -= (byte)((value >> 8) & 0xff);
+
+ pixel = *srcPtr++;
+ }
+
+ if (y < starty || pixel == 0)
+ break;
+
+ start1 = x;
+ fillLen = (byte)(pixel & 0xff);
+
+ if (fillLen) {
+ x += fillLen;
+
+ if (start1 < 0) {
+ fillLen += start1;
+
+ if (fillLen > 0)
+ start1 = 0;
+ }
+
+ if (fillLen > 0 || start1 >= 0) {
+ if (x <= 799 + 1 || (fillLen += 799 - x + 1, fillLen > 0)) {
+ if (y <= endy) {
+ if (pX == -1) {
+ int bgcolor = palette[(pixel >> 8) & 0xff];
+ curDestPtr = (uint16 *)g_fullpipe->_backgroundSurface.getBasePtr(start1, y);
+ colorFill(curDestPtr, fillLen, bgcolor);
+ } else {
+ if (y == pY && pX >= start1 && pX < start1 + fillLen)
+ return true;
+ }
+ }
+ }
+ }
+ } else {
+ fillLen = (pixel >> 8) & 0xff;
+ srcPtr2 = srcPtr;
+ x += fillLen;
+ srcPtr += (fillLen + 1) >> 1;
+
+ if (start1 < 0) {
+ fillLen += start1;
+ if (fillLen > 0) {
+ srcPtr2 = (uint16 *)((byte *)srcPtr2 - start1);
+ start1 = 0;
+ }
+ }
+
+ if (x > 799 + 1) {
+ fillLen += 799 - x + 1;
+ if (fillLen <= 0)
+ continue;
+ }
+
+ if (y <= endy) {
+ if (pX == -1) {
+ curDestPtr = (uint16 *)g_fullpipe->_backgroundSurface.getBasePtr(start1, y);
+ paletteFill(curDestPtr, (byte *)srcPtr2, fillLen, (int32 *)palette);
+ } else {
+ if (y == pY && pX >= start1 && pX < start1 + fillLen)
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ if (pX == -1)
+ g_fullpipe->_system->copyRectToScreen(g_fullpipe->_backgroundSurface.getBasePtr(startx, starty), g_fullpipe->_backgroundSurface.pitch, startx, starty, endx + 1 - startx, endy + 1 - starty);
+
+ return false;
+}
+
+void Bitmap::putDibCB(int32 *palette) {
+ uint16 *curDestPtr;
+ int endx;
+ int endy;
+ int bpp;
+ uint pitch;
+ bool cb05_format;
+
+ endx = _width + _x - 1;
+ endy = _height + _y - 1;
+
+ debug(8, "Bitmap::putDibCB(): %d, %d, %d, %d [%d, %d]", _x, _y, endx, endy, _width, _height);
+
+ if (_x > 799 || endx < 0 || _y > 599 || endy < 0)
+ return;
+
+ if (endy > 599)
+ endy = 599;
+
+ if (endx > 799)
+ endx = 799;
+
+ cb05_format = (_type == MKTAG('C', 'B', '\05', 'e'));
+
+ if (!palette && !cb05_format)
+ error("Bitmap::putDibCB(): Both global and local palettes are empty");
+
+ bpp = cb05_format ? 2 : 1;
+ pitch = (bpp * _width + 3) & 0xFFFFFFFC;
+
+ byte *srcPtr = &_pixels[pitch * (endy - _y)];
+
+ int starty = _y;
+ if (starty < 0) {
+ starty = 0;
+ srcPtr = &_pixels[pitch * (_height + _y)];
+ }
+
+ int startx = _x;
+ if (startx < 0) {
+ srcPtr += bpp * -_x;
+ startx = 0;
+ }
+
+ if (_flags & 0x1000000) {
+ for (int y = starty; y < endy; srcPtr -= pitch, y++) {
+ curDestPtr = (uint16 *)g_fullpipe->_backgroundSurface.getBasePtr(startx, y);
+ copierKeyColor(curDestPtr, srcPtr, endx - startx + 1, _flags & 0xff, (int32 *)palette, cb05_format);
+ }
+ } else {
+ for (int y = starty; y <= endy; srcPtr -= pitch, y++) {
+ curDestPtr = (uint16 *)g_fullpipe->_backgroundSurface.getBasePtr(startx, y);
+ copier(curDestPtr, srcPtr, endx - startx + 1, (int32 *)palette, cb05_format);
+ }
+ }
+
+ g_fullpipe->_system->copyRectToScreen(g_fullpipe->_backgroundSurface.getBasePtr(startx, starty), g_fullpipe->_backgroundSurface.pitch, startx, starty, endx + 1 - startx, endy + 1 - starty);
+}
+
+void Bitmap::colorFill(uint16 *dest, int len, int32 color) {
+#if 0
+ if (blendMode) {
+ if (blendMode != 1)
+ error("vrtPutDib : RLE Fill : Invalid alpha blend mode");
+
+ colorFill = ptralphaFillColor16bit;
+ } else {
+ colorFill = ptrfillColor16bit;
+ }
+#endif
+
+ for (int i = 0; i < len; i++)
+ *dest++ = (int16)(color & 0xffff);
+}
+
+void Bitmap::paletteFill(uint16 *dest, byte *src, int len, int32 *palette) {
+#if 0
+ if (blendMode) {
+ if (blendMode != 1)
+ error("vrtPutDib : RLE Fill : Invalid alpha blend mode");
+
+ paletteFill = ptrcopierWithPaletteAlpha;
+ } else {
+ paletteFill = ptrcopierWithPalette;
+ }
+#endif
+
+ for (int i = 0; i < len; i++)
+ *dest++ = READ_LE_UINT32(&palette[*src++]) & 0xffff;
+}
+
+void Bitmap::copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format) {
+#if 0
+ if (blendMode) {
+ if (blendMode == 1) {
+ if (cb05_format)
+ copierKeyColor = ptrcopier16bitKeycolorAlpha;
+ else
+ copierKeyColor = ptrcopierKeycolorAlpha;
+ } else {
+ copier = 0;
+ }
+ } else if (cb05_format) {
+ copierKeyColor = ptrcopier16bitKeycolor;
+ } else {
+ copierKeyColor = ptrkeyColor16bit;
+ }
+#endif
+
+ if (!cb05_format) {
+ for (int i = 0; i < len; i++) {
+ if (*src != keyColor)
+ *dest = READ_LE_UINT32(&palette[*src]) & 0xffff;
+
+ dest++;
+ src++;
+ }
+ } else {
+ int16 *src16 = (int16 *)src;
+
+ for (int i = 0; i < len; i++) {
+ if (*src16 != 0)
+ *dest = *src16;
+
+ dest++;
+ src16++;
+ }
+ }
+}
+
+void Bitmap::copier(uint16 *dest, byte *src, int len, int32 *palette, bool cb05_format) {
+#if 0
+ if (blendMode) {
+ if (blendMode == 1) {
+ if (cb05_format)
+ copier = ptrcopier16bitAlpha;
+ else
+ copier = ptrcopierWithPaletteAlpha;
+ } else {
+ copier = 0;
+ }
+ } else if (cb05_format) {
+ copier = ptrcopier16bit;
+ } else {
+ copier = ptrcopierWithPalette;
+ }
+#endif
+
+ if (!cb05_format) {
+ for (int i = 0; i < len; i++)
+ *dest++ = READ_LE_UINT32(&palette[*src++]) & 0xffff;
+ } else {
+ int16 *src16 = (int16 *)src;
+
+ for (int i = 0; i < len; i++)
+ *dest++ = *src16++;
+ }
+}
+
+Bitmap *Bitmap::reverseImage() {
+ switch (_type) {
+ case MKTAG('R', 'B', '\0', '\0'):
+ return reverseImageRB();
+ case MKTAG('C', 'B', '\0', '\0'):
+ return reverseImageCB();
+ case MKTAG('C', 'B', '\05', 'e'):
+ return reverseImageCB05();
+ default:
+ error("Bitmap::reverseImage: Unknown image type: %x", _type);
+ }
+
+ return 0;
+}
+
+Bitmap *Bitmap::reverseImageRB() {
+ uint16 *newpixels = (uint16 *)calloc(((_dataSize + 15) & 0xfffffff0) + sizeof(Bitmap), 1);
+ uint16 *srcPtr = (uint16 *)_pixels;
+
+ int idx = 0;
+ while (srcPtr[idx] != 0x100) {
+ uint16 *srcPtr2 = &srcPtr[idx];
+
+ int prevIdx = idx;
+ int i = idx;
+
+ while (*srcPtr2) {
+ ++srcPtr2;
+ ++idx;
+ }
+
+ int idx2 = idx;
+
+ newpixels[idx] = srcPtr[idx];
+
+ while (i != idx) {
+ int fillLen = 2 - ((srcPtr[prevIdx] & 0xff) != 0 ? 1 : 0);
+ idx2 -= fillLen;
+ memcpy(&newpixels[idx2], &srcPtr[prevIdx], 2 * fillLen);
+ prevIdx = fillLen + i;
+ i += fillLen;
+ }
+ ++idx;
+ }
+ newpixels[idx] = 256;
+
+ int oldBmp = ((_dataSize + 15) >> 1) & 0x7FFFFFF8;
+ memcpy(&newpixels[oldBmp], &srcPtr[oldBmp], sizeof(Bitmap));
+
+ Bitmap *res = new Bitmap(this);
+ res->_pixels = (byte *)newpixels;
+
+ return res;
+}
+
+Bitmap *Bitmap::reverseImageCB() {
+ warning("STUB: Bitmap::reverseImageCB()");
+
+ return this;
+}
+
+Bitmap *Bitmap::reverseImageCB05() {
+ warning("STUB: Bitmap::reverseImageCB05()");
+
+ return this;
+}
+
+Bitmap *Bitmap::flipVertical() {
+ warning("STUB: Bitmap::flipVertical()");
+
+ return this;
+}
+
+void Bitmap::drawShaded(int type, int x, int y, byte *palette) {
+ warning("STUB: Bitmap::drawShaded(%d, %d, %d)", type, x, y);
+
+ putDib(x, y, (int32 *)palette);
+}
+
+ void Bitmap::drawRotated(int x, int y, int angle, byte *palette) {
+ warning("STUB: Bitmap::drawShaded(%d, %d, %d)", x, y, angle);
+
+ putDib(x, y, (int32 *)palette);
+}
+
+bool BigPicture::load(MfcArchive &file) {
+ debug(5, "BigPicture::load()");
+ Picture::load(file);
+
+ return true;
+}
+
+Shadows::Shadows() {
+ _staticAniObjectId = 0;
+ _movementId = 0;
+ _sceneId = 0;
+}
+
+bool Shadows::load(MfcArchive &file) {
+ debug(5, "Shadows::load()");
+ _sceneId = file.readUint32LE();
+ _staticAniObjectId = file.readUint32LE();
+ _movementId = file.readUint32LE();
+
+ return true;
+}
+
+void Shadows::init() {
+ Scene *scene = g_fullpipe->accessScene(_sceneId);
+
+ StaticANIObject *st;
+ Movement *mov;
+
+ if (scene && (st = scene->getStaticANIObject1ById(_staticAniObjectId, -1)) != 0
+ && ((mov = st->getMovementById(_movementId)) != 0))
+ initMovement(mov);
+}
+
+void Shadows::initMovement(Movement *mov) {
+ uint num;
+
+ if (mov->_currMovement)
+ num = mov->_currMovement->_dynamicPhases.size();
+ else
+ num = mov->_dynamicPhases.size();
+
+ _items.clear();
+ _items.resize(num);
+
+ Common::Point point;
+
+ _items[0].dynPhase = (DynamicPhase *)mov->_staticsObj1;
+ _items[0].dynPhase->getDimensions(&point);
+ _items[0].width = point.x;
+ _items[0].height = point.y;
+
+ for (uint i = 1; i < num; i++) {
+ _items[i].dynPhase = mov->getDynamicPhaseByIndex(i - 1);
+ _items[i].dynPhase->getDimensions(&point);
+ _items[i].width = point.x;
+ _items[i].height = point.y;
+ }
+}
+
+DynamicPhase *Shadows::findSize(int width, int height) {
+ int idx = 0;
+ int min = 1000;
+
+ if (!_items.size())
+ return 0;
+
+ for (uint i = 0; i < _items.size(); i++) {
+ int w = abs(width - _items[i].width);
+ if (w < min) {
+ min = w;
+ idx = i;
+ }
+ }
+ return _items[idx].dynPhase;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/gfx.h b/engines/fullpipe/gfx.h
new file mode 100644
index 0000000000..9d5c45de0b
--- /dev/null
+++ b/engines/fullpipe/gfx.h
@@ -0,0 +1,218 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_GFX_H
+#define FULLPIPE_GFX_H
+
+namespace Fullpipe {
+
+class DynamicPhase;
+class Movement;
+struct PicAniInfo;
+
+struct Bitmap {
+ int _x;
+ int _y;
+ int _width;
+ int _height;
+ byte *_pixels;
+ int _type;
+ int _dataSize;
+ int _flags;
+
+ Bitmap();
+ Bitmap(Bitmap *src);
+ ~Bitmap();
+
+ void load(Common::ReadStream *s);
+ void putDib(int x, int y, int32 *palette);
+ bool putDibRB(int32 *palette, int x = -1, int y = -1);
+ void putDibCB(int32 *palette);
+
+ void colorFill(uint16 *dest, int len, int32 color);
+ void paletteFill(uint16 *dest, byte *src, int len, int32 *palette);
+ void copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format);
+ void copier(uint16 *dest, byte *src, int len, int32 *palette, bool cb05_format);
+
+ Bitmap *reverseImage();
+ Bitmap *reverseImageRB();
+ Bitmap *reverseImageCB();
+ Bitmap *reverseImageCB05();
+ Bitmap *flipVertical();
+
+ void drawShaded(int type, int x, int y, byte *palette);
+ void drawRotated(int x, int y, int angle, byte *palette);
+
+ bool isPixelHitAtPos(int x, int y);
+ bool isPixelAtHitPosRB(int x, int y);
+};
+
+class Picture : public MemoryObject {
+ public:
+ Common::Rect _rect;
+ Bitmap *_convertedBitmap;
+ int _x;
+ int _y;
+ int _field_44;
+ int _width;
+ int _height;
+ Bitmap *_bitmap;
+ int _field_54;
+ MemoryObject2 *_memoryObject2;
+ int _alpha;
+ byte *_paletteData;
+
+ void displayPicture();
+
+ public:
+ Picture();
+ virtual ~Picture();
+
+ void freePicture();
+
+ virtual bool load(MfcArchive &file);
+ void setAOIDs();
+ void init();
+ void getDibInfo();
+ Bitmap *getPixelData();
+ void draw(int x, int y, int style, int angle);
+ void drawRotated(int x, int y, int angle);
+
+ byte getAlpha() { return (byte)_alpha; }
+ void setAlpha(byte alpha) { _alpha = alpha; }
+
+ Common::Point *getDimensions(Common::Point *p);
+ bool isPointInside(int x, int y);
+ bool isPixelHitAtPos(int x, int y);
+ int getPixelAtPos(int x, int y);
+ int getPixelAtPosEx(int x, int y);
+
+ byte *getPaletteData() { return _paletteData; }
+ void setPaletteData(byte *pal);
+
+ void copyMemoryObject2(Picture *src);
+};
+
+class BigPicture : public Picture {
+ public:
+ BigPicture() {}
+ virtual bool load(MfcArchive &file);
+};
+
+class GameObject : public CObject {
+ public:
+ int16 _okeyCode;
+ int _field_8;
+ int16 _flags;
+ int16 _id;
+ char *_objectName;
+ int _ox;
+ int _oy;
+ int _priority;
+ int _field_20;
+
+ public:
+ GameObject();
+ GameObject(GameObject *src);
+ ~GameObject();
+
+ virtual bool load(MfcArchive &file);
+ void setOXY(int x, int y);
+ void renumPictures(PtrList *lst);
+ void setFlags(int16 flags) { _flags = flags; }
+ void clearFlags() { _flags = 0; }
+ const char *getName() { return _objectName; }
+
+ bool getPicAniInfo(PicAniInfo *info);
+ bool setPicAniInfo(PicAniInfo *info);
+};
+
+class PictureObject : public GameObject {
+ public:
+ Picture *_picture;
+ PtrList *_pictureObject2List;
+ int _ox2;
+ int _oy2;
+
+ public:
+ PictureObject();
+ PictureObject(PictureObject *src);
+
+ virtual bool load(MfcArchive &file, bool bigPicture);
+ virtual bool load(MfcArchive &file) { assert(0); return false; } // Disable base class
+
+ Common::Point *getDimensions(Common::Point *p);
+ void draw();
+ void drawAt(int x, int y);
+
+ bool setPicAniInfo(PicAniInfo *picAniInfo);
+ bool isPointInside(int x, int y);
+ bool isPixelHitAtPos(int x, int y);
+};
+
+class Background : public CObject {
+ public:
+ PtrList _picObjList;
+
+ char *_bgname;
+ int _x;
+ int _y;
+ int16 _messageQueueId;
+ MemoryObject *_palette;
+ int _bigPictureArray1Count;
+ int _bigPictureArray2Count;
+ BigPicture ***_bigPictureArray;
+
+ public:
+ Background();
+ virtual bool load(MfcArchive &file);
+ void addPictureObject(PictureObject *pct);
+
+ BigPicture *getBigPicture(int x, int y) { return _bigPictureArray[x][y]; }
+};
+
+struct ShadowsItem {
+ int width;
+ int height;
+ DynamicPhase *dynPhase;
+};
+
+typedef Common::Array<ShadowsItem> ShadowsItemArray;
+
+class Shadows : public CObject {
+ int _sceneId;
+ int _staticAniObjectId;
+ int _movementId;
+ ShadowsItemArray _items;
+
+ public:
+ Shadows();
+ virtual bool load(MfcArchive &file);
+ void init();
+
+ void initMovement(Movement *mov);
+ DynamicPhase *findSize(int width, int height);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_GFX_H */
diff --git a/engines/fullpipe/init.cpp b/engines/fullpipe/init.cpp
new file mode 100644
index 0000000000..49bf72ac91
--- /dev/null
+++ b/engines/fullpipe/init.cpp
@@ -0,0 +1,247 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/objectnames.h"
+#include "fullpipe/input.h"
+
+#include "fullpipe/constants.h"
+
+namespace Fullpipe {
+
+void FullpipeEngine::initObjectStates() {
+ setLevelStates();
+
+ setObjectState(sO_Dude, getObjectEnumState(sO_Dude, sO_NotCarryingEgg));
+ setObjectState(sO_EggCracker, getObjectEnumState(sO_EggCracker, sO_DidNotCrackEgg));
+ setObjectState(sO_GuvTheDrawer, getObjectEnumState(sO_GuvTheDrawer, sO_Awaken));
+ setObjectState(sO_EggGulper, getObjectEnumState(sO_EggGulper, sO_First));
+ setObjectState(sO_EggGulperGaveCoin, getObjectEnumState(sO_EggGulperGaveCoin, sO_No));
+ setObjectState(sO_Jar_4, getObjectEnumState(sO_Jar_4, sO_OnTheSpring));
+ setObjectState(sO_GulpedEggs, getObjectEnumState(sO_GulpedEgg, sO_NotPresent));
+
+ setSwallowedEggsState();
+
+ setObjectState(sO_WeirdWacko, getObjectEnumState(sO_WeirdWacko, sO_InGlasses));
+ setObjectState(sO_TumyTrampie, getObjectEnumState(sO_TumyTrampie, sO_Drinking));
+ setObjectState(sO_StairsUp_8, getObjectEnumState(sO_StairsUp_8, sO_NotBroken));
+ setObjectState(sO_HareTheNooksiter, getObjectEnumState(sO_HareTheNooksiter, sO_WithHandle));
+ setObjectState(sO_Elephantine, getObjectEnumState(sO_Elephantine, sO_WithBoot));
+ setObjectState(sO_Fly_12, 0);
+ setObjectState(sO_ClockAxis, getObjectEnumState(sO_ClockAxis, sO_NotAvailable));
+ setObjectState(sO_ClockHandle, getObjectEnumState(sO_ClockHandle, sO_In_7));
+ setObjectState(sO_BigMumsy, getObjectEnumState(sO_BigMumsy, sO_Sleeping));
+ setObjectState(sO_CoinSlot_1, getObjectEnumState(sO_CoinSlot_1, sO_Empty));
+ setObjectState(sO_FriesPit, getObjectEnumState(sO_FriesPit, sO_WithApple));
+ setObjectState(sO_Jug, getObjectEnumState(sO_Jug, sO_Blocked));
+ setObjectState(sO_RightStairs_9, getObjectEnumState(sO_RightStairs_9, sO_IsClosed));
+ setObjectState(sO_Pipe_9, getObjectEnumState(sO_Pipe_9, sO_WithJug));
+ setObjectState(sO_Inflater, getObjectEnumState(sO_Inflater, sO_WithGum));
+ setObjectState(sO_Swingie, getObjectEnumState(sO_Swingie, sO_Swinging));
+ setObjectState(sO_DudeJumped, getObjectEnumState(sO_DudeJumped, sO_No));
+ setObjectState(sO_Bridge, getObjectEnumState(sO_Bridge, sO_Convoluted));
+ setObjectState(sO_Guardian, getObjectEnumState(sO_Guardian, sO_OnRight));
+ setObjectState(sO_Grandma, getObjectEnumState(sO_Grandma, sO_In_14));
+ setObjectState(sO_Boot_15, getObjectEnumState(sO_Boot_15, sO_NotPresent));
+ setObjectState(sO_LeftPipe_15, getObjectEnumState(sO_LeftPipe_15, sO_OpenedShe));
+ setObjectState(sO_Pedestal_16, getObjectEnumState(sO_Pedestal_16, sO_IsFree));
+ setObjectState(sO_Cup, getObjectEnumState(sO_Cup, sO_InSmokeRoom));
+ setObjectState(sO_Pedestal_17, getObjectEnumState(sO_Pedestal_17, sO_IsFree));
+ setObjectState(sO_UsherHand, getObjectEnumState(sO_UsherHand, sO_WithoutCoin));
+ setObjectState(sO_RightPipe_17, getObjectEnumState(sO_RightPipe_17, sO_IsClosed));
+ setObjectState(sO_Fly_17, 1);
+ setObjectState(sO_DudeSwinged, 0);
+ setObjectState(sO_Girl, getObjectEnumState(sO_Girl, sO_Swinging));
+ setObjectState(sO_Sugar, getObjectEnumState(sO_Sugar, sO_Present));
+ setObjectState(sO_Janitors, getObjectEnumState(sO_Janitors, sO_Together));
+ setObjectState(sO_Bag_22, getObjectEnumState(sO_Bag_22, sO_NotFallen));
+ setObjectState(sO_Grandpa, getObjectEnumState(sO_Grandpa, sO_InSock));
+ setObjectState(sO_CoinSlot_22, getObjectEnumState(sO_CoinSlot_22, sO_Empty));
+ setObjectState(sO_UpperHatch_23, getObjectEnumState(sO_UpperHatch_23, sO_Closed));
+ setObjectState(sO_LowerHatch_23, getObjectEnumState(sO_LowerHatch_23, sO_Closed));
+ setObjectState(sO_Lever_23, getObjectEnumState(sO_Lever_23, sO_NotTaken));
+ setObjectState(sO_LeverHandle_23, getObjectEnumState(sO_LeverHandle_23, sO_WithoutStool));
+ setObjectState(sO_LowerPipe_21, getObjectEnumState(sO_LowerPipe_21, sO_IsClosed));
+ setObjectState(sO_StarsDown_24, getObjectEnumState(sO_StarsDown_24, sO_OpenedShe));
+ setObjectState(sO_Hatch_26, getObjectEnumState(sO_Hatch_26, sO_Closed));
+ setObjectState(sO_Sock_26, getObjectEnumState(sO_Sock_26, sO_NotHanging));
+ setObjectState(sO_LeftPipe_26, getObjectEnumState(sO_LeftPipe_26, sO_IsClosed));
+ setObjectState(sO_Valve1_26, getObjectEnumState(sO_Valve1_26, sO_Opened));
+ setObjectState(sO_Valve2_26, getObjectEnumState(sO_Valve2_26, sO_Closed));
+ setObjectState(sO_Valve3_26, getObjectEnumState(sO_Valve3_26, sO_Closed));
+ setObjectState(sO_Valve4_26, getObjectEnumState(sO_Valve4_26, sO_Closed));
+ setObjectState(sO_Valve5_26, getObjectEnumState(sO_Valve5_26, sO_Opened));
+ setObjectState(sO_Pool, getObjectEnumState(sO_Pool, sO_Overfull));
+ setObjectState(sO_Plank_25, getObjectEnumState(sO_Plank_25, sO_NearDudesStairs));
+ setObjectState(sO_Driver, getObjectEnumState(sO_Driver, sO_WithSteering));
+ setObjectState(sO_Janitress, getObjectEnumState(sO_Janitress, sO_WithMop));
+ setObjectState(sO_LeftPipe_29, getObjectEnumState(sO_LeftPipe_29, sO_IsClosed));
+ setObjectState(sO_LeftPipe_30, getObjectEnumState(sO_LeftPipe_30, sO_IsClosed));
+ setObjectState(sO_Leg, getObjectEnumState(sO_Leg, sO_ShowingHeel));
+ setObjectState(sO_Tub, getObjectEnumState(sO_Tub, sO_EmptyShe));
+ setObjectState(sO_Cactus, getObjectEnumState(sO_Cactus, sO_NotGrown));
+ setObjectState(sO_Fireman, getObjectEnumState(sO_Fireman, sO_WithHose));
+ setObjectState(sO_Cube, getObjectEnumState(sO_Cube, sO_In_33));
+ setObjectState(sO_MommyOfHandle_32, getObjectEnumState(sO_MommyOfHandle_32, sO_WithoutHandle));
+ setObjectState(sO_Pedestal_33, getObjectEnumState(sO_Pedestal_33, sO_IsFree));
+ setObjectState(sO_Valve_34, getObjectEnumState(sO_Valve_34, sO_WithNothing));
+ setObjectState(sO_Stool_34, getObjectEnumState(sO_Stool_34, sO_WithoutDrawer));
+ setObjectState(sO_Plank_34, getObjectEnumState(sO_Plank_34, sO_Passive));
+ setObjectState(sO_Hatch_34, getObjectEnumState(sO_Hatch_34, sO_Closed));
+ setObjectState(sO_Valve_35, getObjectEnumState(sO_Valve_35, sO_TurnedOff));
+ setObjectState(sO_Carpet_35, getObjectEnumState(sO_Carpet_35, sO_CannotTake));
+ setObjectState(sO_CoinSlot_35, getObjectEnumState(sO_CoinSlot_35, sO_WithCoin));
+ setObjectState(sO_BellyInflater, getObjectEnumState(sO_BellyInflater, sO_WithCork));
+ setObjectState(sO_Jawcrucnher, getObjectEnumState(sO_Jawcrucnher, sO_WithoutCarpet));
+ setObjectState(sO_Guard_1, getObjectEnumState(sO_Guard_1, sO_On));
+ setObjectState(sO_Gurad_2, getObjectEnumState(sO_Gurad_2, sO_On));
+ setObjectState(sO_Guard_3, getObjectEnumState(sO_Guard_3, sO_On));
+ setObjectState(sO_Bottle_38, getObjectEnumState(sO_Bottle_38, sO_OnTheTable));
+ setObjectState(sO_Boss, getObjectEnumState(sO_Boss, sO_WithHammer));
+}
+
+void FullpipeEngine::setLevelStates() {
+ GameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
+
+ if (v) {
+ v->setSubVarAsInt(sO_Level0, 2833);
+ v->setSubVarAsInt(sO_Level1, 2754);
+ v->setSubVarAsInt(sO_Level2, 2757);
+ v->setSubVarAsInt(sO_Level3, 2760);
+ v->setSubVarAsInt(sO_Level4, 2763);
+ v->setSubVarAsInt(sO_Level5, 2766);
+ v->setSubVarAsInt(sO_Level6, 2769);
+ v->setSubVarAsInt(sO_Level7, 2772);
+ v->setSubVarAsInt(sO_Level8, 2775);
+ v->setSubVarAsInt(sO_Level9, 2778);
+ }
+}
+
+void FullpipeEngine::addCursor(CursorInfo *cursorInfo, Scene *inv, int pictureId, int hotspotX, int hotspotY, int itemPictureOffsX, int itemPictureOffsY) {
+ cursorInfo->pictureId = pictureId;
+ cursorInfo->picture = inv->getPictureObjectById(pictureId, 0)->_picture;
+ cursorInfo->hotspotX = hotspotX;
+ cursorInfo->hotspotY = hotspotY;
+ cursorInfo->itemPictureOffsX = itemPictureOffsX;
+ cursorInfo->itemPictureOffsY = itemPictureOffsY;
+
+ getGameLoaderInputController()->addCursor(cursorInfo);
+}
+
+void FullpipeEngine::initCursors() {
+ CursorInfo crs;
+ Scene *inv = accessScene(SC_INV);
+
+ addCursor(&crs, inv, PIC_CSR_DEFAULT, 15, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_DEFAULT_INV, 18, 18, 23, 23);
+ addCursor(&crs, inv, PIC_CSR_ITN, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ITN_RED, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ITN_GREEN, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ITN_INV, 23, 17, 23, 17);
+ addCursor(&crs, inv, PIC_CSR_GOU, 15, 17, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_GOD, 15, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_GOL, 26, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_GOR, 15, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_GOFAR_L, 1, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_GOFAR_R, 39, 1, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE1, 12, 24, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE2, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE2_D, 22, 15, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE3, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE4, 18, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE5, 23, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE6, 11, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE6_D, 0, 0, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE7, 21, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE7_D, 7, 20, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_ARCADE8, 23, 11, 10, 10);
+ addCursor(&crs, inv, PIC_CSR_LIFT, 6, 13, 10, 10);
+
+ getGameLoaderInputController()->setCursorMode(0);
+}
+
+void FullpipeEngine::initMap() {
+ memset(_mapTable, 0, sizeof(_mapTable));
+
+ updateMapPiece(PIC_MAP_S01, 1);
+ updateMapPiece(PIC_MAP_A13, 1u);
+}
+
+void FullpipeEngine::loadAllScenes() {
+ accessScene(301);
+ accessScene(302);
+ accessScene(303);
+ accessScene(304);
+ accessScene(305);
+ accessScene(321);
+ accessScene(635);
+ accessScene(649);
+ accessScene(650);
+ accessScene(651);
+ accessScene(652);
+ accessScene(653);
+ accessScene(654);
+ accessScene(655);
+ accessScene(726);
+ accessScene(858);
+ accessScene(903);
+ accessScene(1137);
+ accessScene(1138);
+ accessScene(1139);
+ accessScene(1140);
+ accessScene(1141);
+ accessScene(1142);
+ accessScene(1143);
+ accessScene(1144);
+ accessScene(1546);
+ accessScene(1547);
+ accessScene(1548);
+ accessScene(1549);
+ accessScene(1550);
+ accessScene(1551);
+ accessScene(1552);
+ accessScene(2062);
+ accessScene(2063);
+ accessScene(2064);
+ accessScene(2065);
+ accessScene(2066);
+ accessScene(2067);
+ accessScene(2068);
+ accessScene(2069);
+ accessScene(2070);
+ accessScene(2071);
+ accessScene(2072);
+ accessScene(2460);
+ accessScene(3896);
+ accessScene(3907);
+ accessScene(4620);
+ accessScene(4999);
+ accessScene(5000);
+ accessScene(5001);
+ accessScene(5166);
+ accessScene(5222);
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/input.cpp b/engines/fullpipe/input.cpp
new file mode 100644
index 0000000000..e98920c78a
--- /dev/null
+++ b/engines/fullpipe/input.cpp
@@ -0,0 +1,277 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/input.h"
+#include "fullpipe/gfx.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/constants.h"
+
+namespace Fullpipe {
+
+InputController::InputController() {
+ g_fullpipe->_inputController = this;
+
+ _flag = 0;
+ _cursorHandle = 0;
+ _hCursor = 0;
+ _field_14 = 0;
+ _cursorId = 0;
+ _cursorIndex = -1;
+ _inputFlags = 1;
+
+ _cursorBounds.left = 0;
+ _cursorBounds.top = 0;
+ _cursorBounds.right = 0;
+ _cursorBounds.bottom = 0;
+
+ _cursorItemPicture = 0;
+}
+
+InputController::~InputController() {
+ removeMessageHandler(126, -1);
+
+ g_fullpipe->_inputController = 0;
+}
+
+void InputController::setInputDisabled(bool state) {
+ _flag = state;
+ g_fullpipe->_inputDisabled = state;
+}
+
+void setInputDisabled(bool state) {
+ g_fullpipe->_inputController->setInputDisabled(state);
+}
+
+void InputController::addCursor(CursorInfo *cursor) {
+ CursorInfo *newc = new CursorInfo(cursor);
+ Common::Point p;
+
+ cursor->picture->getDimensions(&p);
+
+ newc->width = p.x;
+ newc->height = p.y;
+
+ newc->picture->_x = -1;
+ newc->picture->_y = -1;
+
+ _cursorsArray.push_back(newc);
+}
+
+void InputController::setCursorMode(bool enabled) {
+ if (enabled)
+ _inputFlags |= 1;
+ else
+ _inputFlags &= ~1;
+}
+
+void InputController::drawCursor(int x, int y) {
+ if (_cursorIndex == -1)
+ return;
+
+ _cursorBounds.left = g_fullpipe->_sceneRect.left + x - _cursorsArray[_cursorIndex]->hotspotX;
+ _cursorBounds.top = g_fullpipe->_sceneRect.top + y - _cursorsArray[_cursorIndex]->hotspotY;
+ _cursorBounds.right = _cursorBounds.left + _cursorsArray[_cursorIndex]->width;
+ _cursorBounds.bottom = _cursorBounds.top + _cursorsArray[_cursorIndex]->height;
+
+ _cursorsArray[_cursorIndex]->picture->draw(_cursorBounds.left, _cursorBounds.top, 0, 0);
+
+ if (_cursorItemPicture)
+ _cursorItemPicture->draw(_cursorBounds.left + _cursorsArray[_cursorIndex]->itemPictureOffsX,
+ _cursorBounds.top + _cursorsArray[_cursorIndex]->itemPictureOffsY, 0, 0);
+}
+
+void InputController::setCursor(int cursorId) {
+ if (_cursorIndex == -1 || _cursorsArray[_cursorIndex]->pictureId != cursorId) {
+ _cursorIndex = -1;
+
+ for (uint i = 0; i < _cursorsArray.size(); i++) {
+ if (_cursorsArray[i]->pictureId == cursorId) {
+ _cursorIndex = i;
+ break;
+ }
+ }
+ }
+}
+
+CursorInfo::CursorInfo() {
+ pictureId = 0;
+ picture = 0;
+ hotspotX = 0;
+ hotspotY = 0;
+ itemPictureOffsX = 0;
+ itemPictureOffsY = 0;
+ width = 0;
+ height = 0;
+}
+
+CursorInfo::CursorInfo(CursorInfo *src) {
+ pictureId = src->pictureId;
+ picture = src->picture;
+ hotspotX = src->hotspotX;
+ hotspotY = src->hotspotY;
+ itemPictureOffsX = src->itemPictureOffsX;
+ itemPictureOffsY = src->itemPictureOffsY;
+ width = src->width;
+ height = src->height;
+}
+
+void FullpipeEngine::setCursor(int id) {
+ if (_inputController)
+ _inputController->setCursor(id);
+}
+
+const char *input_cheats[] = {
+ "HELP",
+ "STUFF",
+ "FASTER",
+ "OHWAIT",
+ "MUSOFF",
+ ""
+};
+
+void FullpipeEngine::defHandleKeyDown(int key) {
+ if (_currentCheat == -1) {
+ for (int i = 0; input_cheats[i][0]; i++)
+ if (toupper(key) == input_cheats[i][0]) {
+ _currentCheat = i;
+ _currentCheatPos = 1;
+ }
+
+ return;
+ }
+
+ if (toupper(key) != input_cheats[_currentCheat][_currentCheatPos]) {
+ _currentCheat = -1;
+
+ return;
+ }
+
+ _currentCheatPos++;
+
+ if (!input_cheats[_currentCheat][_currentCheatPos]) {
+ switch (_currentCheat) {
+ case 0: // HELP
+ winArcade();
+ break;
+ case 1: // STUFF
+ getAllInventory();
+ break;
+ case 2: // FASTER
+ _normalSpeed = !_normalSpeed;
+ break;
+ case 3: // OHWAIT
+ _gamePaused = 1;
+ _flgGameIsRunning = 0;
+ break;
+ case 4: // MUSOFF
+ if (_musicAllowed & 2)
+ setMusicAllowed(_musicAllowed & 0xFFFFFFFD);
+ else
+ setMusicAllowed(_musicAllowed | 2);
+ break;
+ default:
+ break;
+ }
+
+ _currentCheatPos = 0;
+ _currentCheat = -1;
+ }
+}
+
+void FullpipeEngine::winArcade() {
+ ExCommand *ex = new ExCommand(0, 17, MSG_CMN_WINARCADE, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+
+ ex->postMessage();
+
+}
+
+void FullpipeEngine::updateCursorCommon() {
+ GameObject *ani = _currentScene->getStaticANIObjectAtPos(_mouseVirtX, _mouseVirtY);
+
+ GameObject *pic = _currentScene->getPictureObjectAtPos(_mouseVirtX, _mouseVirtY);
+ if (!ani || (pic && pic->_priority < ani->_priority))
+ ani = pic;
+
+ int selId = getGameLoaderInventory()->getSelectedItemId();
+
+ _objectAtCursor = ani;
+
+ if (ani) {
+ _objectIdAtCursor = ani->_id;
+
+ if (!selId && ani->_id >= _minCursorId && ani->_id <= _maxCursorId) {
+ selId = _objectIdCursors[ani->_id - _minCursorId];
+ if (selId) {
+ _cursorId = selId;
+ return;
+ }
+ }
+ if (canInteractAny(_aniMan, ani, selId)) {
+ _cursorId = selId > 0 ? PIC_CSR_ITN_INV : PIC_CSR_ITN;
+ return;
+ }
+ if (selId) {
+ _cursorId = PIC_CSR_DEFAULT_INV;
+ return;
+ }
+ if (_objectIdAtCursor == ANI_LIFTBUTTON && lift_getButtonIdP(((StaticANIObject *)ani)->_statics->_staticsId)) {
+ _cursorId = PIC_CSR_LIFT;
+ return;
+ }
+ if (_sceneRect.right - _mouseVirtX < 47 && _sceneRect.right < _sceneWidth - 1) {
+ _cursorId = PIC_CSR_GOFAR_R;
+ return;
+ }
+ if (_mouseVirtX - _sceneRect.left < 47 && _sceneRect.left > 0) {
+ _cursorId = PIC_CSR_GOFAR_L;
+ return;
+ }
+ _cursorId = PIC_CSR_DEFAULT;
+ return;
+ } else {
+ _objectIdAtCursor = 0;
+
+ if (selId) {
+ _cursorId = PIC_CSR_DEFAULT_INV;
+ return;
+ }
+ if (_sceneRect.right - _mouseVirtX < 47 && _sceneRect.right < _sceneWidth - 1) {
+ _cursorId = PIC_CSR_GOFAR_R;
+ return;
+ }
+ if (_mouseVirtX - _sceneRect.left < 47 && _sceneRect.left > 0) {
+ _cursorId = PIC_CSR_GOFAR_L;
+ return;
+ }
+ }
+
+ _cursorId = PIC_CSR_DEFAULT;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/input.h b/engines/fullpipe/input.h
new file mode 100644
index 0000000000..bfd547ae2f
--- /dev/null
+++ b/engines/fullpipe/input.h
@@ -0,0 +1,77 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_INPUT_H
+#define FULLPIPE_INPUT_H
+
+namespace Fullpipe {
+
+class Picture;
+
+void setInputDisabled(bool state);
+
+struct CursorInfo {
+ int pictureId;
+ Picture *picture;
+ int hotspotX;
+ int hotspotY;
+ int itemPictureOffsX;
+ int itemPictureOffsY;
+ int width;
+ int height;
+
+ CursorInfo();
+ CursorInfo(CursorInfo *src);
+};
+
+typedef Common::Array<CursorInfo *> CursorsArray;
+
+class InputController {
+ //CObject obj;
+ int _flag;
+ int _inputFlags;
+ int _cursorHandle;
+ int _hCursor;
+ int _field_14;
+ int _cursorId;
+ int _cursorIndex;
+ CursorsArray _cursorsArray;
+ Common::Rect _cursorBounds;
+ Picture *_cursorItemPicture;
+
+ public:
+ InputController();
+ ~InputController();
+
+ void setInputDisabled(bool state);
+ void addCursor(CursorInfo *cursor);
+ void setCursorMode(bool mode);
+
+ void drawCursor(int x, int y);
+ void setCursor(int id);
+
+ void setCursorItemPicture(Picture *pic) { _cursorItemPicture = pic; }
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_INPUT_H */
diff --git a/engines/fullpipe/interaction.cpp b/engines/fullpipe/interaction.cpp
new file mode 100644
index 0000000000..b513d2b8ee
--- /dev/null
+++ b/engines/fullpipe/interaction.cpp
@@ -0,0 +1,528 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/motion.h"
+
+namespace Fullpipe {
+
+int handleObjectInteraction(StaticANIObject *subject, GameObject *object, int invId) {
+ return getGameLoaderInteractionController()->handleInteraction(subject, object, invId);
+}
+
+bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId) {
+ int sceneId = 0;
+
+ if (g_fullpipe->_currentScene)
+ sceneId = g_fullpipe->_currentScene->_sceneId;
+
+ InteractionController *intC = getGameLoaderInteractionController();
+ for (ObList::iterator i = intC->_interactions.begin(); i != intC->_interactions.end(); ++i) {
+ Interaction *intr = (Interaction *)*i;
+
+ if (intr->_sceneId > 0 && intr->_sceneId != sceneId)
+ break;
+
+ if (invId == -3) {
+ invId = getGameLoaderInventory()->getSelectedItemId();
+ }
+ if (intr->canInteract(obj1, obj2, invId))
+ return true;
+ }
+ return false;
+}
+
+bool InteractionController::load(MfcArchive &file) {
+ debug(5, "InteractionController::load()");
+
+ return _interactions.load(file);
+}
+
+int static_compSceneId = 0;
+
+bool InteractionController::compareInteractions(const void *p1, const void *p2) {
+ const Interaction *i1 = (const Interaction *)p1;
+ const Interaction *i2 = (const Interaction *)p2;
+
+ if (i2->_sceneId < i1->_sceneId) {
+ if (i1->_sceneId != static_compSceneId)
+ return false;
+ }
+ if (i2->_sceneId != i1->_sceneId) {
+ if (i1->_sceneId > 0 && i2->_sceneId == static_compSceneId)
+ return false;
+ if (i2->_sceneId != i1->_sceneId)
+ return true;
+ }
+ if (i2->_objectId3 == -1)
+ return true;
+
+ if (i1->_objectId3 == i2->_objectId3)
+ return true;
+
+ if (i1->_objectId3 == -1 || i1->_objectId3 == -2)
+ return false;
+
+ return true;
+}
+
+void InteractionController::sortInteractions(int sceneId) {
+ static_compSceneId = sceneId;
+
+ Common::sort(_interactions.begin(), _interactions.end(), InteractionController::compareInteractions);
+}
+
+bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) {
+ if (subj) {
+ if (!subj->isIdle() || (subj->_flags & 0x100))
+ return false;
+ }
+
+ if (!_interactions.size())
+ return false;
+
+ Interaction *inter = 0;
+ Interaction *previnter = 0;
+ int dur = 0;
+ int mindur = 0xFFFF;
+
+ MessageQueue *mq;
+ ExCommand *ex;
+
+ for (ObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) {
+ Interaction *cinter = (Interaction *)*i;
+
+ if (!cinter->canInteract(subj, obj, invId))
+ continue;
+
+ if ((inter || cinter->_objectId2) && (!obj || cinter->_objectId3 != obj->_id)) {
+ if (cinter->_messageQueue)
+ cinter->_messageQueue->calcDuration(subj);
+
+ PicAniInfo aniInfo;
+
+ obj->getPicAniInfo(&aniInfo);
+
+ if (cinter->_staticsId1) {
+ StaticANIObject *ani = (StaticANIObject *)obj;
+ ani->_messageQueueId = 0;
+ ani->changeStatics2(cinter->_staticsId1);
+ }
+ int xpos = cinter->_xOffs + obj->_ox;
+ int ypos = cinter->_yOffs + obj->_oy;
+
+ obj->setPicAniInfo(&aniInfo);
+
+ if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1) {
+ mq = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->doWalkTo(subj, xpos, ypos, 1, cinter->_staticsId2);
+ if (mq) {
+ dur = mq->calcDuration(subj);
+ delete mq;
+ } else {
+ dur = 0x10000;
+ }
+ inter = previnter;
+ } else {
+ dur = 0;
+ }
+ if (dur < mindur) {
+ inter = cinter;
+ mindur = dur;
+ previnter = cinter;
+ }
+ } else {
+ inter = cinter;
+ break;
+ }
+ }
+
+ if (!inter)
+ return false;
+
+ if (!inter->_objectId2) {
+ StaticANIObject *ani = (StaticANIObject *)obj;
+
+ if (!ani->isIdle())
+ return false;
+
+ if (ani->_flags & 0x100)
+ return false;
+
+ if (!inter->_staticsId1 || !(inter->_flags & 1))
+ goto LABEL_38;
+
+ if (ani->_movement || ani->_statics == 0 || ani->_statics->_staticsId != inter->_staticsId1) {
+ mq = ani->changeStatics1(inter->_staticsId1);
+ if (!mq)
+ return false;
+
+ ex = new ExCommand((subj ? subj->_id : 0), 55, 0, 0, 0, 0, 1, 0, 0, 0);
+ ex->_x = obj->_id;
+ ex->_y = obj->_okeyCode;
+ ex->_keyCode = subj ? subj->_okeyCode : 0;
+ ex->_excFlags = 3;
+ ex->_field_14 = (obj->_objtype != kObjTypePictureObject);
+ ex->_field_20 = invId;
+ mq->_exCommands.push_back(ex);
+
+ if (mq->_isFinished) {
+ mq->_isFinished = 0;
+ ani->queueMessageQueue(mq);
+ }
+ } else {
+ if (ani->getMessageQueue())
+ ani->queueMessageQueue(0);
+LABEL_38:
+ if (inter->_messageQueue) {
+ mq = new MessageQueue(inter->_messageQueue, 0, 1);
+ mq->changeParam28ForObjectId(ani->_id, -1, ani->_okeyCode);
+
+ if (!mq->chain(0))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (obj && !subj)
+ return true;
+
+ if (!obj || inter->_objectId3 == obj->_id) {
+ if (subj) {
+ if (inter->_messageQueue) {
+ if (subj->isIdle()) {
+ mq = new MessageQueue(inter->_messageQueue, 0, 1);
+
+ if (!mq->chain(subj)) {
+ delete mq;
+
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ if (inter->isOverlapping(subj, obj)) {
+ if (obj->_objtype == kObjTypeStaticANIObject) {
+ StaticANIObject *ani = (StaticANIObject *)obj;
+
+ ani->queueMessageQueue(0);
+
+ if (inter->_staticsId1)
+ ani->changeStatics2(inter->_staticsId1);
+
+ if (!(inter->_flags & 0x10000))
+ obj->_flags |= 0x80;
+ }
+
+ if (!inter->_messageQueue)
+ return false;
+
+ subj->setOXY(inter->_xOffs + obj->_ox, inter->_yOffs + obj->_oy);
+
+ mq = new MessageQueue(inter->_messageQueue, 0, 1);
+ mq->changeParam28ForObjectId(obj->_id, -1, obj->_okeyCode);
+ mq->_flags |= 1;
+
+ if (!(inter->_flags & 0x10000)) {
+ ex = new ExCommand(obj->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = obj->_okeyCode;
+ ex->_field_14 = 0x100;
+ ex->_messageNum = 0;
+ ex->_excFlags = 3;
+ mq->_exCommands.push_back(ex);
+ }
+
+ ex = new ExCommand(obj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = obj->_okeyCode;
+ ex->_field_14 = 0x100;
+ ex->_messageNum = 0;
+ ex->_excFlags = 3;
+ mq->_exCommands.push_back(ex);
+
+ ex = new ExCommand(subj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = subj->_okeyCode;
+ ex->_field_14 = 0x100;
+ ex->_messageNum = 0;
+ ex->_excFlags = 3;
+ mq->_exCommands.push_back(ex);
+
+ ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ ex->_keyCode = 0;
+ mq->_exCommands.push_back(ex);
+
+ if (!mq->chain(subj)) {
+ delete mq;
+
+ return false;
+ }
+
+ subj->_flags |= 1;
+ obj->_flags |= 1;
+ } else {
+ bool someFlag = false;
+ PicAniInfo aniInfo;
+
+ obj->getPicAniInfo(&aniInfo);
+
+ if (obj->_objtype == kObjTypeStaticANIObject && inter->_staticsId1) {
+ StaticANIObject *ani = (StaticANIObject *)obj;
+
+ ani->_messageQueueId = 0;
+ ani->changeStatics2(inter->_staticsId1);
+ }
+
+ int xpos = inter->_yOffs + obj->_ox;
+ int ypos = inter->_yOffs + obj->_oy;
+
+ obj->setPicAniInfo(&aniInfo);
+
+ if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1
+ || (inter->_staticsId2 != 0 && (subj->_statics == 0 || subj->_statics->_staticsId != inter->_staticsId2))) {
+ mq = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->method34(subj, xpos, ypos, 1, inter->_staticsId2);
+
+ if (!mq)
+ return false;
+
+ ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0);
+ ex->_x = obj->_id;
+ ex->_y = obj->_okeyCode;
+ ex->_keyCode = subj->_okeyCode;
+ ex->_excFlags = 3;
+ ex->_field_20 = invId;
+ ex->_field_14 = (obj->_objtype != kObjTypePictureObject);
+ mq->_exCommands.push_back(ex);
+
+ someFlag = true;
+
+ ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0);
+ ex->_x = xpos;
+ ex->_y = ypos;
+ ex->_excFlags |= 3;
+ ex->_keyCode = 6;
+ ex->_field_14 = obj->_id;
+ ex->_field_20 = obj->_okeyCode;
+ ex->postMessage();
+ }
+
+ if (!inter->_staticsId1 || !(inter->_flags & 1))
+ return true;
+
+ StaticANIObject *ani = (StaticANIObject *)obj;
+
+ if (!ani->isIdle())
+ return false;
+
+ if (ani->getMessageQueue())
+ ani->queueMessageQueue(0);
+
+ if (!ani->_statics || ani->_statics->_staticsId != inter->_staticsId1 || ani->_movement) {
+ mq = ani->changeStatics1(inter->_staticsId1);
+
+ if (!mq)
+ return false;
+
+ if (someFlag) {
+ if (!(inter->_flags & 0x10000)) {
+ if (mq->_isFinished) {
+ ani->_flags |= 0x80u;
+ } else {
+ ex = new ExCommand(ani->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0);
+ ex->_field_14 = 0x80;
+ ex->_keyCode = ani->_okeyCode;
+ ex->_excFlags = 3;
+ mq->_exCommands.push_back(ex);
+ }
+ }
+ ex = new ExCommand(ani->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = ani->_okeyCode;
+ ex->_field_14 = 0x100;
+ ex->_excFlags = 3;
+ mq->_exCommands.push_back(ex);
+ } else {
+ ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0);
+ ex->_x = ani->_id;
+ ex->_y = ani->_okeyCode;
+ ex->_keyCode = subj->_okeyCode;
+ ex->_excFlags = 2;
+ ex->_field_14 = (obj->_objtype != kObjTypePictureObject);
+ ex->_field_20 = invId;
+ mq->_exCommands.push_back(ex);
+
+ if (!mq->_isFinished)
+ return true;
+
+ mq->_isFinished = 0;
+ ani->queueMessageQueue(mq);
+ }
+ } else {
+ obj->_flags |= 1;
+
+ if (inter->_flags & 0x10000)
+ return true;
+
+ obj->_flags |= 0x80;
+ }
+ }
+
+ return true;
+}
+
+Interaction *InteractionController::getInteractionByObjectIds(int obId, int obId2, int obId3) {
+ for (ObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) {
+ Interaction *intr = (Interaction *)*i;
+
+ if (intr->_objectId1 == obId && intr->_objectId2 == obId2 && intr->_objectId3 == obId3)
+ return intr;
+ }
+
+ return 0;
+}
+
+Interaction::Interaction() {
+ _objectId1 = 0;
+ _objectId2 = 0;
+ _staticsId1 = 0;
+ _objectId3 = 0;
+ _objectState2 = 0;
+ _objectState1 = 0;
+ _messageQueue = 0;
+ _flags = 0;
+ _yOffs = 0;
+ _xOffs = 0;
+ _staticsId2 = 0;
+ _field_28 = 0;
+ _sceneId = -1;
+ _actionName = 0;
+}
+
+bool Interaction::load(MfcArchive &file) {
+ debug(5, "Interaction::load()");
+
+ _objectId1 = file.readUint16LE();
+ _objectId2 = file.readUint16LE();
+ _staticsId1 = file.readUint16LE();
+ _staticsId2 = file.readUint16LE();
+ _objectId3 = file.readUint16LE();
+ _objectState2 = file.readUint32LE();
+ _objectState1 = file.readUint32LE();
+ _xOffs = file.readUint32LE();
+ _yOffs = file.readUint32LE();
+ _sceneId = file.readUint32LE();
+ _flags = file.readUint32LE();
+ _actionName = file.readPascalString();
+
+ _messageQueue = (MessageQueue *)file.readClass();
+
+ return true;
+}
+
+bool Interaction::canInteract(GameObject *obj1, GameObject *obj2, int invId) {
+ if (_sceneId > 0 && g_fullpipe->_currentScene && g_fullpipe->_currentScene->_sceneId != _sceneId)
+ return false;
+
+ if (_flags & 0x20000)
+ return false;
+
+ if (!obj2)
+ return false;
+
+ if (obj2->_id != _objectId1)
+ return false;
+
+ if ((_flags & 8) && (_flags & 1)) {
+ if (obj2->_objtype != kObjTypeStaticANIObject)
+ return false;
+
+ StaticANIObject *st = (StaticANIObject *)obj2;
+
+ if (!st->_statics)
+ return false;
+
+ if (st->_statics->_staticsId != _staticsId1) {
+ if (_staticsId1)
+ return false;
+ }
+ }
+
+ if ((_objectId3 != invId && _objectId3 != -1 && _objectId3 != -2) || (!invId && _objectId3 == -2))
+ return false;
+
+ if (_objectState1) {
+ if (_flags & 0x10) {
+ if ((g_fullpipe->getObjectState(obj1->getName()) & _objectState1) == 0)
+ return false;
+ } else {
+ if (g_fullpipe->getObjectState(obj1->getName()) != _objectState1)
+ return false;
+ }
+ }
+
+ if (_objectState2) {
+ if (_flags & 0x10) {
+ if ((g_fullpipe->getObjectState(obj2->getName()) & _objectState2) == 0)
+ return false;
+ } else {
+ if (g_fullpipe->getObjectState(obj2->getName()) != _objectState2)
+ return false;
+ }
+ }
+
+ if (_objectId2 && (!obj1 || _objectId2 != obj1->_id))
+ return false;
+
+ return true;
+}
+
+bool Interaction::isOverlapping(StaticANIObject *subj, GameObject *obj) {
+ StaticANIObject *ani = (StaticANIObject *)obj;
+
+ if (abs(_xOffs + obj->_ox - subj->_ox) <= 1
+ && abs(obj->_oy + _yOffs - subj->_oy) <= 1) {
+ if (!_staticsId2 || (subj->_statics != 0 && subj->_statics->_staticsId == _staticsId2)) {
+ if (!_staticsId1 || !(_flags & 1) || (ani->_statics != 0 && ani->_statics->_staticsId == _staticsId1))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool EntranceInfo::load(MfcArchive &file) {
+ debug(5, "EntranceInfo::load()");
+
+ _sceneId = file.readUint32LE();
+ _field_4 = file.readUint32LE();
+ _messageQueueId = file.readUint32LE();
+ file.read(_gap_C, 292); // FIXME, Ugh
+ _field_130 = file.readUint32LE();
+
+ return true;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/interaction.h b/engines/fullpipe/interaction.h
new file mode 100644
index 0000000000..456b35458b
--- /dev/null
+++ b/engines/fullpipe/interaction.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.
+ *
+ */
+
+#ifndef FULLPIPE_INTERACTION_H
+#define FULLPIPE_INTERACTION_H
+
+#include "fullpipe/utils.h"
+
+namespace Fullpipe {
+
+class GameObject;
+class MessageQueue;
+class StaticANIObject;
+
+int handleObjectInteraction(StaticANIObject *subject, GameObject *object, int invId);
+bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId);
+
+
+class Interaction : public CObject {
+ public:
+ int16 _objectId1;
+ int16 _objectId2;
+ int16 _objectId3;
+ int16 _staticsId1;
+ int16 _staticsId2;
+ int _objectState1;
+ int _objectState2;
+ int _xOffs;
+ int _yOffs;
+ MessageQueue *_messageQueue;
+ int _sceneId;
+ int _field_28;
+ int _flags;
+ char *_actionName;
+
+ public:
+ Interaction();
+ virtual bool load(MfcArchive &file);
+ bool canInteract(GameObject *obj1, GameObject *obj2, int invId);
+ bool isOverlapping(StaticANIObject *subj, GameObject *obj);
+};
+
+class InteractionController : public CObject {
+ public:
+ ObList _interactions;
+ int16 _field_20;
+ bool _flag24;
+
+ private:
+ static bool compareInteractions(const void *p1, const void *p2);
+
+ public:
+ InteractionController() : _field_20(0), _flag24(true) {}
+
+ virtual bool load(MfcArchive &file);
+
+ void enableFlag24() { _flag24 = true; }
+ void disableFlag24() { _flag24 = false; }
+
+ void sortInteractions(int sceneId);
+
+ bool handleInteraction(StaticANIObject *subj, GameObject *obj, int invId);
+
+ Interaction *getInteractionByObjectIds(int obId, int obId2, int obId3);
+};
+
+struct EntranceInfo {
+ int32 _sceneId;
+ int32 _field_4;
+ int32 _messageQueueId;
+ byte _gap_C[292]; // FIXME
+ int32 _field_130;
+
+ bool load(MfcArchive &file);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_INTERACTION_H */
diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp
new file mode 100644
index 0000000000..18ef3c4d97
--- /dev/null
+++ b/engines/fullpipe/inventory.cpp
@@ -0,0 +1,437 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/utils.h"
+#include "fullpipe/inventory.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/input.h"
+
+namespace Fullpipe {
+
+bool Inventory::load(MfcArchive &file) {
+ debug(5, "Inventory::load()");
+
+ _sceneId = file.readUint16LE();
+ int numInvs = file.readUint32LE();
+
+ for (int i = 0; i < numInvs; i++) {
+ InventoryPoolItem *t = new InventoryPoolItem();
+ t->id = file.readUint16LE();
+ t->pictureObjectNormal = file.readUint16LE();
+ t->pictureObjectId1 = file.readUint16LE();
+ t->pictureObjectHover = file.readUint16LE();
+ t->pictureObjectSelected = file.readUint16LE();
+ t->flags = file.readUint32LE();
+ t->field_C = 0;
+ t->field_A = -536;
+ _itemsPool.push_back(t);
+ }
+
+ return true;
+}
+
+int Inventory::getInventoryPoolItemIndexById(int itemId) {
+ if (_itemsPool.size() <= 0)
+ return -1;
+
+ for (uint i = 0; i < _itemsPool.size(); i++) {
+ if (_itemsPool[i]->id == itemId)
+ return i;
+ }
+
+ return 0;
+}
+
+bool Inventory::setItemFlags(int itemId, int flags) {
+ int idx = getInventoryPoolItemIndexById(itemId);
+
+ if (idx < 0)
+ return false;
+ else
+ _itemsPool[idx]->flags = flags;
+
+ return true;
+}
+
+Inventory2::Inventory2() {
+ _selectedId = -1;
+ _field_48 = -1;
+ _scene = 0;
+ _picture = 0;
+ _isInventoryOut = false;
+ _isLocked = 0;
+ _topOffset = -65;
+}
+
+bool Inventory2::loadPartial(MfcArchive &file) { // Inventory2_SerializePartially
+ int numInvs = file.readUint32LE();
+
+ for (int i = 0; i < numInvs; i++) {
+ InventoryItem *t = new InventoryItem();
+ t->itemId = file.readUint16LE();
+ t->count = file.readUint16LE();
+ _inventoryItems.push_back(t);
+ }
+
+ return true;
+}
+
+void Inventory2::addItem(int itemId, int count) {
+ if (getInventoryPoolItemIndexById(itemId) >= 0)
+ _inventoryItems.push_back(new InventoryItem(itemId, count));
+}
+
+void Inventory2::addItem2(StaticANIObject *obj) {
+ if (getInventoryPoolItemIndexById(obj->_id) >= 0 && getInventoryPoolItemFieldCById(obj->_id) != 2) {
+ addItem(obj->_id, 1);
+ obj->hide();
+ }
+}
+
+void Inventory2::removeItem(int itemId, int count) {
+ warning("STUB: Inventory2::removeItem(%d, %d)", itemId, count);
+}
+
+void Inventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority) {
+ warning("STUB: void removeItem2(sc, %d, %d, %d, %d)", itemId, x, y, priority);
+}
+
+int Inventory2::getCountItemsWithId(int itemId) {
+ int res = 0;
+
+ for (uint i = 0; i < _inventoryItems.size(); i++) {
+ if (_inventoryItems[i]->itemId == itemId)
+ res += _inventoryItems[i]->count;
+ }
+
+ return res;
+}
+
+int Inventory2::getInventoryItemIndexById(int itemId) {
+ for (uint i = 0; i < _inventoryItems.size(); i++) {
+ if (_inventoryItems[i]->itemId == itemId)
+ return i;
+ }
+
+ return -1;
+}
+
+int Inventory2::getInventoryPoolItemIdAtIndex(int itemId) {
+ return _itemsPool[itemId]->id;
+}
+
+int Inventory2::getInventoryPoolItemFieldCById(int itemId) {
+ for (uint i = 0; i < _itemsPool.size(); i++) {
+ if (_itemsPool[i]->id == itemId)
+ return _itemsPool[i]->field_C;
+ }
+
+ return 0;
+}
+
+int Inventory2::getItemFlags(int itemId) {
+ int idx = getInventoryPoolItemIndexById(itemId);
+
+ if (idx < 0)
+ return 0;
+
+ return _itemsPool[idx]->flags;
+}
+
+void Inventory2::rebuildItemRects() {
+ _scene = g_fullpipe->accessScene(_sceneId);
+
+ if (!_scene)
+ return;
+
+ _picture = _scene->getBigPicture(0, 0);
+ _picture->setAlpha(50);
+
+ int itemX = 9;
+ int itemY = 0;
+
+ for (uint i = 0; i < _scene->_picObjList.size(); i++) {
+ PictureObject *pic = (PictureObject *)_scene->_picObjList[i];
+
+ for (uint j = 0; j < _itemsPool.size(); j++) {
+ if (_itemsPool[j]->pictureObjectNormal == pic->_id) {
+ if (pic->_okeyCode)
+ _scene->deletePictureObject(pic);
+ else
+ pic->_flags &= 0xFFFB;
+ }
+ }
+ }
+
+ for (uint i = 0; i < _inventoryItems.size(); i++) {
+ Common::Point point;
+
+ int idx = getInventoryPoolItemIndexById(_inventoryItems[i]->itemId);
+
+ InventoryIcon *icn = new InventoryIcon();
+
+ icn->inventoryItemId = _itemsPool[idx]->id;
+
+ icn->pictureObjectNormal = _scene->getPictureObjectById(_itemsPool[idx]->pictureObjectNormal, 0);
+ icn->pictureObjectHover = _scene->getPictureObjectById(_itemsPool[idx]->pictureObjectHover, 0);
+ icn->pictureObjectSelected = _scene->getPictureObjectById(_itemsPool[idx]->pictureObjectSelected, 0);
+
+ icn->pictureObjectNormal->getDimensions(&point);
+
+ if (_itemsPool[idx]->flags & 0x10000) {
+ icn->x1 = 730;
+ icn->y1 = itemY;
+ icn->x2 = point.x + 730;
+ icn->y2 = point.y + itemY + 10;
+ } else {
+ icn->x1 = itemX;
+ icn->y1 = itemY;
+ icn->x2 = itemX + point.x;
+ itemX = icn->x2 + 1;
+ icn->y2 = point.y + itemY + 10;
+ }
+
+ _inventoryIcons.push_back(icn);
+
+ if (itemX >= 2 * (icn->x1 - icn->x2) + 800) {
+ itemX = 9;
+ itemY = icn->y2 + 1;
+ }
+ }
+}
+
+void Inventory2::draw() {
+ if (!_scene)
+ return;
+
+ int oldScLeft = g_fullpipe->_sceneRect.left;
+ int oldScTop = g_fullpipe->_sceneRect.top;
+
+ g_fullpipe->_sceneRect.top = -_topOffset;
+ g_fullpipe->_sceneRect.left = 0;
+
+ _picture->draw(-1, -1, 0, 0);
+
+ for (uint i = 0; i < _inventoryIcons.size(); i++) {
+ InventoryIcon *icn = _inventoryIcons[i];
+
+ if (icn->isSelected) {
+ icn->pictureObjectSelected->drawAt(icn->x1, icn->y1 + 10);
+ } else {
+ if (icn->isMouseHover)
+ icn->pictureObjectHover->drawAt(icn->x1, icn->y1 + 10);
+ else
+ icn->pictureObjectNormal->drawAt(icn->x1, icn->y1 + 10);
+ }
+ }
+
+ if (!_isInventoryOut)
+ goto LABEL_30;
+
+ int v10, v11, v12;
+
+ if (_topOffset != -10) {
+ if (_topOffset < -10) {
+ v10 = -10;
+ goto LABEL_13;
+ }
+ if (_topOffset + 10 >= 20) {
+ v11 = -20;
+cont:
+ _topOffset += v11;
+ goto reset;
+ }
+ v12 = -10;
+ goto LABEL_25;
+ }
+ if (!_isInventoryOut) {
+LABEL_30:
+ if (_topOffset != -65) {
+ if (_topOffset < -65) {
+ v10 = -65;
+LABEL_13:
+ v11 = v10 - _topOffset;
+ if (v11 >= 20)
+ v11 = 20;
+ goto cont;
+ }
+ if (_topOffset + 65 >= 20) {
+ v11 = -20;
+ goto cont;
+ }
+ v12 = -65;
+LABEL_25:
+ v11 = v12 - _topOffset;
+ goto cont;
+ }
+ }
+
+reset:
+
+ g_fullpipe->_sceneRect.top = oldScTop;
+ g_fullpipe->_sceneRect.left = oldScLeft;
+
+}
+
+void Inventory2::slideIn() {
+ _isInventoryOut = false;
+
+ ExCommand *ex = new ExCommand(0, 17, 65, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_2C = 10;
+ ex->_field_14 = _isInventoryOut;
+ ex->_field_20 = !_isInventoryOut;
+ ex->_excFlags |= 3;
+ ex->postMessage();
+}
+
+void Inventory2::slideOut() {
+ _isInventoryOut = true;
+
+ ExCommand *ex = new ExCommand(0, 17, 65, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_2C = 10;
+ ex->_field_14 = _isInventoryOut;
+ ex->_field_20 = !_isInventoryOut;
+ ex->_excFlags |= 3;
+ ex->postMessage();
+}
+
+bool Inventory2::handleLeftClick(ExCommand *cmd) {
+ if (!_isInventoryOut)
+ return false;
+
+ bool res = false;
+
+ for (uint i = 0; i < _inventoryIcons.size(); i++) {
+ if (cmd->_x >= _inventoryIcons[i]->x1 && cmd->_x <= _inventoryIcons[i]->x2 &&
+ cmd->_y >= _inventoryIcons[i]->y1 && cmd->_y <= _inventoryIcons[i]->y2) {
+ if (getSelectedItemId()) {
+ if (getSelectedItemId() != _inventoryIcons[i]->inventoryItemId)
+ unselectItem(0);
+ }
+ if (getItemFlags(_inventoryIcons[i]->inventoryItemId) & 1) {
+ ExCommand *ex = new ExCommand(0, 17, 65, 0, 0, 0, 1, 0, 0, 0);
+ ex->_field_2C = 11;
+ ex->_field_14 = _inventoryIcons[i]->inventoryItemId;
+ ex->_excFlags |= 3;
+ ex->postMessage();
+ }
+ if (!(getItemFlags(_inventoryIcons[i]->inventoryItemId) & 2)) {
+ selectItem(_inventoryIcons[i]->inventoryItemId);
+ _inventoryIcons[i]->isSelected = true;
+ }
+ res = true;
+ }
+ }
+
+ if (!res)
+ unselectItem(0);
+
+ return res;
+}
+
+int Inventory2::selectItem(int itemId) {
+ if (getInventoryItemIndexById(itemId) < 0)
+ return -1;
+
+ unselectItem(0);
+
+ _selectedId = itemId;
+
+ if (_scene) {
+ int idx = getInventoryPoolItemIndexById(itemId);
+
+ Picture *pic = _scene->getPictureObjectById(_itemsPool[idx]->pictureObjectId1, 0)->_picture;
+ g_fullpipe->getGameLoaderInputController()->setCursorItemPicture(pic);
+ }
+
+ return _selectedId;
+}
+
+bool Inventory2::unselectItem(bool flag) {
+ if (_selectedId < 0)
+ return false;
+
+ _selectedId = -1;
+
+ for (uint i = 0; i < _inventoryIcons.size(); i++) {
+ if (_inventoryIcons[i]->isSelected)
+ _inventoryIcons[i]->isSelected = false;
+ }
+
+ g_fullpipe->getGameLoaderInputController()->setCursorItemPicture(0);
+
+ return true;
+}
+
+int Inventory2::getHoveredItem(Common::Point *point) {
+ int selId = getSelectedItemId();
+
+ if (point->y <= 20 && !_isInventoryOut && !_isLocked)
+ slideOut();
+
+ if (!selId && point->y >= 55) {
+ if (!_isInventoryOut)
+ return 0;
+
+ if (!_isLocked)
+ slideIn();
+ }
+
+ if (!_isInventoryOut)
+ return 0;
+
+ for (uint i = 0; i < _inventoryIcons.size(); i++) {
+ InventoryIcon *icn = _inventoryIcons[i];
+ if (selId ||
+ point->x < icn->x1 ||
+ point->x > icn->x2 ||
+ point->y < _topOffset + icn->y1 ||
+ point->y > _topOffset + icn->y2) {
+ icn->isMouseHover = false;
+ } else {
+ icn->isMouseHover = true;
+ return icn->inventoryItemId;
+ }
+ }
+
+ return 0;
+}
+
+void FullpipeEngine::getAllInventory() {
+ Inventory2 *inv = getGameLoaderInventory();
+
+ for (uint i = 0; i < inv->getItemsPoolCount(); ++i ) {
+ int id = inv->getInventoryPoolItemIdAtIndex(i);
+
+ if (inv->getCountItemsWithId(id) < 1)
+ inv->addItem(id, 1);
+ }
+
+ inv->rebuildItemRects();
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/inventory.h b/engines/fullpipe/inventory.h
new file mode 100644
index 0000000000..6d07f069bd
--- /dev/null
+++ b/engines/fullpipe/inventory.h
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_INVENTORY_H
+#define FULLPIPE_INVENTORY_H
+
+namespace Fullpipe {
+
+class Scene;
+class BigPicture;
+
+struct InventoryPoolItem {
+ int16 id;
+ int16 pictureObjectNormal;
+ int16 pictureObjectId1;
+ int16 pictureObjectHover;
+ int16 pictureObjectSelected;
+ int16 field_A;
+ int field_C;
+ int obj;
+ int flags;
+};
+
+typedef Common::Array<InventoryPoolItem *> InventoryPoolItems;
+
+class Inventory : public CObject {
+ protected:
+ int16 _sceneId;
+ InventoryPoolItems _itemsPool;
+
+ public:
+ Inventory() { _sceneId = 0; }
+ virtual bool load(MfcArchive &file);
+
+ int getInventoryPoolItemIndexById(int itemId);
+ uint getItemsPoolCount() { return _itemsPool.size(); }
+ bool setItemFlags(int itemId, int flags);
+};
+
+struct InventoryItem {
+ int16 itemId;
+ int16 count;
+
+ InventoryItem() { itemId = count = 0; }
+ InventoryItem(int id, int cnt) : itemId(id), count(cnt) {}
+};
+
+typedef Common::Array<InventoryItem *> InventoryItems;
+
+class PictureObject;
+
+struct InventoryIcon {
+ PictureObject *pictureObjectNormal;
+ PictureObject *pictureObjectHover;
+ PictureObject *pictureObjectSelected;
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ int16 inventoryItemId;
+ bool isSelected;
+ bool isMouseHover;
+};
+
+typedef Common::Array<InventoryIcon *> InventoryIcons;
+
+class Inventory2 : public Inventory {
+ InventoryItems _inventoryItems;
+ InventoryIcons _inventoryIcons;
+ int _selectedId;
+ int _field_48;
+ bool _isInventoryOut;
+ bool _isLocked;
+ int _topOffset;
+ Scene *_scene;
+ BigPicture *_picture;
+
+ public:
+ Inventory2();
+ bool loadPartial(MfcArchive &file);
+ void addItem(int itemId, int count);
+ void addItem2(StaticANIObject *obj);
+ void removeItem(int itemId, int count);
+ void removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority);
+
+ int getInventoryItemIndexById(int itemId);
+ int getInventoryPoolItemIdAtIndex(int itemId);
+ int getInventoryPoolItemFieldCById(int itemId);
+ int getCountItemsWithId(int itemId);
+ int getItemFlags(int itemId);
+
+ void rebuildItemRects();
+
+ Scene *getScene() { return _scene; }
+ bool getIsLocked() { return _isLocked; }
+ void setIsLocked(bool val) { _isLocked = val; }
+ bool getIsInventoryOut() { return _isInventoryOut; }
+
+ int getSelectedItemId() { return _selectedId < 0 ? 0 : _selectedId; }
+ int getHoveredItem(Common::Point *point);
+ void slideIn();
+ void slideOut();
+
+ bool handleLeftClick(ExCommand *cmd);
+ int selectItem(int itemId);
+ bool unselectItem(bool flag);
+
+ void draw();
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_INVENTORY_H */
diff --git a/engines/fullpipe/lift.cpp b/engines/fullpipe/lift.cpp
new file mode 100644
index 0000000000..1d6d986977
--- /dev/null
+++ b/engines/fullpipe/lift.cpp
@@ -0,0 +1,108 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+namespace Fullpipe {
+
+int FullpipeEngine::lift_getButtonIdP(int objid) {
+ switch (objid) {
+ case ST_LBN_0N:
+ return ST_LBN_0P;
+ break;
+ case ST_LBN_1N:
+ return ST_LBN_1P;
+ break;
+ case ST_LBN_2N:
+ return ST_LBN_2P;
+ break;
+ case ST_LBN_3N:
+ return ST_LBN_3P;
+ break;
+ case ST_LBN_4N:
+ return ST_LBN_4P;
+ break;
+ case ST_LBN_5N:
+ return ST_LBN_5P;
+ break;
+ case ST_LBN_6N:
+ return ST_LBN_6P;
+ break;
+ case ST_LBN_7N:
+ return ST_LBN_7P;
+ break;
+ case ST_LBN_8N:
+ return ST_LBN_8P;
+ break;
+ case ST_LBN_9N:
+ return ST_LBN_9P;
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+void FullpipeEngine::lift_setButton(const char *name, int state) {
+ GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
+
+ if (var)
+ var->setSubVarAsInt(name, state);
+}
+
+void FullpipeEngine::lift_sub5(Scene *sc, int qu1, int qu2) {
+ warning("STUB: FullpipeEngine::lift_sub5()");
+}
+
+void FullpipeEngine::lift_exitSeq(ExCommand *ex) {
+ warning("STUB: FullpipeEngine::lift_exitSeq()");
+}
+
+void FullpipeEngine::lift_closedoorSeq() {
+ warning("STUB: FullpipeEngine::lift_closedoorSeq()");
+}
+
+void FullpipeEngine::lift_animation3() {
+ warning("STUB: FullpipeEngine::lift_animation3()");
+}
+
+void FullpipeEngine::lift_goAnimation() {
+ warning("STUB: FullpipeEngine::lift_goAnimation()");
+}
+
+void FullpipeEngine::lift_sub1(StaticANIObject *ani) {
+ warning("STUB: FullpipeEngine::lift_sub1()");
+}
+
+void FullpipeEngine::lift_startExitQueue() {
+ warning("STUB: FullpipeEngine::lift_startExitQueue()");
+}
+
+void FullpipeEngine::lift_sub05(ExCommand *ex) {
+ warning("STUB: FullpipeEngine::lift_sub05()");
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp
new file mode 100644
index 0000000000..fc57109f07
--- /dev/null
+++ b/engines/fullpipe/messagehandlers.cpp
@@ -0,0 +1,743 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/messages.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/input.h"
+
+#include "fullpipe/constants.h"
+
+namespace Fullpipe {
+
+void global_messageHandler_KickStucco() {
+ warning("STUB: global_messageHandler_KickStucco()");
+}
+
+void global_messageHandler_KickMetal() {
+ warning("STUB: global_messageHandler_KickMetal()");
+}
+
+int global_messageHandler1(ExCommand *cmd) {
+ debug(0, "global_messageHandler1: %d %d", cmd->_messageKind, cmd->_messageNum);
+
+ if (cmd->_excFlags & 0x10000) {
+ if (cmd->_messageNum == MV_MAN_TOLADDER)
+ cmd->_messageNum = MV_MAN_TOLADDER2;
+ if (cmd->_messageNum == MV_MAN_STARTLADDER)
+ cmd->_messageNum = MV_MAN_STARTLADDER2;
+ if (cmd->_messageNum == MV_MAN_GOLADDER)
+ cmd->_messageNum = MV_MAN_GOLADDER2;
+ if (cmd->_messageNum == MV_MAN_STOPLADDER)
+ cmd->_messageNum = MV_MAN_STOPLADDER2;
+ }
+
+ if (g_fullpipe->_inputDisabled) {
+ if (cmd->_messageKind == 17) {
+ switch (cmd->_messageNum) {
+ case 29:
+ case 30:
+ case 36:
+ case 106:
+ cmd->_messageKind = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ } else if (cmd->_messageKind == 17) {
+ switch (cmd->_messageNum) {
+ case MSG_MANSHADOWSON:
+ g_fullpipe->_aniMan->_shadowsOn = 1;
+ break;
+ case MSG_HMRKICK_STUCCO:
+ global_messageHandler_KickStucco();
+ break;
+ case MSG_MANSHADOWSOFF:
+ g_fullpipe->_aniMan->_shadowsOn = 0;
+ break;
+ case MSG_DISABLESAVES:
+ g_fullpipe->disableSaves(cmd);
+ break;
+ case MSG_ENABLESAVES:
+ g_fullpipe->enableSaves();
+ break;
+ case MSG_HMRKICK_METAL:
+ global_messageHandler_KickMetal();
+ break;
+ case 29: // left mouse
+ if (g_fullpipe->_inventoryScene) {
+ if (getGameLoaderInventory()->handleLeftClick(cmd))
+ cmd->_messageKind = 0;
+ }
+ break;
+ case 107: // right mouse
+ if (getGameLoaderInventory()->getSelectedItemId()) {
+ getGameLoaderInventory()->unselectItem(0);
+ cmd->_messageKind = 0;
+ }
+ break;
+ case 36: // keydown
+ g_fullpipe->defHandleKeyDown(cmd->_keyCode);
+
+ switch (cmd->_keyCode) {
+ case '\x1B': // ESC
+ if (g_fullpipe->_currentScene) {
+ getGameLoaderInventory()->unselectItem(0);
+ g_fullpipe->openMainMenu();
+ cmd->_messageKind = 0;
+ }
+ break;
+ case 't':
+ g_fullpipe->stopAllSounds();
+ cmd->_messageKind = 0;
+ break;
+ case 'u':
+ g_fullpipe->toggleMute();
+ cmd->_messageKind = 0;
+ break;
+ case ' ':
+ if (getGameLoaderInventory()->getIsLocked()) {
+ if (getGameLoaderInventory()->getIsInventoryOut()) {
+ getGameLoaderInventory()->setIsLocked(0);
+ }
+ } else {
+ getGameLoaderInventory()->slideOut();
+ getGameLoaderInventory()->setIsLocked(1);
+ }
+ break;
+ case '\t':
+ if (g_fullpipe->_flgCanOpenMap)
+ g_fullpipe->openMap();
+ cmd->_messageKind = 0;
+ break;
+ case 'p':
+ if (g_fullpipe->_flgCanOpenMap)
+ g_fullpipe->openHelp();
+ cmd->_messageKind = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 33:
+ if (!g_fullpipe->_inventoryScene)
+ break;
+
+ int invItem;
+
+ if (g_fullpipe->_updateFlag && (invItem = g_fullpipe->_inventory->getHoveredItem(&g_fullpipe->_mouseScreenPos))) {
+ g_fullpipe->_cursorId = PIC_CSR_ITN;
+ if (!g_fullpipe->_currSelectedInventoryItemId && !g_fullpipe->_aniMan->_movement &&
+ !(g_fullpipe->_aniMan->_flags & 0x100) && g_fullpipe->_aniMan->isIdle()) {
+ int st = g_fullpipe->_aniMan->_statics->_staticsId;
+ ExCommand *newex = 0;
+
+ if (st == ST_MAN_RIGHT) {
+ newex = new ExCommand(g_fullpipe->_aniMan->_id, 1, rMV_MAN_LOOKUP, 0, 0, 0, 1, 0, 0, 0);
+ } else if (st == (0x4000 | ST_MAN_RIGHT)) {
+ newex = new ExCommand(g_fullpipe->_aniMan->_id, 1, MV_MAN_LOOKUP, 0, 0, 0, 1, 0, 0, 0);
+ }
+
+ if (newex) {
+ newex->_keyCode = g_fullpipe->_aniMan->_okeyCode;
+ newex->_excFlags |= 3;
+ newex->postMessage();
+ }
+ }
+
+ if (g_fullpipe->_currSelectedInventoryItemId != invItem)
+ g_fullpipe->playSound(SND_CMN_070, 0);
+
+ g_fullpipe->_currSelectedInventoryItemId = invItem;
+ g_fullpipe->setCursor(g_fullpipe->_cursorId);
+ break;
+ }
+ if (g_fullpipe->_updateCursorCallback)
+ g_fullpipe->_updateCursorCallback();
+
+ g_fullpipe->_currSelectedInventoryItemId = 0;
+ g_fullpipe->setCursor(g_fullpipe->_cursorId);
+ break;
+ case 65: // open map
+ if (cmd->_field_2C == 11 && cmd->_field_14 == ANI_INV_MAP && g_fullpipe->_flgCanOpenMap)
+ g_fullpipe->openMap();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (cmd->_messageKind == 56) {
+ getGameLoaderInventory()->rebuildItemRects();
+
+ ExCommand *newex = new ExCommand(0, 35, SND_CMN_031, 0, 0, 0, 1, 0, 0, 0);
+
+ newex->_field_14 = 1;
+ newex->_excFlags |= 3;
+ newex->postMessage();
+
+ return 1;
+ } else if (cmd->_messageKind == 57) {
+ getGameLoaderInventory()->rebuildItemRects();
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void staticANIObjectCallback(int *arg) {
+ (*arg)--;
+}
+
+int global_messageHandler2(ExCommand *cmd) {
+ if (cmd->_messageKind != 17)
+ return 0;
+
+ int res = 0;
+ StaticANIObject *ani;
+
+ switch (cmd->_messageNum) {
+ case 0x44c8:
+ error("0x44c8");
+ // Unk3_sub_4477A0(&unk3, _parentId, _field_14 != 0);
+ break;
+
+ case 28:
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (ani)
+ ani->_priority = cmd->_field_14;
+ break;
+
+ case 25:
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (ani) {
+ if (cmd->_field_14) {
+ ani->setFlags40(true);
+ ani->_callback2 = staticANIObjectCallback;
+ } else {
+ ani->setFlags40(false);
+ ani->_callback2 = 0;
+ }
+ }
+ break;
+
+ case 26:
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (ani) {
+ Movement *mov = ani->_movement;
+ if (mov)
+ mov->_currDynamicPhase->_field_68 = 0;
+ }
+ break;
+
+ default:
+#if 0
+ // We never put anything into _defMsgArray
+ while (::iterator it = g_fullpipe->_defMsgArray.begin(); it != g_fullpipe->_defMsgArray.end(); ++it)
+ if (((ExCommand *)*it)->_field_24 == _messageNum) {
+ ((ExCommand *)*it)->firef34(v13);
+ res = 1;
+ }
+#endif
+
+ //debug_msg(_messageNum);
+
+ if (!g_fullpipe->_soundEnabled || cmd->_messageNum != 33 || g_fullpipe->_currSoundListCount <= 0)
+ return res;
+
+ for (int snd = 0; snd < g_fullpipe->_currSoundListCount; snd++) {
+ SoundList *s = g_fullpipe->_currSoundList1[snd];
+ int ms = s->getCount();
+ for (int i = 0; i < ms; i++) {
+ s->getSoundByIndex(i)->setPanAndVolumeByStaticAni();
+ }
+ }
+ }
+
+ return res;
+}
+
+int global_messageHandler3(ExCommand *cmd) {
+ int result = 0;
+
+ if (cmd->_messageKind == 17) {
+ switch (cmd->_messageNum) {
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 36:
+ if (g_fullpipe->_inputDisabled)
+ cmd->_messageKind = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ StaticANIObject *ani, *ani2;
+
+ switch (cmd->_messageKind) {
+ case 17:
+ switch (cmd->_messageNum) {
+ case 61:
+ return g_fullpipe->_gameLoader->preloadScene(cmd->_parentId, cmd->_keyCode);
+ case 62:
+ return g_fullpipe->_gameLoader->gotoScene(cmd->_parentId, cmd->_keyCode);
+ case 64:
+ if (g_fullpipe->_currentScene && g_fullpipe->_msgObjectId2
+ && (!(cmd->_keyCode & 4) || g_fullpipe->_msgObjectId2 != cmd->_field_14 || g_fullpipe->_msgId != cmd->_field_20)) {
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_msgObjectId2, g_fullpipe->_msgId);
+ if (ani) {
+ ani->_flags &= 0xFF7F;
+ ani->_flags &= 0xFEFF;
+ ani->deleteFromGlobalMessageQueue();
+ }
+ }
+ g_fullpipe->_msgX = 0;
+ g_fullpipe->_msgY = 0;
+ g_fullpipe->_msgObjectId2 = 0;
+ g_fullpipe->_msgId = 0;
+ if ((cmd->_keyCode & 1) || (cmd->_keyCode & 2)) {
+ g_fullpipe->_msgX = cmd->_x;
+ g_fullpipe->_msgY = cmd->_y;
+ }
+ if (cmd->_keyCode & 4) {
+ g_fullpipe->_msgObjectId2 = cmd->_field_14;
+ g_fullpipe->_msgId = cmd->_field_20;
+ }
+ return result;
+ case 29:
+ if (!g_fullpipe->_currentScene)
+ return result;
+
+ if (g_fullpipe->_gameLoader->_interactionController->_flag24) {
+ ani = g_fullpipe->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
+ ani2 = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_gameLoader->_field_FA, -1);
+ if (ani) {
+ if (g_fullpipe->_msgObjectId2 == ani->_id && g_fullpipe->_msgId == ani->_okeyCode) {
+ cmd->_messageKind = 0;
+ return result;
+ }
+ if (canInteractAny(ani2, ani, cmd->_keyCode)) {
+ handleObjectInteraction(ani2, ani, cmd->_keyCode);
+ return 1;
+ }
+ } else {
+ int id = g_fullpipe->_currentScene->getPictureObjectIdAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
+ PictureObject *pic = g_fullpipe->_currentScene->getPictureObjectById(id, 0);
+ if (pic) {
+ if (g_fullpipe->_msgObjectId2 == pic->_id && g_fullpipe->_msgId == pic->_okeyCode) {
+ cmd->_messageKind = 0;
+ return result;
+ }
+ if (!ani2 || canInteractAny(ani2, pic, cmd->_keyCode)) {
+ if (!ani2 || (ani2->isIdle() && !(ani2->_flags & 0x80) && !(ani2->_flags & 0x100)))
+ handleObjectInteraction(ani2, pic, cmd->_keyCode);
+ return 1;
+ }
+ }
+ }
+ }
+ if (getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->_isEnabled && cmd->_keyCode <= 0) {
+ if (g_fullpipe->_msgX != cmd->_sceneClickX || g_fullpipe->_msgY != cmd->_sceneClickY) {
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_gameLoader->_field_FA, -1);
+ if (!ani || (ani->isIdle() && !(ani->_flags & 0x80) && !(ani->_flags & 0x100))) {
+ result = startWalkTo(g_fullpipe->_gameLoader->_field_FA, -1, cmd->_sceneClickX, cmd->_sceneClickY, 0);
+ if (result) {
+ ExCommand *ex = new ExCommand(g_fullpipe->_gameLoader->_field_FA, 17, 64, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_keyCode = 1;
+ ex->_excFlags |= 3;
+ ex->_x = cmd->_sceneClickX;
+ ex->_y = cmd->_sceneClickY;
+ ex->postMessage();
+ }
+ }
+ } else {
+ cmd->_messageKind = 0;
+ }
+ }
+ return result;
+ default:
+ return result;
+ }
+ case 58:
+ g_fullpipe->setCursor(cmd->_keyCode);
+ return result;
+ case 59:
+ setInputDisabled(1);
+ return result;
+ case 60:
+ setInputDisabled(0);
+ return result;
+ case 56:
+ if (cmd->_field_2C) {
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (ani) {
+ getGameLoaderInventory()->addItem2(ani);
+ result = 1;
+ }
+ } else {
+ result = 1;
+ getGameLoaderInventory()->addItem(cmd->_parentId, 1);
+ }
+ getGameLoaderInventory()->rebuildItemRects();
+ return result;
+ case 57:
+ if (cmd->_field_2C) {
+ if (!cmd->_field_20) {
+ getGameLoaderInventory()->removeItem2(g_fullpipe->_currentScene, cmd->_parentId, cmd->_x, cmd->_y, cmd->_field_14);
+ getGameLoaderInventory()->rebuildItemRects();
+ return 1;
+ }
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_gameLoader->_field_FA, -1);
+ if (ani) {
+ getGameLoaderInventory()->removeItem2(g_fullpipe->_currentScene, cmd->_parentId, ani->_ox + cmd->_x, ani->_oy + cmd->_y, ani->_priority + cmd->_field_14);
+ getGameLoaderInventory()->rebuildItemRects();
+ return 1;
+ }
+ } else {
+ getGameLoaderInventory()->removeItem(cmd->_parentId, 1);
+ }
+ getGameLoaderInventory()->rebuildItemRects();
+ return 1;
+ case 55:
+ if (g_fullpipe->_currentScene) {
+ GameObject *obj;
+ if (cmd->_field_14)
+ obj = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_x, cmd->_y);
+ else
+ obj = g_fullpipe->_currentScene->getPictureObjectById(cmd->_x, cmd->_y);
+ handleObjectInteraction(g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode), obj, cmd->_field_20);
+ result = 1;
+ }
+ return result;
+ case 51:
+ return startWalkTo(cmd->_parentId, cmd->_keyCode, cmd->_x, cmd->_y, cmd->_field_20);
+ case 52:
+ return doSomeAnimation(cmd->_parentId, cmd->_keyCode, cmd->_field_20);
+ case 53:
+ return doSomeAnimation2(cmd->_parentId, cmd->_keyCode);
+ case 63:
+ if (cmd->_objtype == kObjTypeObjstateCommand) {
+ ObjstateCommand *c = (ObjstateCommand *)cmd;
+ result = 1;
+ g_fullpipe->setObjectState(c->_objCommandName, c->_value);
+ }
+ return result;
+ default:
+ return result;
+ }
+}
+
+int global_messageHandler4(ExCommand *cmd) {
+ StaticANIObject *ani = 0;
+
+ switch (cmd->_messageKind) {
+ case 18: {
+ MessageQueue *mq = new MessageQueue(g_fullpipe->_currentScene->getMessageQueueById(cmd->_messageNum), cmd->_parId, 0);
+
+ if (cmd->_excFlags & 1)
+ mq->_flag1 = 1;
+ else
+ mq->_flag1 = 0;
+
+ mq->sendNextCommand();
+ break;
+ }
+ case 2:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->trySetMessageQueue(cmd->_messageNum, cmd->_parId);
+ break;
+
+ case 1: {
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ int flags = cmd->_field_14;
+ if (flags <= 0)
+ flags = -1;
+
+ if (cmd->_excFlags & 1)
+ ani->startAnim(cmd->_messageNum, 0, flags);
+ else
+ ani->startAnim(cmd->_messageNum, cmd->_parId, flags);
+
+ break;
+ }
+ case 8:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->startAnimEx(cmd->_messageNum, cmd->_parId, -1, -1);
+ break;
+
+ case 20: {
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ int flags = cmd->_field_14;
+ if (flags <= 0)
+ flags = -1;
+
+ ExCommand2 *cmd2 = (ExCommand2 *)cmd;
+
+ if (cmd->_excFlags & 1) {
+ ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags);
+ } else {
+ ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags);
+ }
+ break;
+ }
+ case 21:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->queueMessageQueue(0);
+ ani->playIdle();
+ break;
+ case 9:
+ // Nop in original
+ break;
+ case 3:
+ g_fullpipe->_currentScene->_y = cmd->_messageNum - cmd->_messageNum % g_fullpipe->_scrollSpeed;
+ break;
+
+ case 4:
+ g_fullpipe->_currentScene->_x = cmd->_messageNum - cmd->_messageNum % g_fullpipe->_scrollSpeed;
+ break;
+
+ case 19: {
+ if (!g_fullpipe->_currentScene)
+ break;
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ MessageQueue *mq = ani->getMessageQueue();
+ MessageQueue *mq2 = ani->changeStatics1(cmd->_messageNum);
+
+ if (!mq2 || !mq2->getExCommandByIndex(0) || !mq)
+ break;
+
+ mq2->_parId = mq->_id;
+ mq2->_flag1 = (cmd->_field_24 == 0);
+ break;
+ }
+ case 22:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->_flags |= 4;
+ ani->changeStatics2(cmd->_messageNum);
+ break;
+
+ case 6:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->hide();
+ break;
+
+ case 27:
+ if (!g_fullpipe->_currentScene || g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode) == 0) {
+ ani = g_fullpipe->accessScene(cmd->_field_20)->getStaticANIObject1ById(cmd->_parentId, -1);
+ if (ani) {
+ ani = new StaticANIObject(ani);
+ g_fullpipe->_currentScene->addStaticANIObject(ani, 1);
+ }
+ }
+
+ // fall through
+ case 5:
+ if (g_fullpipe->_currentScene)
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+
+ if (!ani)
+ break;
+
+ if (cmd->_field_14 >= 0)
+ ani->_priority = cmd->_field_14;
+
+ ani->show1(cmd->_x, cmd->_y, cmd->_messageNum, cmd->_parId);
+ break;
+
+ case 10:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ if (cmd->_field_14 >= 0)
+ ani->_priority = cmd->_field_14;
+
+ ani->show2(cmd->_x, cmd->_y, cmd->_messageNum, cmd->_parId);
+ break;
+
+ case 7: {
+ if (!g_fullpipe->_currentScene->_picObjList.size())
+ break;
+
+ int offX = g_fullpipe->_scrollSpeed * (cmd->_x / g_fullpipe->_scrollSpeed);
+ int offY = g_fullpipe->_scrollSpeed * (cmd->_y / g_fullpipe->_scrollSpeed);
+
+ if (cmd->_messageNum) {
+ g_fullpipe->_currentScene->_x = offX - g_fullpipe->_sceneRect.left;
+ g_fullpipe->_currentScene->_y = offY - g_fullpipe->_sceneRect.top;
+
+ if (cmd->_field_24) {
+ g_fullpipe->_currentScene->_messageQueueId = cmd->_parId;
+ }
+ } else {
+ g_fullpipe->_sceneRect.moveTo(offX, offY);
+
+ g_fullpipe->_currentScene->_x = 0;
+ g_fullpipe->_currentScene->_y = 0;
+
+ g_fullpipe->_currentScene->updateScrolling2();
+ }
+ break;
+ }
+ case 34:
+ if (!g_fullpipe->_currentScene)
+ break;
+
+ ani = g_fullpipe->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_keyCode);
+ if (!ani)
+ break;
+
+ ani->_flags = cmd->_messageNum | (ani->_flags & ~cmd->_field_14);
+
+ break;
+
+ case 35:
+ global_messageHandler_handleSound(cmd);
+ break;
+
+ case 11:
+ case 12:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+int MovGraph_messageHandler(ExCommand *cmd) {
+ if (cmd->_messageKind != 17)
+ return 0;
+
+ if (cmd->_messageNum != 33)
+ return 0;
+
+ StaticANIObject *ani = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_gameLoader->_field_FA, -1);
+
+ if (!getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId))
+ return 0;
+
+ if (getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->_objtype != kObjTypeMovGraph || !ani)
+ return 0;
+
+ MovGraph *gr = (MovGraph *)getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId);
+
+ MovGraphLink *link = 0;
+ double mindistance = 1.0e10;
+ Common::Point point;
+
+ for (ObList::iterator i = gr->_links.begin(); i != gr->_links.end(); ++i) {
+ point.x = ani->_ox;
+ point.y = ani->_oy;
+
+ double dst = gr->calcDistance(&point, (MovGraphLink *)(*i), 0);
+ if (dst >= 0.0 && dst < mindistance) {
+ mindistance = dst;
+ link = (MovGraphLink *)(*i);
+ }
+ }
+
+ int top;
+
+ if (link) {
+ MovGraphNode *node = link->_movGraphNode1;
+
+ double sq = (ani->_oy - node->_y) * (ani->_oy - node->_y) + (ani->_ox - node->_x) * (ani->_ox - node->_x);
+ int off = (node->_field_14 >> 16) & 0xFF;
+ double off2 = ((link->_movGraphNode2->_field_14 >> 8) & 0xff) - off;
+
+ top = off + (int)(sqrt(sq) * off2 / link->_distance);
+ } else {
+ top = (gr->calcOffset(ani->_ox, ani->_oy)->_field_14 >> 8) & 0xff;
+ }
+
+ if (ani->_movement) {
+ ani->_movement->_currDynamicPhase->_rect->top = 255 - top;
+ return 0;
+ }
+
+ if (ani->_statics)
+ ani->_statics->_rect->top = 255 - top;
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp
new file mode 100644
index 0000000000..4abf2ef56f
--- /dev/null
+++ b/engines/fullpipe/messages.cpp
@@ -0,0 +1,791 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/modal.h"
+#include "fullpipe/statics.h"
+
+namespace Fullpipe {
+
+ExCommand::ExCommand() {
+ _field_3C = 1;
+ _messageNum = 0;
+ _excFlags = 0;
+ _parId = 0;
+}
+
+ExCommand::ExCommand(ExCommand *src) : Message(src) {
+ _field_3C = 1;
+ _messageNum = src->_messageNum;
+ _excFlags = src->_excFlags;
+ _parId = src->_parId;
+
+}
+
+ExCommand::ExCommand(int16 parentId, int messageKind, int messageNum, int x, int y, int a7, int a8, int sceneClickX, int sceneClickY, int a11) :
+ Message(parentId, messageKind, x, y, a7, a8, sceneClickX, sceneClickY, a11) {
+ _field_3C = 1;
+ _messageNum = messageNum;
+ _excFlags = 0;
+ _parId = 0;
+}
+
+bool ExCommand::load(MfcArchive &file) {
+ debug(5, "ExCommand::load()");
+
+ _parentId = file.readUint16LE();
+ _messageKind = file.readUint32LE();
+ _x = file.readUint32LE();
+ _y = file.readUint32LE();
+ _field_14 = file.readUint32LE();
+ _sceneClickX = file.readUint32LE();
+ _sceneClickY = file.readUint32LE();
+ _field_20 = file.readUint32LE();
+ _field_24 = file.readUint32LE();
+ _keyCode = file.readUint32LE();
+ _field_2C = file.readUint32LE();
+ _field_30 = file.readUint32LE();
+ _field_34 = file.readUint32LE();
+
+ _messageNum = file.readUint32LE();
+
+ _field_3C = 0;
+
+ if (g_fullpipe->_gameProjectVersion >= 12) {
+ _excFlags = file.readUint32LE();
+ _parId = file.readUint32LE();
+ }
+
+ return true;
+}
+
+bool ExCommand::handleMessage() {
+ int cnt = 0;
+ for (MessageHandler *m = g_fullpipe->_messageHandlers; m; m = m->nextItem)
+ cnt += m->callback(this);
+
+ if (_messageKind == 17 || (_excFlags & 1)) {
+ if (_parId) {
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(_parId);
+ if (mq)
+ mq->update();
+ }
+ }
+
+ if (_excFlags & 2)
+ delete this;
+
+ return (cnt > 0);
+}
+
+void ExCommand::sendMessage() {
+ g_fullpipe->_exCommandList.push_back(this);
+
+ processMessages();
+}
+
+void ExCommand::postMessage() {
+ g_fullpipe->_exCommandList.push_back(this);
+}
+
+void ExCommand::handle() {
+ if (g_fullpipe->_modalObject) {
+ g_fullpipe->_modalObject->handleMessage(this);
+
+ delete this;
+ } else {
+ postMessage();
+ }
+}
+
+Message::Message() {
+ _messageKind = 0;
+ _parentId = 0;
+
+ _x = 0;
+ _y = 0;
+ _field_14 = 0;
+ _sceneClickX = 0;
+ _sceneClickY = 0;
+ _field_20 = 0;
+ _field_24 = 0;
+ _keyCode = 0;
+ _field_2C = 0;
+ _field_30 = 0;
+ _field_34 = 0;
+}
+
+Message::Message(Message *src) {
+ _parentId = src->_parentId;
+ _messageKind = src->_messageKind;
+ _x = src->_x;
+ _y = src->_y;
+ _field_14 = src->_field_14;
+ _sceneClickX = src->_sceneClickX;
+ _sceneClickY = src->_sceneClickY;
+ _field_20 = src->_field_20;
+ _field_24 = src->_field_24;
+ _keyCode = src->_keyCode;
+ _field_2C = src->_field_2C;
+ _field_30 = src->_field_30;
+ _field_34 = src->_field_34;
+}
+
+Message::Message(int16 parentId, int messageKind, int x, int y, int a6, int a7, int sceneClickX, int sceneClickY, int a10) {
+ _messageKind = messageKind;
+ _parentId = parentId;
+ _x = x;
+ _y = y;
+ _field_14 = a6;
+ _sceneClickX = sceneClickX;
+ _sceneClickY = sceneClickY;
+ _field_24 = a7;
+ _field_20 = a10;
+ _keyCode = 0;
+ _field_2C = 0;
+ _field_30 = 0;
+ _field_34 = 0;
+}
+
+ObjstateCommand::ObjstateCommand() {
+ _value = 0;
+ _objCommandName = 0;
+}
+
+bool ObjstateCommand::load(MfcArchive &file) {
+ debug(5, "ObjStateCommand::load()");
+
+ _objtype = kObjTypeObjstateCommand;
+
+ _cmd.load(file);
+
+ _value = file.readUint32LE();
+
+ _objCommandName = file.readPascalString();
+
+ return true;
+}
+
+MessageQueue::MessageQueue() {
+ _field_14 = 0;
+ _parId = 0;
+ _dataId = 0;
+ _id = 0;
+ _isFinished = 0;
+ _flags = 0;
+ _queueName = 0;
+ _counter = 0;
+ _field_38 = 0;
+ _flag1 = 0;
+}
+
+MessageQueue::MessageQueue(int dataId) {
+ _field_14 = 0;
+ _parId = 0;
+ _dataId = dataId;
+ _id = g_fullpipe->_globalMessageQueueList->compact();
+ _isFinished = 0;
+ _flags = 0;
+ _queueName = 0;
+ _counter = 0;
+ _field_38 = 0;
+ _flag1 = 0;
+}
+
+MessageQueue::MessageQueue(MessageQueue *src, int parId, int field_38) {
+ _counter = 0;
+ _field_38 = (field_38 == 0);
+
+ for (Common::List<ExCommand *>::iterator it = src->_exCommands.begin(); it != src->_exCommands.end(); ++it) {
+ ExCommand *ex = new ExCommand(*it);
+ ex->_excFlags |= 2;
+
+ _exCommands.push_back(ex);
+ }
+ _field_14 = src->_field_14;
+
+ if (parId)
+ _parId = parId;
+ else
+ _parId = src->_parId;
+
+ _id = g_fullpipe->_globalMessageQueueList->compact();
+ _dataId = src->_dataId;
+ _flags = src->_flags;
+
+ g_fullpipe->_globalMessageQueueList->addMessageQueue(this);
+
+ _isFinished = 0;
+ _flag1 = 0;
+}
+
+MessageQueue::~MessageQueue() {
+ for (Common::List<ExCommand *>::iterator it = _exCommands.begin(); it != _exCommands.end(); ++it) {
+ ExCommand *ex = (ExCommand *)*it;
+
+ if (ex && ex->_excFlags & 2)
+ delete ex;
+ }
+
+ _exCommands.clear();
+
+ if (_field_14)
+ delete _field_14;
+
+ if (_flags & 2) {
+ g_fullpipe->_globalMessageQueueList->removeQueueById(_id);
+ }
+
+ finish();
+
+ free(_queueName);
+}
+
+bool MessageQueue::load(MfcArchive &file) {
+ debug(5, "MessageQueue::load()");
+
+ _dataId = file.readUint16LE();
+
+ int count = file.readUint16LE();
+
+ assert(g_fullpipe->_gameProjectVersion >= 12);
+
+ _queueName = file.readPascalString();
+
+ for (int i = 0; i < count; i++) {
+ ExCommand *tmp = (ExCommand *)file.readClass();
+
+ _exCommands.push_back(tmp);
+ }
+
+ _id = -1;
+ _field_14 = 0;
+ _parId = 0;
+ _isFinished = 0;
+
+ return true;
+}
+
+bool MessageQueue::chain(StaticANIObject *ani) {
+ if (checkGlobalExCommandList1() && checkGlobalExCommandList2()) {
+ if (!(getFlags() & 2)) {
+ g_fullpipe->_globalMessageQueueList->addMessageQueue(this);
+ _flags |= 2;
+ }
+ if (ani) {
+ ani->queueMessageQueue(this);
+ return true;
+ } else {
+ sendNextCommand();
+ return true;
+ }
+ }
+ return false;
+}
+
+void MessageQueue::update() {
+ if (_counter > 0)
+ _counter--;
+
+ if (_exCommands.size()) {
+ sendNextCommand();
+ } else if (_counter == 0) {
+ _isFinished = 1;
+ finish();
+ }
+}
+
+void MessageQueue::messageQueueCallback1(int par) {
+ // Autosave
+ debug(3, "STUB: MessageQueue::messageQueueCallback1()");
+}
+
+void MessageQueue::addExCommand(ExCommand *ex) {
+ _exCommands.push_front(ex);
+}
+
+ExCommand *MessageQueue::getExCommandByIndex(uint idx) {
+ if (idx > _exCommands.size())
+ return 0;
+
+ Common::List<ExCommand *>::iterator it = _exCommands.begin();
+
+ while (idx) {
+ ++it;
+ idx--;
+ }
+
+ return *it;
+}
+
+void MessageQueue::deleteExCommandByIndex(uint idx, bool doFree) {
+ if (idx > _exCommands.size())
+ return;
+
+ Common::List<ExCommand *>::iterator it = _exCommands.begin();
+
+ while (idx) {
+ ++it;
+ idx--;
+ }
+
+ _exCommands.erase(it);
+
+ if (doFree)
+ delete *it;
+}
+
+void MessageQueue::transferExCommands(MessageQueue *mq) {
+ while (mq->_exCommands.size()) {
+ _exCommands.push_back(mq->_exCommands.front());
+ mq->_exCommands.pop_front();
+ }
+}
+
+void MessageQueue::sendNextCommand() {
+ if (_exCommands.size()) {
+ if (!(_flags & 4) && (_flags & 1)) {
+ messageQueueCallback1(16);
+ }
+ ExCommand *ex = _exCommands.front();
+
+ _exCommands.pop_front();
+
+ _counter++;
+ ex->_parId = _id;
+ ex->_excFlags |= (ex->_field_24 == 0 ? 1 : 0) | (ex->_field_3C != 0 ? 2 : 0);
+
+ _flags |= 4;
+ ex->sendMessage();
+ } else if (_counter <= 0) {
+ _isFinished = 1;
+ finish();
+ }
+}
+
+bool MessageQueue::checkGlobalExCommandList1() {
+ ExCommand *ex, *ex1;
+
+ for (uint i = 0; i < getCount(); i++) {
+ ex = getExCommandByIndex(i);
+
+ if (ex->_messageKind != 1 && ex->_messageKind != 20 && ex->_messageKind != 5 && ex->_messageKind != 27)
+ continue;
+
+ for (Common::List<ExCommand *>::iterator it = g_fullpipe->_exCommandList.begin(); it != g_fullpipe->_exCommandList.end(); it++) {
+ ex1 = *it;
+
+ if (ex1->_messageKind != 1 && ex1->_messageKind != 20 && ex1->_messageKind != 5 && ex1->_messageKind != 27)
+ continue;
+
+ if (ex1->_keyCode != ex->_keyCode && ex1->_keyCode != -1 && ex->_keyCode != -1)
+ continue;
+
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(ex1->_parId);
+
+ if (mq) {
+ if (mq->getFlags() & 1)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool MessageQueue::checkGlobalExCommandList2() {
+ ExCommand *ex, *ex1;
+
+ for (uint i = 0; i < getCount(); i++) {
+ ex = getExCommandByIndex(i);
+
+ if (ex->_messageKind != 1 && ex->_messageKind != 20 && ex->_messageKind != 5 && ex->_messageKind != 27)
+ continue;
+
+ for (Common::List<ExCommand *>::iterator it = g_fullpipe->_exCommandList.begin(); it != g_fullpipe->_exCommandList.end();) {
+ ex1 = *it;
+
+ if (ex1->_messageKind != 1 && ex1->_messageKind != 20 && ex1->_messageKind != 5 && ex1->_messageKind != 27) {
+ it++;
+ continue;
+ }
+
+ if (ex1->_keyCode != ex->_keyCode && ex1->_keyCode != -1 && ex->_keyCode != -1) {
+ it++;
+ continue;
+ }
+
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(ex1->_parId);
+
+ if (mq) {
+ if (mq->getFlags() & 1)
+ return false;
+
+ delete mq;
+ }
+
+ it = g_fullpipe->_exCommandList.erase(it);
+
+ if (ex1->_excFlags & 2) {
+ delete ex1;
+ }
+ }
+ }
+ return true;
+}
+
+void MessageQueue::finish() {
+ if (!_parId)
+ return;
+
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(_parId);
+
+ _parId = 0;
+
+ if (!mq)
+ return;
+
+ if (!_flag1) {
+ mq->update();
+ return;
+ }
+
+ mq->_counter--;
+
+ if (!mq->_counter && !mq->_exCommands.size())
+ mq->update();
+}
+
+void MessageQueue::replaceKeyCode(int key1, int key2) {
+ for (uint i = 0; i < getCount(); i++) {
+ ExCommand *ex = getExCommandByIndex(i);
+ int k = ex->_messageKind;
+ if ((k == 1 || k == 20 || k == 5 || k == 6 || k == 2 || k == 18 || k == 19 || k == 22 || k == 55)
+ && ex->_keyCode == key1)
+ ex->_keyCode = key2;
+ }
+}
+
+int MessageQueue::calcDuration(StaticANIObject *obj) {
+ int res = 0;
+ ExCommand *ex;
+ Movement *mov;
+
+ for (uint i = 0; (ex = getExCommandByIndex(i)); i++)
+ if (ex->_parentId == obj->_id) {
+ if (ex->_messageKind == 1 || ex->_messageKind == 20) {
+ if ((mov = obj->getMovementById(ex->_messageNum)) != 0) {
+ if (ex->_field_14 >= 1)
+ res += ex->_field_14;
+ else
+ res += mov->calcDuration();
+ }
+ }
+ }
+
+ return res;
+}
+
+void MessageQueue::changeParam28ForObjectId(int objId, int oldParam28, int newParam28) {
+ for (uint i = 0; i < _exCommands.size(); i++) {
+ ExCommand *ex = getExCommandByIndex(i);
+ int k = ex->_messageKind;
+
+ if ((k == 1 || k == 20 || k == 5 || k == 6 || k == 2 || k == 18 || k == 19 || k == 22 || k == 55)
+ && ex->_keyCode == oldParam28
+ && ex->_parentId == objId)
+ ex->_keyCode = newParam28;
+ }
+}
+
+MessageQueue *GlobalMessageQueueList::getMessageQueueById(int id) {
+ for (Common::Array<MessageQueue *>::iterator s = begin(); s != end(); ++s) {
+ if ((*s)->_id == id)
+ return *s;
+ }
+
+ return 0;
+}
+
+void GlobalMessageQueueList::deleteQueueById(int id) {
+ for (uint i = 0; i < size(); i++)
+ if (_storage[i]->_id == id) {
+ remove_at(i);
+
+ disableQueueById(id);
+ return;
+ }
+}
+
+void GlobalMessageQueueList::removeQueueById(int id) {
+ for (uint i = 0; i < size(); i++)
+ if (_storage[i]->_id == id) {
+ _storage[i]->_flags &= 0xFD; // It is quite pointless
+ remove_at(i);
+
+ disableQueueById(id);
+ return;
+ }
+}
+
+void GlobalMessageQueueList::disableQueueById(int id) {
+ for (Common::Array<MessageQueue *>::iterator s = begin(); s != end(); ++s) {
+ if ((*s)->_parId == id)
+ (*s)->_parId = 0;
+ }
+}
+
+int GlobalMessageQueueList::compact() {
+ for (uint i = 0; i < size();) {
+ if (((MessageQueue *)_storage[i])->_isFinished) {
+ disableQueueById(_storage[i]->_id);
+ remove_at(i);
+ } else {
+ i++;
+ }
+ }
+
+ return size() + 1;
+}
+
+void GlobalMessageQueueList::addMessageQueue(MessageQueue *msg) {
+ msg->setFlags(msg->getFlags() | 2);
+
+ push_back(msg);
+}
+
+void clearGlobalMessageQueueList1() {
+ warning("STUB: clearGlobalMessageQueueList1()");
+}
+
+bool removeMessageHandler(int16 id, int pos) {
+ if (g_fullpipe->_messageHandlers) {
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+ MessageHandler *prevItem = 0;
+ int curPos = 0;
+
+ while (id != curItem->id) {
+ prevItem = curItem;
+ curItem = curItem->nextItem;
+ curPos++;
+
+ if (!curItem)
+ return false;
+ }
+
+ if (pos == -1 || curPos == pos) {
+ prevItem->nextItem = curItem->nextItem;
+ delete curItem;
+ updateMessageHandlerIndex(prevItem->nextItem, -1);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void updateMessageHandlerIndex(MessageHandler *msg, int offset) {
+ for (; msg; msg = msg->nextItem)
+ msg->index += offset;
+}
+
+void addMessageHandler(int (*callback)(ExCommand *), int16 id) {
+ if (getMessageHandlerById(id))
+ return;
+
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+
+ if (!curItem)
+ return;
+
+ int index = 0;
+ for (MessageHandler *i = g_fullpipe->_messageHandlers->nextItem; i; i = i->nextItem) {
+ curItem = i;
+ index++;
+ }
+
+ allocMessageHandler(curItem, id, callback, index);
+
+ if (curItem)
+ updateMessageHandlerIndex(curItem->nextItem->nextItem, 1);
+}
+
+MessageHandler *getMessageHandlerById(int16 id) {
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+
+ if (!curItem)
+ return 0;
+
+ while (id != curItem->id) {
+ curItem = curItem->nextItem;
+
+ if (!curItem)
+ return 0;
+ }
+
+ return curItem;
+}
+
+bool allocMessageHandler(MessageHandler *where, int16 id, int (*callback)(ExCommand *), int index) {
+ MessageHandler *msg = new MessageHandler;
+
+ if (where) {
+ msg->nextItem = where->nextItem;
+ where->nextItem = msg;
+ msg->id = id;
+ msg->callback = callback;
+ msg->index = index;
+ } else {
+ msg->nextItem = 0;
+ msg->id = id;
+ msg->callback = callback;
+ msg->index = 0;
+
+ g_fullpipe->_messageHandlers = msg;
+ }
+
+ return true;
+}
+
+int getMessageHandlersCount() {
+ int result;
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+
+ for (result = 0; curItem; result++)
+ curItem = curItem->nextItem;
+
+ return result;
+}
+
+bool addMessageHandlerByIndex(int (*callback)(ExCommand *), int index, int16 id) {
+ if (getMessageHandlerById(id))
+ return false;
+
+ if (index) {
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+
+ for (int i = index - 1; i > 0; i--)
+ if (curItem)
+ curItem = curItem->nextItem;
+
+ if (!curItem)
+ return false;
+
+ bool res = allocMessageHandler(curItem, id, callback, index);
+
+ if (res)
+ updateMessageHandlerIndex(curItem->nextItem->nextItem, 1);
+
+ return res;
+ } else {
+ MessageHandler *newItem = new MessageHandler;
+
+ newItem->nextItem = g_fullpipe->_messageHandlers;
+ newItem->id = id;
+ newItem->callback = callback;
+ newItem->index = 0;
+
+ updateMessageHandlerIndex(g_fullpipe->_messageHandlers, 1);
+ g_fullpipe->_messageHandlers = newItem;
+
+ return true;
+ }
+}
+
+bool insertMessageHandler(int (*callback)(ExCommand *), int index, int16 id) {
+ if (getMessageHandlerById(id))
+ return false;
+
+ MessageHandler *curItem = g_fullpipe->_messageHandlers;
+
+ for (int i = index; i > 0; i--)
+ if (curItem)
+ curItem = curItem->nextItem;
+
+ bool res = allocMessageHandler(curItem, id, callback, index + 1);
+ if (curItem)
+ updateMessageHandlerIndex(curItem->nextItem->nextItem, 1);
+
+ return res;
+}
+
+void clearMessageHandlers() {
+ MessageHandler *curItem;
+ MessageHandler *nextItem;
+
+ curItem = g_fullpipe->_messageHandlers;
+ if (curItem) {
+ do {
+ nextItem = curItem->nextItem;
+
+ delete curItem;
+
+ curItem = nextItem;
+ } while (nextItem);
+
+ g_fullpipe->_messageHandlers = 0;
+ }
+}
+
+void processMessages() {
+ if (!g_fullpipe->_isProcessingMessages) {
+ g_fullpipe->_isProcessingMessages = true;
+
+ while (g_fullpipe->_exCommandList.size()) {
+ ExCommand *ex = g_fullpipe->_exCommandList.front();
+ g_fullpipe->_exCommandList.pop_front();
+ ex->handleMessage();
+ }
+ g_fullpipe->_isProcessingMessages = false;
+ }
+}
+
+void updateGlobalMessageQueue(int id, int objid) {
+ MessageQueue *m = g_fullpipe->_globalMessageQueueList->getMessageQueueById(id);
+ if (m) {
+ m->update();
+ }
+}
+
+bool chainQueue(int queueId, int flags) {
+ MessageQueue *mq = g_fullpipe->_currentScene->getMessageQueueById(queueId);
+
+ if (!mq)
+ return false;
+
+ MessageQueue *nmq = new MessageQueue(mq, 0, 0);
+
+ nmq->_flags |= flags;
+
+ if (!mq->chain(0)) {
+ delete mq;
+
+ return false;
+ }
+
+ return true;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h
new file mode 100644
index 0000000000..326f05cef3
--- /dev/null
+++ b/engines/fullpipe/messages.h
@@ -0,0 +1,181 @@
+/* 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 FULLPIPE_MESSAGEQUEUE_H
+#define FULLPIPE_MESSAGEQUEUE_H
+
+#include "fullpipe/utils.h"
+#include "fullpipe/inventory.h"
+#include "fullpipe/gfx.h"
+#include "fullpipe/sound.h"
+#include "fullpipe/scene.h"
+
+namespace Fullpipe {
+
+class Message : public CObject {
+ public:
+ int _messageKind;
+ int16 _parentId;
+ int _x;
+ int _y;
+ int _field_14;
+ int _sceneClickX;
+ int _sceneClickY;
+ int _field_20;
+ int _field_24;
+ int _keyCode;
+ int _field_2C;
+ int _field_30;
+ int _field_34;
+
+ public:
+ Message();
+ Message(Message *src);
+ virtual ~Message() {}
+
+ Message(int16 parentId, int messageKind, int x, int y, int a6, int a7, int sceneClickX, int sceneClickY, int a10);
+};
+
+class ExCommand : public Message {
+ public:
+
+ int _messageNum;
+ int _field_3C;
+ int _excFlags;
+ int _parId;
+
+ ExCommand();
+ ExCommand(ExCommand *src);
+ ExCommand(int16 parentId, int messageKind, int messageNum, int x, int y, int a7, int a8, int sceneClickX, int sceneClickY, int a11);
+ virtual ~ExCommand() {}
+
+ virtual bool load(MfcArchive &file);
+
+ bool handleMessage();
+ void sendMessage();
+ void postMessage();
+ void handle();
+};
+
+class ExCommand2 : public ExCommand {
+ public:
+ Common::Point **_points;
+ int _pointsSize;
+};
+
+class ObjstateCommand : public CObject {
+ public:
+ ExCommand _cmd;
+ char *_objCommandName;
+ int _value;
+
+ public:
+ ObjstateCommand();
+ virtual bool load(MfcArchive &file);
+};
+
+class MessageQueue : public CObject {
+ public:
+ int _id;
+ int _flags;
+ char *_queueName;
+ int16 _dataId;
+ CObject *_field_14;
+ Common::List<ExCommand *> _exCommands;
+ int _counter;
+ int _field_38;
+ int _isFinished;
+ int _parId;
+ int _flag1;
+
+ public:
+ MessageQueue();
+ MessageQueue(int dataId);
+ MessageQueue(MessageQueue *src, int parId, int field_38);
+ virtual ~MessageQueue();
+
+ virtual bool load(MfcArchive &file);
+
+ int getFlags() { return _flags; }
+ void setFlags(int flags) { _flags = flags; }
+
+ uint getCount() { return _exCommands.size(); }
+
+ void addExCommand(ExCommand *ex);
+ ExCommand *getExCommandByIndex(uint idx);
+ void deleteExCommandByIndex(uint idx, bool doFree);
+
+ void transferExCommands(MessageQueue *mq);
+
+ void replaceKeyCode(int key1, int key2);
+
+ bool chain(StaticANIObject *ani);
+ void update();
+ void sendNextCommand();
+ void finish();
+
+ void messageQueueCallback1(int par);
+
+ bool checkGlobalExCommandList1();
+ bool checkGlobalExCommandList2();
+
+ int calcDuration(StaticANIObject *obj);
+ void changeParam28ForObjectId(int objId, int oldParam28, int newParam28);
+};
+
+class GlobalMessageQueueList : public Common::Array<MessageQueue *> {
+ public:
+ MessageQueue *getMessageQueueById(int id);
+ void deleteQueueById(int id);
+ void removeQueueById(int id);
+ void disableQueueById(int id);
+ void addMessageQueue(MessageQueue *msg);
+
+ int compact();
+};
+
+struct MessageHandler {
+ int (*callback)(ExCommand *cmd);
+ int16 id;
+ int16 field_6;
+ int index;
+ MessageHandler *nextItem;
+};
+
+bool removeMessageHandler(int16 id, int pos);
+void updateMessageHandlerIndex(MessageHandler *msg, int offset);
+void addMessageHandler(int (*callback)(ExCommand *), int16 id);
+MessageHandler *getMessageHandlerById(int16 id);
+bool allocMessageHandler(MessageHandler *where, int16 id, int (*callback)(ExCommand *), int index);
+int getMessageHandlersCount();
+bool addMessageHandlerByIndex(int (*callback)(ExCommand *), int index, int16 id);
+bool insertMessageHandler(int (*callback)(ExCommand *), int index, int16 id);
+void clearMessageHandlers();
+void processMessages();
+void updateGlobalMessageQueue(int id, int objid);
+void clearGlobalMessageQueueList1();
+
+bool chainQueue(int queueId, int flags);
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_MESSAGEQUEUE_H */
diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp
new file mode 100644
index 0000000000..f766be3eac
--- /dev/null
+++ b/engines/fullpipe/modal.cpp
@@ -0,0 +1,242 @@
+/* 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 "fullpipe/fullpipe.h"
+#include "fullpipe/modal.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/constants.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/gameloader.h"
+
+namespace Fullpipe {
+
+ModalIntro::ModalIntro() {
+ _field_8 = 0;
+ _countDown = 0;
+ _stillRunning = 0;
+
+ if (g_vars->sceneIntro_skipIntro) {
+ _introFlags = 4;
+ } else {
+ _introFlags = 33;
+ _countDown = 150;
+
+ PictureObject *pict = g_fullpipe->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0);
+ pict->setFlags(pict->_flags & 0xFFFB);
+ }
+
+ g_vars->sceneIntro_skipIntro = false;
+ _sfxVolume = g_fullpipe->_sfxVolume;
+}
+
+ModalIntro::~ModalIntro() {
+ g_fullpipe->stopAllSounds();
+ g_fullpipe->_sfxVolume = _sfxVolume;
+}
+
+bool ModalIntro::handleMessage(ExCommand *message) {
+ if (message->_messageKind != 17)
+ return false;
+
+ if (message->_messageNum != 36)
+ return false;
+
+ if (message->_keyCode != 13 && message->_keyCode != 27 && message->_keyCode != 32)
+ return false;
+
+ if (_stillRunning) {
+ if (!(_introFlags & 0x10)) {
+ _countDown = 0;
+ g_vars->sceneIntro_needBlackout = true;
+ return true;
+ }
+ g_vars->sceneIntro_playing = false;
+ g_vars->sceneIntro_needBlackout = true;
+ }
+
+ return true;
+}
+
+bool ModalIntro::init(int counterdiff) {
+ if (!g_vars->sceneIntro_playing) {
+ if (!_stillRunning) {
+ finish();
+ return false;
+ }
+
+ if (_introFlags & 0x10)
+ g_fullpipe->_gameLoader->updateSystems(42);
+
+ _introFlags |= 2;
+
+ return true;
+ }
+
+ if (_introFlags & 4) {
+ ModalVideoPlayer *player = new ModalVideoPlayer();
+
+ g_fullpipe->_modalObject = player;
+ player->_parentObj = this;
+ player->play("intro.avi");
+
+ _countDown--;
+
+ if (_countDown > 0 )
+ return true;
+
+ if (_stillRunning <= 0) {
+ _countDown = 0;
+ _stillRunning = 0;
+ _introFlags = (_introFlags & 0xfb) | 0x40;
+
+ return true;
+ }
+
+ _introFlags |= 2;
+ return true;
+ }
+
+ if (_introFlags & 0x40) {
+ ModalVideoPlayer *player = new ModalVideoPlayer();
+
+ g_fullpipe->_modalObject = player;
+ player->_parentObj = this;
+ player->play("intro2.avi");
+
+ _countDown--;
+ if (_countDown > 0)
+ return true;
+
+ if (_stillRunning <= 0) {
+ _countDown = 50;
+ _stillRunning = 0;
+ _introFlags = (_introFlags & 0xbf) | 9;
+
+ return true;
+ }
+
+ _introFlags |= 2;
+ return true;
+ }
+
+ if (_introFlags & 8) {
+ _countDown--;
+
+ if (_countDown > 0 )
+ return true;
+
+ if (_stillRunning > 0) {
+ _introFlags |= 2;
+ return true;
+ }
+
+ _countDown = 150;
+ _introFlags = (_introFlags & 0xf7) | 0x21;
+ g_fullpipe->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0)->_flags &= 0xfffb;
+ }
+
+ if (!(_introFlags & 0x20)) {
+ if (_introFlags & 0x10) {
+ if (!_stillRunning) {
+ _introFlags |= 1;
+
+ g_fullpipe->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0)->_flags &= 0xfffb;
+ g_fullpipe->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_GAMETITLE, 0)->_flags &= 0xfffb;
+
+ chainQueue(QU_INTR_STARTINTRO, 1);
+ }
+ g_fullpipe->_gameLoader->updateSystems(42);
+ }
+ return true;
+ }
+
+ _countDown--;
+
+ if (_countDown <= 0) {
+ if (_stillRunning > 0) {
+ _introFlags |= 2;
+
+ return true;
+ }
+
+ _introFlags = (_introFlags & 0xdf) | 0x10;
+
+ g_fullpipe->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_GAMETITLE, 0)->_flags &= 0xfffb;
+
+ _stillRunning = 0;
+ }
+
+ return true;
+}
+
+void ModalIntro::update() {
+ if (g_fullpipe->_currentScene) {
+ if (_introFlags & 1) {
+ //sceneFade(virt, g_currentScene, 1);
+ _stillRunning = 255;
+ _introFlags &= 0xfe;
+
+ if (_introFlags & 0x20)
+ g_fullpipe->playSound(SND_INTR_019, 0);
+ } else if (_introFlags & 2) {
+ if (g_vars->sceneIntro_needBlackout) {
+ //vrtRectangle(*(_DWORD *)virt, 0, 0, 0, 800, 600);
+ g_vars->sceneIntro_needBlackout = 0;
+ _stillRunning = 0;
+ _introFlags &= 0xfd;
+ } else {
+ //sceneFade(virt, g_currentScene, 0);
+ _stillRunning = 0;
+ _introFlags &= 0xfd;
+ }
+ } else if (_stillRunning) {
+ g_fullpipe->_currentScene->draw();
+ }
+ }
+}
+
+void ModalIntro::finish() {
+ g_fullpipe->_gameLoader->unloadScene(SC_INTRO2);
+ g_fullpipe->_currentScene = g_fullpipe->accessScene(SC_INTRO1);
+ g_fullpipe->_gameLoader->preloadScene(SC_INTRO1, TrubaDown);
+
+ if (g_fullpipe->_currentScene)
+ g_fullpipe->_gameLoader->updateSystems(42);
+}
+
+void ModalVideoPlayer::play(const char *fname) {
+ warning("STUB: ModalVideoPlayer::play(%s)", fname);
+}
+
+void FullpipeEngine::openMap() {
+ warning("STUB: FullpipeEngine::openMap()");
+}
+
+void FullpipeEngine::openHelp() {
+ warning("STUB: FullpipeEngine::openHelp()");
+}
+
+void FullpipeEngine::openMainMenu() {
+ warning("STUB: FullpipeEngine::openMainMenu()");
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h
new file mode 100644
index 0000000000..b57d1fbd06
--- /dev/null
+++ b/engines/fullpipe/modal.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_MODAL_H
+#define FULLPIPE_MODAL_H
+
+namespace Fullpipe {
+
+class BaseModalObject {
+ public:
+
+ BaseModalObject *_parentObj;
+
+ public:
+ BaseModalObject() : _parentObj(0) {}
+ virtual ~BaseModalObject() {}
+
+
+ virtual bool pollEvent() = 0;
+ virtual bool handleMessage(ExCommand *message) = 0;
+ virtual bool init(int counterdiff) = 0;
+ virtual void update() = 0;
+
+ virtual void saveload() = 0;
+};
+
+class ModalIntro : public BaseModalObject {
+ int _field_8;
+ int _introFlags;
+ int _countDown;
+ int _stillRunning;
+ int _sfxVolume;
+
+ public:
+ ModalIntro();
+ virtual ~ModalIntro();
+
+ virtual bool pollEvent() { return true; }
+ virtual bool handleMessage(ExCommand *message);
+ virtual bool init(int counterdiff);
+ virtual void update();
+ virtual void saveload() {}
+
+ void finish();
+};
+
+class ModalVideoPlayer : public BaseModalObject {
+public:
+
+ virtual bool pollEvent() { return true; }
+ virtual bool handleMessage(ExCommand *message) { return true; }
+ virtual bool init(int counterdiff) { return false; }
+ virtual void update() {}
+ virtual void saveload() {}
+
+ void play(const char *fname);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_MODAL_H */
diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk
new file mode 100644
index 0000000000..88e3ac5d02
--- /dev/null
+++ b/engines/fullpipe/module.mk
@@ -0,0 +1,39 @@
+MODULE := engines/fullpipe
+
+MODULE_OBJS = \
+ behavior.o \
+ detection.o \
+ floaters.o \
+ fullpipe.o \
+ gameloader.o \
+ gfx.o \
+ init.o \
+ input.o \
+ interaction.o \
+ inventory.o \
+ lift.o \
+ messagehandlers.o \
+ messages.o \
+ modal.o \
+ motion.o \
+ ngiarchive.o \
+ scene.o \
+ scenes.o \
+ sound.o \
+ stateloader.o \
+ statics.o \
+ utils.o \
+ scenes/scene01.o \
+ scenes/scene02.o \
+ scenes/scene03.o \
+ scenes/scene04.o \
+ scenes/sceneDbg.o \
+ scenes/sceneIntro.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_FULLPIPE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
new file mode 100644
index 0000000000..f67011a50f
--- /dev/null
+++ b/engines/fullpipe/motion.cpp
@@ -0,0 +1,1611 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "common/file.h"
+#include "common/array.h"
+#include "common/list.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/gameloader.h"
+
+namespace Fullpipe {
+
+bool MotionController::load(MfcArchive &file) {
+ // Is originally empty file.readClass();
+
+ debug(5, "MotionController::load()");
+
+ return true;
+}
+
+bool MctlCompound::load(MfcArchive &file) {
+ debug(5, "MctlCompound::load()");
+
+ int count = file.readUint32LE();
+
+ debug(6, "MctlCompound::count = %d", count);
+
+ for (int i = 0; i < count; i++) {
+ debug(6, "CompoundArray[%d]", i);
+ MctlCompoundArrayItem *obj = new MctlCompoundArrayItem();
+
+ obj->_motionControllerObj = (MotionController *)file.readClass();
+
+ int count1 = file.readUint32LE();
+
+ debug(6, "ConnectionPoint::count: %d", count1);
+ for (int j = 0; j < count1; j++) {
+ debug(6, "ConnectionPoint[%d]", j);
+ MctlConnectionPoint *obj1 = (MctlConnectionPoint *)file.readClass();
+
+ obj->_connectionPoints.push_back(obj1);
+ }
+
+ obj->_field_20 = file.readUint32LE();
+ obj->_field_24 = file.readUint32LE();
+
+ debug(6, "graphReact");
+ obj->_movGraphReactObj = (MovGraphReact *)file.readClass();
+
+ _motionControllers.push_back(obj);
+ }
+
+ return true;
+}
+
+void MctlCompound::addObject(StaticANIObject *obj) {
+ for (uint i = 0; i < _motionControllers.size(); i++)
+ _motionControllers[i]->_motionControllerObj->addObject(obj);
+}
+
+int MctlCompound::removeObject(StaticANIObject *obj) {
+ warning("STUB: MctlCompound::removeObject()");
+
+ return 0;
+}
+
+void MctlCompound::initMovGraph2() {
+ if (_objtype != kObjTypeMctlCompound)
+ return;
+
+ for (uint i = 0; i < _motionControllers.size(); i++) {
+ if (_motionControllers[i]->_motionControllerObj->_objtype != kObjTypeMovGraph)
+ continue;
+
+ MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj;
+
+ MovGraph2 *newgr = new MovGraph2();
+
+ newgr->_links = gr->_links;
+ newgr->_nodes = gr->_nodes;
+
+ gr->_links.clear();
+ gr->_nodes.clear();
+
+ delete gr;
+
+ _motionControllers[i]->_motionControllerObj = newgr;
+ }
+}
+
+void MctlCompound::freeItems() {
+ for (uint i = 0; i < _motionControllers.size(); i++)
+ _motionControllers[i]->_motionControllerObj->freeItems();
+}
+
+MessageQueue *MctlCompound::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ warning("STUB: MctlCompound::method34()");
+
+ return 0;
+}
+
+MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ int match1 = -1;
+ int match2 = -1;
+
+ if (!subj)
+ return 0;
+
+ for (uint i = 0; i < _motionControllers.size(); i++) {
+ if (_motionControllers[i]->_movGraphReactObj) {
+ if (_motionControllers[i]->_movGraphReactObj->pointInRegion(subj->_ox, subj->_oy)) {
+ match1 = i;
+ break;
+ }
+ }
+ }
+
+ if (match1 == -1)
+ return 0;
+
+ for (uint i = 0; i < _motionControllers.size(); i++) {
+ if (_motionControllers[i]->_movGraphReactObj) {
+ if (_motionControllers[i]->_movGraphReactObj->pointInRegion(xpos, ypos)) {
+ match2 = i;
+ break;
+ }
+ }
+ }
+
+ if (match2 == -1)
+ return 0;
+
+ if (match1 == match2)
+ return _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId);
+
+ MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &match2);
+
+ if (!closestP)
+ return 0;
+
+ MessageQueue *mq = _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, closestP->_connectionX, closestP->_connectionY, 1, closestP->_field_14);
+
+ ExCommand *ex;
+
+ if (mq) {
+ for (uint i = 0; i < closestP->_messageQueueObj->getCount(); i++) {
+ ex = new ExCommand(closestP->_messageQueueObj->getExCommandByIndex(i));
+ ex->_excFlags |= 2;
+ mq->_exCommands.push_back(ex);
+ }
+
+ ex = new ExCommand(subj->_id, 51, 0, xpos, ypos, 0, 1, 0, 0, 0);
+
+ ex->_field_20 = fuzzyMatch;
+ ex->_keyCode = subj->_okeyCode;
+ ex->_excFlags |= 2;
+
+ mq->_exCommands.push_back(ex);
+ }
+
+ return mq;
+}
+
+MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr) {
+ warning("STUB: MctlCompound::findClosestConnectionPoint()");
+
+ return 0;
+}
+
+bool MctlCompoundArray::load(MfcArchive &file) {
+ debug(5, "MctlCompoundArray::load()");
+
+ int count = file.readUint32LE();
+
+ debug(0, "MctlCompoundArray::count = %d", count);
+
+ assert(0);
+
+ return true;
+}
+
+MovGraphItem::MovGraphItem() {
+ ani = 0;
+ field_4 = 0;
+ field_8 = 0;
+ field_C = 0;
+ field_10 = 0;
+ field_14 = 0;
+ field_18 = 0;
+ field_1C = 0;
+ field_20 = 0;
+ field_24 = 0;
+ items = 0;
+ count = 0;
+ field_30 = 0;
+ field_34 = 0;
+ field_38 = 0;
+ field_3C = 0;
+}
+
+int MovGraph_messageHandler(ExCommand *cmd);
+
+int MovGraphCallback(int a1, int a2, int a3) {
+ warning("STUB: MovgraphCallback");
+
+ return 0;
+}
+
+MovGraph::MovGraph() {
+ _callback1 = MovGraphCallback;
+ _field_44 = 0;
+ insertMessageHandler(MovGraph_messageHandler, getMessageHandlersCount() - 1, 129);
+
+ _objtype = kObjTypeMovGraph;
+}
+
+bool MovGraph::load(MfcArchive &file) {
+ debug(5, "MovGraph::load()");
+
+ _links.load(file);
+ _nodes.load(file);
+
+ return true;
+}
+
+void MovGraph::addObject(StaticANIObject *obj) {
+ _mgm.clear();
+ _mgm.addItem(obj->_id);
+
+ for (uint i = 0; i < _items.size(); i++)
+ if (_items[i]->ani == obj)
+ return;
+
+ MovGraphItem *item = new MovGraphItem();
+
+ item->ani = obj;
+
+ _items.push_back(item);
+
+ _mgm.addItem(obj->_id); // FIXME: Is it really needed?
+}
+
+int MovGraph::removeObject(StaticANIObject *obj) {
+ warning("STUB: MovGraph::removeObject()");
+
+ return 0;
+}
+
+void MovGraph::freeItems() {
+ warning("STUB: MovGraph::freeItems()");
+}
+
+int MovGraph::method28() {
+ warning("STUB: MovGraph::method28()");
+
+ return 0;
+}
+
+int MovGraph::method2C() {
+ warning("STUB: MovGraph::method2C()");
+
+ return 0;
+}
+
+MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ warning("STUB: MovGraph::method34()");
+
+ return 0;
+}
+
+int MovGraph::changeCallback() {
+ warning("STUB: MovGraph::changeCallback()");
+
+ return 0;
+}
+
+int MovGraph::method3C() {
+ warning("STUB: MovGraph::method3C()");
+
+ return 0;
+}
+
+int MovGraph::method44() {
+ warning("STUB: MovGraph::method44()");
+
+ return 0;
+}
+
+MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ warning("STUB: MovGraph::doWalkTo()");
+
+ return 0;
+}
+
+int MovGraph::method50() {
+ warning("STUB: MovGraph::method50()");
+
+ return 0;
+}
+
+double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch) {
+ int n1x = link->_movGraphNode1->_x;
+ int n1y = link->_movGraphNode1->_y;
+ int n2x = link->_movGraphNode2->_x;
+ int n2y = link->_movGraphNode2->_y;
+ double dist1x = (double)(point->x - n1x);
+ double dist1y = (double)(n1y - point->y);
+ double dist2x = (double)(n2x - n1x);
+ double dist2y = (double)(n2y - n1y);
+ double dist1 = sqrt(dist1y * dist1y + dist1x * dist1x);
+ double dist2 = ((double)(n1y - n2y) * dist1y + dist2x * dist1x) / link->_distance / dist1;
+ double distm = dist2 * dist1;
+ double res = sqrt(1.0 - dist2 * dist2) * dist1;
+
+ if (dist2 <= 0.0 || distm >= link->_distance) {
+ if (fuzzyMatch) {
+ if (dist2 > 0.0) {
+ if (distm >= link->_distance) {
+ point->x = n2x;
+ point->y = n2y;
+ }
+ } else {
+ point->x = n1x;
+ point->y = n1y;
+ }
+ } else {
+ return -1.0;
+ }
+ } else {
+ point->x = n1x + (dist2x * distm / link->_distance);
+ point->y = n1y + (dist2y * distm / link->_distance);
+ }
+
+ return res;
+}
+
+void MovGraph::calcNodeDistancesAndAngles() {
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ assert(((CObject *)*i)->_objtype == kObjTypeMovGraphLink);
+
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ lnk->_flags &= 0x7FFFFFFF;
+
+ lnk->calcNodeDistanceAndAngle();
+ }
+}
+
+int MovGraph2::getItemIndexByGameObjectId(int objectId) {
+ for (uint i = 0; i < _items2.size(); i++)
+ if (_items2[i]->_objectId == objectId)
+ return i;
+
+ return -1;
+}
+
+int MovGraph2::getItemSubIndexByStaticsId(int idx, int staticsId) {
+ for (int i = 0; i < 4; i++)
+ if (_items2[idx]->_subItems[i]._staticsId1 == staticsId || _items2[idx]->_subItems[i]._staticsId2 == staticsId)
+ return i;
+
+ return -1;
+}
+
+int MovGraph2::getItemSubIndexByMovementId(int idx, int movId) {
+ for (int i = 0; i < 4; i++)
+ if (_items2[idx]->_subItems[i]._walk[0]._movementId == movId || _items2[idx]->_subItems[i]._turn[0]._movementId == movId ||
+ _items2[idx]->_subItems[i]._turnS[0]._movementId == movId)
+ return i;
+
+ return -1;
+}
+
+int MovGraph2::getItemSubIndexByMGM(int idx, StaticANIObject *ani) {
+ warning("STUB: MovGraph2::getItemSubIndexByMGM()");
+
+ return -1;
+}
+
+bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
+ item->_obj = obj;
+ item->_objectId = obj->_id;
+
+ GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(obj->_objectName);
+ if (!var)
+ return false;
+
+ var = var->getSubVarByName("Test_walk");
+
+ if (!var)
+ return false;
+
+ GameVar *varD = 0;
+ Common::Point point;
+
+ for (int dir = 0; dir < 4; dir++) {
+ switch (dir) {
+ case 0:
+ varD = var->getSubVarByName("Right");
+ break;
+ case 1:
+ varD = var->getSubVarByName("Left");
+ break;
+ case 2:
+ varD = var->getSubVarByName("Up");
+ break;
+ case 3:
+ varD = var->getSubVarByName("Down");
+ break;
+ }
+
+ if (!varD)
+ return false;
+
+ for (int act = 0; act < 3; act++) {
+ int idx = 0;
+
+ switch(act) {
+ case 0:
+ idx = varD->getSubVarAsInt("Start");
+ break;
+ case 1:
+ idx = varD->getSubVarAsInt("Go");
+ break;
+ case 2:
+ idx = varD->getSubVarAsInt("Stop");
+ break;
+ }
+
+ item->_subItems[dir]._walk[act]._movementId = idx;
+
+ Movement *mov = obj->getMovementById(idx);
+
+ item->_subItems[dir]._walk[act]._mov = mov;
+ if (mov) {
+ mov->calcSomeXY(point, 0);
+ item->_subItems[dir]._walk[act]._mx = point.x;
+ item->_subItems[dir]._walk[act]._my = point.y;
+ }
+ }
+
+ for (int act = 0; act < 4; act++) {
+ int idx = 0;
+
+ switch(act) {
+ case 0:
+ idx = varD->getSubVarAsInt("TurnR");
+ break;
+ case 1:
+ idx = varD->getSubVarAsInt("TurnL");
+ break;
+ case 2:
+ idx = varD->getSubVarAsInt("TurnU");
+ break;
+ case 3:
+ idx = varD->getSubVarAsInt("TurnD");
+ break;
+ }
+
+ item->_subItems[dir]._turn[act]._movementId = idx;
+
+ Movement *mov = obj->getMovementById(idx);
+
+ item->_subItems[dir]._turn[act]._mov = mov;
+ if (mov) {
+ mov->calcSomeXY(point, 0);
+ item->_subItems[dir]._turn[act]._mx = point.x;
+ item->_subItems[dir]._turn[act]._my = point.y;
+ }
+ }
+
+ for (int act = 0; act < 4; act++) {
+ int idx = 0;
+
+ switch(act) {
+ case 0:
+ idx = varD->getSubVarAsInt("TurnSR");
+ break;
+ case 1:
+ idx = varD->getSubVarAsInt("TurnSL");
+ break;
+ case 2:
+ idx = varD->getSubVarAsInt("TurnSU");
+ break;
+ case 3:
+ idx = varD->getSubVarAsInt("TurnSD");
+ break;
+ }
+
+ item->_subItems[dir]._turnS[act]._movementId = idx;
+
+ Movement *mov = obj->getMovementById(idx);
+
+ item->_subItems[dir]._turnS[act]._mov = mov;
+ if (mov) {
+ mov->calcSomeXY(point, 0);
+ item->_subItems[dir]._turnS[act]._mx = point.x;
+ item->_subItems[dir]._turnS[act]._my = point.y;
+ }
+ }
+
+ item->_subItems[dir]._staticsId1 = item->_subItems[dir]._walk[0]._mov->_staticsObj1->_staticsId;
+ item->_subItems[dir]._staticsId2 = item->_subItems[dir]._walk[0]._mov->_staticsObj2->_staticsId;
+
+ }
+ return true;
+}
+
+void MovGraph2::addObject(StaticANIObject *obj) {
+ MovGraph::addObject(obj);
+
+ int id = getItemIndexByGameObjectId(obj->_id);
+
+ if (id >= 0) {
+ _items2[id]->_obj = obj;
+ } else {
+ MovGraph2Item *item = new MovGraph2Item;
+
+ if (initDirections(obj, item)) {
+ _items2.push_back(item);
+ } else {
+ delete item;
+ }
+ }
+}
+
+void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst) {
+ MovInfo1Sub *elem;
+ Common::Point point;
+ Common::Rect rect;
+
+ int subIndex = movinfo->subIndex;
+
+ movinfo->items.clear();
+
+ elem = new MovInfo1Sub;
+ elem->subIndex = subIndex;
+ elem->x = movinfo->pt1.x;
+ elem->y = movinfo->pt1.y;
+ elem->distance = -1;
+
+ movinfo->items.push_back(elem);
+
+ int prevSubIndex = movinfo->subIndex;
+
+ for (uint i = 0; i < linkList->size(); i++) {
+ int idx1;
+
+ if (linkList->size() <= 1) {
+ if (linkList->size() == 1)
+ idx1 = getShortSide((*linkList)[0], movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y);
+ else
+ idx1 = getShortSide(0, movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y);
+
+ point.y = -1;
+ rect.bottom = -1;
+ rect.right = -1;
+ rect.top = -1;
+ rect.left = -1;
+ } else {
+ idx1 = findLink(linkList, i, &rect, &point);
+ }
+
+ if (idx1 != prevSubIndex) {
+ prevSubIndex = idx1;
+ subIndex = idx1;
+
+ elem = new MovInfo1Sub;
+ elem->subIndex = subIndex;
+ elem->x = rect.left;
+ elem->y = rect.top;
+ elem->distance = -1;
+
+ movinfo->items.push_back(elem);
+ }
+
+ if (i != linkList->size() - 1) {
+ while (1) {
+ i++;
+ if (findLink(linkList, i, &rect, 0) != prevSubIndex) {
+ i--;
+ findLink(linkList, i, &rect, &point);
+
+ break;
+ }
+
+ if (i == linkList->size() - 1)
+ break;
+ }
+ }
+
+ if (movinfo->items.back()->subIndex != 10) {
+ subIndex = prevSubIndex;
+
+ elem = new MovInfo1Sub;
+ elem->subIndex = 10;
+ elem->x = -1;
+ elem->y = -1;
+ elem->distance = -1;
+
+ movinfo->items.push_back(elem);
+
+ if (i == linkList->size()) {
+ elem = new MovInfo1Sub;
+ elem->subIndex = prevSubIndex;
+ elem->x = movinfo->pt2.x;
+ elem->y = movinfo->pt2.y;
+ elem->distance = movinfo->distance2;
+
+ movinfo->items.push_back(elem);
+ } else {
+ elem = new MovInfo1Sub;
+ elem->subIndex = prevSubIndex;
+ elem->x = rect.right;
+ elem->y = rect.bottom;
+ elem->distance = point.y;
+
+ movinfo->items.push_back(elem);
+ }
+ }
+ }
+
+ if (subIndex != movinfo->item1Index) {
+ elem = new MovInfo1Sub;
+ elem->subIndex = movinfo->item1Index;
+ elem->x = movinfo->pt2.x;
+ elem->y = movinfo->pt2.y;
+ elem->distance = movinfo->distance2;
+
+ movinfo->items.push_back(elem);
+ }
+
+ movinfo->itemsCount = movinfo->items.size();
+}
+
+MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
+ MovInfo1 movinfo;
+
+ memcpy(&movinfo, movInfo, sizeof(movinfo));
+
+ int curX = movInfo->pt1.x;
+ int curY = movInfo->pt1.y;
+ int curDistance = movInfo->distance1;
+
+ MessageQueue *mq = new MessageQueue(g_fullpipe->_globalMessageQueueList->compact());
+
+ for (int i = 0; i < movInfo->itemsCount - 1; i++) {
+ if (movInfo->items[i + 1]->subIndex != 10) {
+ MG2I *mg2i;
+
+ if (i >= movInfo->itemsCount - 2 || movInfo->items[i + 2]->subIndex != 10) {
+ movinfo.flags = 0;
+ mg2i = &_items2[movInfo->field_0]->_subItems[movInfo->items[i]->subIndex]._turnS[movInfo->items[i + 1]->subIndex];
+ } else {
+ movinfo.flags = 2;
+ mg2i = &_items2[movInfo->field_0]->_subItems[movInfo->items[i]->subIndex]._turn[movInfo->items[i + 1]->subIndex];
+ }
+ if (i < movInfo->itemsCount - 2
+ || (movInfo->items[i]->x == movInfo->items[i + 1]->x
+ && movInfo->items[i]->y == movInfo->items[i + 1]->y)
+ || movInfo->items[i]->x == -1
+ || movInfo->items[i]->y == -1
+ || movInfo->items[i + 1]->x == -1
+ || movInfo->items[i + 1]->y == -1) {
+
+ ExCommand *ex = new ExCommand(_items2[movInfo->field_0]->_objectId, 1, mg2i->_movementId, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_excFlags |= 2;
+ ex->_keyCode = _items2[movInfo->field_0]->_obj->_okeyCode;
+ ex->_field_24 = 1;
+ ex->_field_14 = -1;
+ mq->_exCommands.push_back(ex);
+
+ curX += mg2i->_mx;
+ curY += mg2i->_my;
+ } else {
+ MGMInfo mgminfo;
+
+ memset(&mgminfo, 0, sizeof(mgminfo));
+
+ mgminfo.ani = _items2[movInfo->field_0]->_obj;
+ mgminfo.staticsId2 = mg2i->_mov->_staticsObj2->_staticsId;
+ mgminfo.x1 = movInfo->items[i + 1]->x;
+ mgminfo.y1 = movInfo->items[i + 1]->y;
+ mgminfo.field_1C = movInfo->items[i + 1]->distance;
+ mgminfo.staticsId1 = mg2i->_mov->_staticsObj1->_staticsId;
+
+ mgminfo.x2 = movInfo->items[i]->x;
+ mgminfo.y2 = movInfo->items[i]->y;
+ mgminfo.field_10 = 1;
+ mgminfo.flags = 0x7f;
+ mgminfo.movementId = mg2i->_movementId;
+
+ MessageQueue *mq2 = _mgm.genMovement(&mgminfo);
+ mq->transferExCommands(mq2);
+
+ delete mq2;
+
+ curX = movInfo->items[i + 1]->x;
+ curY = movInfo->items[i + 1]->y;
+ }
+ } else {
+ movinfo.item1Index = movInfo->items[i]->subIndex;
+ movinfo.subIndex = movinfo.item1Index;
+ movinfo.pt1.y = curY;
+ movinfo.pt1.x = curX;
+
+ movinfo.distance1 = curDistance;
+ movinfo.pt2.x = movInfo->items[i + 2]->x;
+ movinfo.pt2.y = movInfo->items[i + 2]->y;
+ movinfo.distance2 = movInfo->items[i + 2]->distance;
+
+ if (i >= movInfo->itemsCount - 4
+ || movInfo->items[i + 2]->subIndex == 10
+ || movInfo->items[i + 3]->subIndex == 10
+ || movInfo->items[i + 2]->subIndex == movInfo->items[i + 3]->subIndex
+ || movInfo->items[i + 4]->subIndex != 10) {
+ if (i >= movInfo->itemsCount - 3
+ || movInfo->items[i + 2]->subIndex == 10
+ || movInfo->items[i + 3]->subIndex == 10
+ || movInfo->items[i + 2]->subIndex == movInfo->items[i + 3]->subIndex) {
+ movinfo.flags &= 3;
+ } else {
+ MG2I *m = &_items2[movInfo->field_0]->_subItems[movInfo->items[i + 2]->subIndex]._turnS[movInfo->items[i + 3]->subIndex];
+ movinfo.pt2.x -= m->_mx;
+ movinfo.pt2.y -= m->_my;
+ movinfo.flags &= 3;
+ }
+ } else {
+ MG2I *m = &_items2[movInfo->field_0]->_subItems[movInfo->items[i + 2]->subIndex]._turn[movInfo->items[i + 3]->subIndex];
+
+ if (movinfo.item1Index && movinfo.item1Index != 1) {
+ movinfo.pt2.y -= m->_my;
+ movinfo.flags = (movinfo.flags & 2) | 1;
+ } else {
+ movinfo.pt2.x -= m->_mx;
+ movinfo.flags = (movinfo.flags & 2) | 1;
+ }
+ }
+ i++; // intentional
+
+ MessageQueue *mq2 = genMovement(&movinfo);
+
+ if (!mq2) {
+ delete mq;
+ return 0;
+ }
+
+ mq->transferExCommands(mq2);
+
+ delete mq2;
+
+ curX = movinfo.pt2.x;
+ curY = movinfo.pt2.y;
+ curDistance = movinfo.distance2;
+ }
+ }
+
+ movInfo->pt2.x = movinfo.pt2.x;
+ movInfo->pt2.y = movinfo.pt2.y;
+
+ return mq;
+}
+
+int MovGraph2::removeObject(StaticANIObject *obj) {
+ warning("STUB: MovGraph2::removeObject()");
+
+ return 0;
+}
+
+void MovGraph2::freeItems() {
+ warning("STUB: MovGraph2::freeItems()");
+}
+
+MessageQueue *MovGraph2::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ if (!ani->isIdle())
+ return 0;
+
+ if (ani->_flags & 0x100)
+ return 0;
+
+ MessageQueue *mq = doWalkTo(ani, xpos, ypos, fuzzyMatch, staticsId);
+
+ if (!mq)
+ return 0;
+
+ if (ani->_movement) {
+ if (mq->getCount() <= 1 || mq->getExCommandByIndex(0)->_messageKind != 22) {
+ PicAniInfo picAniInfo;
+
+ ani->getPicAniInfo(&picAniInfo);
+ ani->updateStepPos();
+ MessageQueue *mq1 = doWalkTo(ani, xpos, ypos, fuzzyMatch, staticsId);
+
+ ani->setPicAniInfo(&picAniInfo);
+
+ if (mq1) {
+ delete mq;
+
+ mq = mq1;
+ }
+ } else {
+ ani->_movement = 0;
+ }
+ }
+
+ if (!mq->chain(ani)) {
+ delete mq;
+
+ return 0;
+ }
+
+ return mq;
+}
+
+MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ LinkInfo linkInfoDest;
+ LinkInfo linkInfoSource;
+ MovInfo1 movInfo1;
+ PicAniInfo picAniInfo;
+ Common::Point point;
+
+ int idx = getItemIndexByGameObjectId(obj->_id);
+
+ if (idx < 0)
+ return 0;
+
+ linkInfoSource.link = 0;
+ linkInfoSource.node = 0;
+
+ linkInfoDest.link = 0;
+ linkInfoDest.node = 0;
+
+ point.x = 0;
+
+ obj->getPicAniInfo(&picAniInfo);
+
+ int idxsub;
+
+ if (obj->_movement)
+ idxsub = getItemSubIndexByMovementId(idx, obj->_movement->_id);
+ else
+ idxsub = getItemSubIndexByStaticsId(idx, obj->_statics->_staticsId);
+
+ bool subMgm = false;
+
+ if (idxsub == -1) {
+ idxsub = getItemSubIndexByMGM(idx, obj);
+ subMgm = true;
+
+ if (idxsub == -1)
+ return 0;
+ }
+
+ if (obj->_movement) {
+ int newx, newy;
+
+ if (subMgm) {
+ obj->_messageQueueId = 0;
+ obj->changeStatics2(_items2[idx]->_subItems[idxsub]._staticsId1);
+ newx = obj->_ox;
+ newy = obj->_oy;
+ } else {
+ obj->_movement->calcSomeXY(point, 0);
+ newx = obj->_movement->_ox - point.x;
+ newy = obj->_movement->_oy - point.y;
+ if (idxsub != 1 && idxsub) {
+ if (idxsub == 2 || idxsub == 3) {
+ newy = obj->_movement->_oy;
+ }
+ } else {
+ newx = obj->_movement->_ox;
+ }
+ }
+
+ obj->_movement = 0;
+ obj->setOXY(newx, newy);
+ }
+
+ if (obj->_ox == xpos && obj->_oy == ypos) {
+ g_fullpipe->_globalMessageQueueList->compact();
+
+ MessageQueue *mq = new MessageQueue();
+
+ if (staticsId && obj->_statics->_staticsId != staticsId) {
+ int idxwalk = getItemSubIndexByStaticsId(idx, staticsId);
+ if (idxwalk == -1) {
+ obj->setPicAniInfo(&picAniInfo);
+
+ delete mq;
+
+ return 0;
+ }
+
+ ExCommand *ex = new ExCommand(picAniInfo.objectId, 1, _items2[idx]->_subItems[idxsub]._walk[idxwalk]._movementId, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_24 = 1;
+ ex->_keyCode = picAniInfo.field_8;
+ ex->_excFlags |= 2;
+
+ mq->_exCommands.push_back(ex);
+ } else {
+ ExCommand *ex = new ExCommand(picAniInfo.objectId, 22, obj->_statics->_staticsId, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_keyCode = picAniInfo.field_8;
+ ex->_excFlags |= 3;
+ mq->_exCommands.push_back(ex);
+
+ ex = new ExCommand(picAniInfo.objectId, 5, -1, obj->_ox, obj->_oy, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = -1;
+ ex->_keyCode = picAniInfo.field_8;
+ ex->_excFlags |= 3;
+ mq->_exCommands.push_back(ex);
+ }
+
+ obj->setPicAniInfo(&picAniInfo);
+
+ return mq;
+ }
+
+ linkInfoSource.node = findNode(obj->_ox, obj->_oy, 0);
+
+ if (!linkInfoSource.node) {
+ linkInfoSource.link = findLink1(obj->_ox, obj->_oy, idxsub, 0);
+
+ if (!linkInfoSource.link) {
+ linkInfoSource.link = findLink2(obj->_ox, obj->_oy);
+
+ if (!linkInfoSource.link) {
+ obj->setPicAniInfo(&picAniInfo);
+
+ return 0;
+ }
+ }
+ }
+
+ linkInfoDest.node = findNode(xpos, ypos, fuzzyMatch);
+
+ if (!linkInfoDest.node) {
+ linkInfoDest.link = findLink1(xpos, ypos, idxsub, fuzzyMatch);
+
+ if (!linkInfoDest.link) {
+ obj->setPicAniInfo(&picAniInfo);
+
+ return 0;
+ }
+ }
+
+ Common::Array<MovGraphLink *> tempLinkList;
+ double minPath = findMinPath(&linkInfoSource, &linkInfoDest, &tempLinkList);
+
+ debug(0, "MovGraph2::doWalkTo(): path: %g parts: %d", minPath, tempLinkList.size());
+
+ if (minPath < 0.0 || ((linkInfoSource.node != linkInfoDest.node || !linkInfoSource.node) && !tempLinkList.size()))
+ return 0;
+
+ memset(&movInfo1, 0, sizeof(movInfo1));
+
+ movInfo1.subIndex = idxsub;
+ movInfo1.pt1.x = obj->_ox;
+ movInfo1.pt1.y = obj->_oy;
+
+ int dx1 = obj->_ox;
+ int dy1 = obj->_oy;
+ int dx2, dy2;
+
+ if (linkInfoSource.node)
+ movInfo1.distance1 = linkInfoSource.node->_distance;
+ else
+ movInfo1.distance1 = linkInfoSource.link->_movGraphNode1->_distance;
+
+ if (linkInfoDest.node) {
+ dx2 = linkInfoDest.node->_x;
+ dy2 = linkInfoDest.node->_y;
+
+ movInfo1.pt2.x = linkInfoDest.node->_x;
+ movInfo1.pt2.y = linkInfoDest.node->_y;
+
+ movInfo1.distance2 = linkInfoDest.node->_distance;
+ } else {
+ movInfo1.pt2.x = xpos;
+ movInfo1.pt2.y = ypos;
+
+ MovGraphNode *nod = linkInfoDest.link->_movGraphNode1;
+ double dst1 = sqrt((double)((ypos - nod->_y) * (ypos - nod->_y) + (xpos - nod->_x) * (xpos - nod->_x)));
+ int dst = linkInfoDest.link->_movGraphNode2->_distance - nod->_distance;
+
+ movInfo1.distance2 = nod->_distance + (dst1 * (double)dst / linkInfoDest.link->_distance);
+
+ calcDistance(&movInfo1.pt2, linkInfoDest.link, 1);
+
+ dx1 = movInfo1.pt1.x;
+ dy1 = movInfo1.pt1.y;
+ dx2 = movInfo1.pt2.x;
+ dy2 = movInfo1.pt2.y;
+ }
+
+ if (staticsId) {
+ movInfo1.item1Index = getItemSubIndexByStaticsId(idx, staticsId);
+ } else if (tempLinkList.size() <= 1) {
+ if (tempLinkList.size() == 1)
+ movInfo1.item1Index = getShortSide(tempLinkList[0], dx2 - dx1, dy2 - dy1);
+ else
+ movInfo1.item1Index = getShortSide(0, dx2 - dx1, dy2 - dy1);
+ } else {
+ movInfo1.item1Index = findLink(&tempLinkList, tempLinkList.size() - 1, 0, 0);
+ }
+
+ movInfo1.flags = fuzzyMatch != 0;
+
+ if (_items2[idx]->_subItems[idxsub]._staticsId1 != obj->_statics->_staticsId)
+ movInfo1.flags |= 2;
+
+ buildMovInfo1SubItems(&movInfo1, &tempLinkList, &linkInfoSource, &linkInfoDest);
+
+ MessageQueue *mq = buildMovInfo1MessageQueue(&movInfo1);
+
+ linkInfoDest.node = findNode(movInfo1.pt2.x, movInfo1.pt2.y, fuzzyMatch);
+
+ if (!linkInfoDest.node)
+ linkInfoDest.link = findLink1(movInfo1.pt2.x, movInfo1.pt2.y, movInfo1.item1Index, fuzzyMatch);
+
+ if (fuzzyMatch || linkInfoDest.link || linkInfoDest.node) {
+ if (mq && mq->getCount() > 0 && picAniInfo.movementId) {
+ ExCommand *ex = mq->getExCommandByIndex(0);
+
+ if (ex && (ex->_messageKind == 1 || ex->_messageKind == 20)
+ && picAniInfo.movementId == ex->_messageNum
+ && picAniInfo.someDynamicPhaseIndex == ex->_field_14) {
+ mq->deleteExCommandByIndex(0, 1);
+ } else {
+ ex = new ExCommand(picAniInfo.objectId, 5, ex->_messageNum, obj->_ox, obj->_oy, 0, 1, 0, 0, 0);
+ ex->_field_14 = -1;
+ ex->_keyCode = picAniInfo.field_8;
+ ex->_excFlags |= 2;
+ mq->addExCommand(ex);
+
+ ex = new ExCommand(picAniInfo.objectId, 22, _items2[idx]->_subItems[idxsub]._staticsId1, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_keyCode = picAniInfo.field_8;
+ ex->_excFlags |= 3;
+ mq->addExCommand(ex);
+ }
+ }
+ } else {
+ if (mq)
+ delete mq;
+ mq = 0;
+ }
+
+ obj->setPicAniInfo(&picAniInfo);
+
+ return mq;
+}
+
+MovGraphNode *MovGraph2::findNode(int x, int y, int fuzzyMatch) {
+ for (ObList::iterator i = _nodes.begin(); i != _nodes.end(); ++i) {
+ assert(((CObject *)*i)->_objtype == kObjTypeMovGraphNode);
+
+ MovGraphNode *node = (MovGraphNode *)*i;
+
+ if (fuzzyMatch) {
+ if (abs(node->_x - x) < 15 && abs(node->_y - y) < 15)
+ return node;
+ } else {
+ if (node->_x == x && node->_y == y)
+ return node;
+ }
+ }
+
+ return 0;
+}
+
+int MovGraph2::getShortSide(MovGraphLink *lnk, int x, int y) {
+ bool cond;
+
+ if (lnk)
+ cond = abs(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) > abs(lnk->_movGraphNode2->_y - lnk->_movGraphNode1->_y);
+ else
+ cond = abs(x) > abs(y);
+
+ if (cond)
+ return x <= 0;
+ else
+ return ((y > 0) + 2);
+}
+
+int MovGraph2::findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *rect, Common::Point *point) {
+ MovGraphNode *node1 = (*linkList)[idx]->_movGraphNode1;
+ MovGraphNode *node2 = (*linkList)[idx]->_movGraphNode2;
+ MovGraphNode *node3 = node1;
+
+ if (idx != 0) {
+ MovGraphLink *lnk = (*linkList)[idx - 1];
+
+ if (lnk->_movGraphNode2 != node1) {
+ if (lnk->_movGraphNode1 != node1) {
+ if (lnk->_movGraphNode2 == node2 || lnk->_movGraphNode1 == node2) {
+ node3 = node2;
+ node2 = node1;
+ }
+ goto LABEL_7;
+ }
+ }
+ node3 = node1;
+ } else if (idx != (int)(linkList->size() - 1)) {
+ MovGraphLink *lnk = (*linkList)[idx + 1];
+
+ if (lnk->_movGraphNode2 == node1 || lnk->_movGraphNode1 == node1) {
+ node3 = node2;
+ node2 = node1;
+ } else if (lnk->_movGraphNode2 == node2 || lnk->_movGraphNode1 == node2) {
+ node3 = node1;
+ }
+ }
+
+ LABEL_7:
+ if (rect) {
+ rect->left = node3->_x;
+ rect->top = node3->_y;
+ rect->right = node2->_x;
+ rect->bottom = node2->_y;
+ }
+ if (point) {
+ point->x = node3->_distance;
+ point->y = node2->_distance;
+ }
+
+ if (abs(node3->_x - node2->_x) <= abs(node3->_y - node2->_y))
+ return (node3->_y < node2->_x) + 2;
+ else
+ return node3->_x >= node2->_x;
+}
+
+MessageQueue *MovGraph2::genMovement(MovInfo1 *movinfo) {
+ warning("STUB: MovGraph2::genMovement()");
+
+ return 0;
+}
+
+MovGraphLink *MovGraph2::findLink1(int x, int y, int idx, int fuzzyMatch) {
+ Common::Point point;
+ MovGraphLink *res = 0;
+
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ assert(((CObject *)*i)->_objtype == kObjTypeMovGraphLink);
+
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ if (fuzzyMatch) {
+ point.x = x;
+ point.y = y;
+ double dst = calcDistance(&point, lnk, 0);
+
+ if (dst >= 0.0 && dst < 2.0)
+ return lnk;
+ } else if (!(lnk->_flags & 0x20000000)) {
+ if (lnk->_movGraphReact->pointInRegion(x, y)) {
+ if (abs(lnk->_movGraphNode1->_x - lnk->_movGraphNode2->_x) <= abs(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y)) {
+ if (idx == 2 || idx == 3)
+ return lnk;
+ res = lnk;
+ } else {
+ if (idx == 1 || !idx)
+ return lnk;
+ res = lnk;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+MovGraphLink *MovGraph2::findLink2(int x, int y) {
+ double mindist = 1.0e20;
+ MovGraphLink *res = 0;
+
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ assert(((CObject *)*i)->_objtype == kObjTypeMovGraphLink);
+
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ if (!(lnk->_flags & 0x20000000)) {
+ double n1x = lnk->_movGraphNode1->_x;
+ double n1y = lnk->_movGraphNode1->_y;
+ double n2x = lnk->_movGraphNode2->_x;
+ double n2y = lnk->_movGraphNode2->_y;
+ double n1dx = n1x - x;
+ double n1dy = n1y - y;
+ double dst1 = sqrt(n1dy * n1dy + n1dx * n1dx);
+ double coeff1 = ((n1y - n2y) * n1dy + (n2x - n1x) * n1dx) / lnk->_distance / dst1;
+ double dst3 = coeff1 * dst1;
+ double dst2 = sqrt(1.0 - coeff1 * coeff1) * dst1;
+
+ if (coeff1 * dst1 < 0.0) {
+ dst3 = 0.0;
+ dst2 = sqrt(n1dy * n1dy + n1dx * n1dx);
+ }
+ if (dst3 > lnk->_distance) {
+ dst3 = lnk->_distance;
+ dst2 = sqrt((n2x - x) * (n2x - x) + (n2y - y) * (n2y - y));
+ }
+ if (dst3 >= 0.0 && dst3 <= lnk->_distance && dst2 < mindist) {
+ mindist = dst2;
+ res = lnk;
+ }
+ }
+ }
+
+ if (mindist < 1.0e20)
+ return res;
+ else
+ return 0;
+}
+
+double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj) {
+ LinkInfo linkInfoWorkSource;
+
+ if (linkInfoSource->link != linkInfoDest->link || linkInfoSource->node != linkInfoDest->node) {
+ double minDistance = -1.0;
+
+ if (linkInfoSource->node) {
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ if ((lnk->_movGraphNode1 == linkInfoSource->node || lnk->_movGraphNode2 == linkInfoSource->node) && !(lnk->_flags & 0xA0000000)) {
+ linkInfoWorkSource.node = 0;
+ linkInfoWorkSource.link = lnk;
+
+ Common::Array<MovGraphLink *> tmpList;
+
+ lnk->_flags |= 0x80000000;
+
+ double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
+
+ if (newDistance >= 0.0 && (minDistance < 0.0 || newDistance + lnk->_distance < minDistance)) {
+ listObj->clear();
+ listObj->push_back(tmpList);
+
+ minDistance = newDistance + lnk->_distance;
+ }
+
+ lnk->_flags &= 0x7FFFFFFF;
+ }
+ }
+ } else if (linkInfoSource->link) {
+ linkInfoWorkSource.node = linkInfoSource->link->_movGraphNode1;
+ linkInfoWorkSource.link = 0;
+
+ Common::Array<MovGraphLink *> tmpList;
+
+ double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
+
+ if (newDistance >= 0.0) {
+ listObj->clear();
+
+ listObj->push_back(linkInfoSource->link);
+ listObj->push_back(tmpList);
+
+ minDistance = newDistance;
+ }
+
+ linkInfoWorkSource.link = 0;
+ linkInfoWorkSource.node = linkInfoSource->link->_movGraphNode2;
+
+ tmpList.clear();
+
+ newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
+
+ if (newDistance >= 0 && (minDistance < 0.0 || newDistance < minDistance)) {
+ listObj->push_back(linkInfoSource->link);
+ listObj->push_back(tmpList);
+
+ minDistance = newDistance;
+ }
+ }
+
+ return minDistance;
+ } else {
+ if (linkInfoSource->link)
+ listObj->push_back(linkInfoSource->link);
+
+ return 0.0;
+ }
+}
+
+MovGraphNode *MovGraph::calcOffset(int ox, int oy) {
+ MovGraphNode *res = 0;
+ double mindist = 1.0e10;
+
+ for (ObList::iterator i = _nodes.begin(); i != _nodes.end(); ++i) {
+ assert(((CObject *)*i)->_objtype == kObjTypeMovGraphNode);
+
+ MovGraphNode *node = (MovGraphNode *)*i;
+
+ double dist = sqrt((double)((node->_x - oy) * (node->_x - oy) + (node->_x - ox) * (node->_x - ox)));
+ if (dist < mindist) {
+ mindist = dist;
+ res = node;
+ }
+ }
+
+ return res;
+}
+
+void MGM::clear() {
+ _items.clear();
+}
+
+MGMItem::MGMItem() {
+ objId = 0;
+}
+
+MGMSubItem::MGMSubItem() {
+ movement = 0;
+ staticsIndex = 0;
+ field_8 = 0;
+ field_C = 0;
+ x = 0;
+ y = 0;
+}
+
+void MGM::addItem(int objId) {
+ if (getItemIndexById(objId) == -1) {
+ MGMItem *item = new MGMItem();
+
+ item->objId = objId;
+ _items.push_back(item);
+ }
+ rebuildTables(objId);
+}
+
+void MGM::rebuildTables(int objId) {
+ int idx = getItemIndexById(objId);
+
+ if (idx == -1)
+ return;
+
+ _items[idx]->subItems.clear();
+ _items[idx]->statics.clear();
+ _items[idx]->movements1.clear();
+ _items[idx]->movements2.clear();
+
+ StaticANIObject *obj = g_fullpipe->_currentScene->getStaticANIObject1ById(objId, -1);
+
+ if (!obj)
+ return;
+
+ for (uint i = 0; i < obj->_staticsList.size(); i++)
+ _items[idx]->statics.push_back((Statics *)obj->_staticsList[i]);
+
+ for (uint i = 0; i < obj->_movements.size(); i++)
+ _items[idx]->movements1.push_back((Movement *)obj->_movements[i]);
+
+ _items[idx]->subItems.clear();
+}
+
+int MGM::getItemIndexById(int objId) {
+ for (uint i = 0; i < _items.size(); i++)
+ if (_items[i]->objId == objId)
+ return i;
+
+ return -1;
+}
+
+MessageQueue *MGM::genMovement(MGMInfo *mgminfo) {
+ warning("STUB: MGM::genMovement()");
+
+ return 0;
+}
+
+MovGraphLink::MovGraphLink() {
+ _distance = 0;
+ _angle = 0;
+ _flags = 0x10000000;
+ _movGraphNode2 = 0;
+ _movGraphNode1 = 0;
+ _field_3C = 0;
+ _field_38 = 0;
+ _movGraphReact = 0;
+ _name = 0;
+
+ _objtype = kObjTypeMovGraphLink;
+}
+
+bool MovGraphLink::load(MfcArchive &file) {
+ debug(5, "MovGraphLink::load()");
+
+ _dwordArray1.load(file);
+ _dwordArray2.load(file);
+
+ _flags = file.readUint32LE();
+
+ debug(8, "GraphNode1");
+ _movGraphNode1 = (MovGraphNode *)file.readClass();
+ debug(8, "GraphNode2");
+ _movGraphNode2 = (MovGraphNode *)file.readClass();
+
+ _distance = file.readDouble();
+ _angle = file.readDouble();
+
+ debug(8, "distance: %g, angle: %g", _distance, _angle);
+
+ _movGraphReact = (MovGraphReact *)file.readClass();
+ _name = file.readPascalString();
+
+ return true;
+}
+
+void MovGraphLink::calcNodeDistanceAndAngle() {
+ if (_movGraphNode1) {
+ double dx = _movGraphNode2->_x - _movGraphNode1->_x;
+ double dy = _movGraphNode2->_y - _movGraphNode1->_y;
+
+ _distance = sqrt(dy * dy + dx * dx);
+ _angle = atan2(dx, dy);
+ }
+}
+
+bool MovGraphNode::load(MfcArchive &file) {
+ debug(5, "MovGraphNode::load()");
+
+ _field_14 = file.readUint32LE();
+ _x = file.readUint32LE();
+ _y = file.readUint32LE();
+ _distance = file.readUint32LE();
+
+ return true;
+}
+
+ReactParallel::ReactParallel() {
+ _x1 = 0;
+ _x2 = 0;
+ _dy = 0;
+ _dx = 0;
+ _y1 = 0;
+ _y2 = 0;
+}
+
+bool ReactParallel::load(MfcArchive &file) {
+ debug(5, "ReactParallel::load()");
+
+ _x1 = file.readUint32LE();
+ _y1 = file.readUint32LE();
+ _x2 = file.readUint32LE();
+ _y2 = file.readUint32LE();
+ _dx = file.readUint32LE();
+ _dy = file.readUint32LE();
+
+ createRegion();
+
+ return true;
+}
+
+void ReactParallel::createRegion() {
+ _points = (Common::Point **)malloc(sizeof(Common::Point *) * 4);
+
+ for (int i = 0; i < 4; i++)
+ _points[i] = new Common::Point;
+
+ double at = atan2((double)(_x1 - _x2), (double)(_y1 - _y2)) + 1.570796;
+ double sn = sin(at);
+ double cs = cos(at);
+
+ _points[0]->x = (int16)(_x1 - _dx * cs);
+ _points[0]->y = (int16)(_y1 - _dx * sn);
+
+ _points[1]->x = (int16)(_x2 - _dx * cs);
+ _points[1]->y = (int16)(_y2 - _dx * sn);
+
+ _points[2]->x = (int16)(_x2 + _dy * cs);
+ _points[2]->y = (int16)(_y2 + _dy * sn);
+
+ _points[3]->x = (int16)(_x1 + _dy * cs);
+ _points[3]->y = (int16)(_y1 + _dy * sn);
+
+ _pointCount = 4;
+ // GdiObject::Attach(_rgn, CreatePolygonRgn(_points, 4, 2);
+}
+
+void ReactParallel::method14() {
+ warning("STUB: ReactParallel::method14()");
+}
+
+ReactPolygonal::ReactPolygonal() {
+ _field_C = 0;
+ _field_10 = 0;
+}
+
+bool ReactPolygonal::load(MfcArchive &file) {
+ debug(5, "ReactPolygonal::load()");
+
+ _field_C = file.readUint32LE();
+ _field_10 = file.readUint32LE();
+ _pointCount = file.readUint32LE();
+
+ if (_pointCount > 0) {
+ _points = (Common::Point **)malloc(sizeof(Common::Point *) * _pointCount);
+
+ for (int i = 0; i < _pointCount; i++) {
+ _points[i] = new Common::Point;
+
+ _points[i]->x = file.readUint32LE();
+ _points[i]->y = file.readUint32LE();
+ }
+
+ }
+
+ createRegion();
+
+ return true;
+}
+
+void ReactPolygonal::createRegion() {
+ if (_points) {
+
+ // GdiObject::Attach(_rgn, CreatePolygonRgn(_points, _pointCount, 2);
+ }
+}
+
+void ReactPolygonal::method14() {
+ warning("STUB: ReactPolygonal::method14()");
+}
+
+bool MovGraphReact::pointInRegion(int x, int y) {
+ if (_pointCount < 3) {
+ return false;
+ }
+
+ int counter = 0;
+ double xinters;
+ Common::Point p, p1, p2;
+
+ p.x = (double)x;
+ p.y = (double)y;
+
+ p1.x = (double)_points[0]->x;
+ p1.y = (double)_points[0]->y;
+
+ for (int i = 1; i <= _pointCount; i++) {
+ p2.x = (double)_points[i % _pointCount]->x;
+ p2.y = (double)_points[i % _pointCount]->y;
+
+ if (p.y > MIN(p1.y, p2.y)) {
+ if (p.y <= MAX(p1.y, p2.y)) {
+ if (p.x <= MAX(p1.x, p2.x)) {
+ if (p1.y != p2.y) {
+ xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
+ if (p1.x == p2.x || p.x <= xinters) {
+ counter++;
+ }
+ }
+ }
+ }
+ }
+ p1 = p2;
+ }
+
+ if (counter % 2 == 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+int startWalkTo(int objId, int objKey, int x, int y, int a5) {
+ MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId);
+
+ if (mc)
+ return (mc->method34(g_fullpipe->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0);
+
+ return 0;
+}
+
+int doSomeAnimation(int objId, int objKey, int a3) {
+ warning("STUB: doSomeAnimation(%d, %d, %d)", objId, objKey, a3);
+
+ return 0;
+}
+
+int doSomeAnimation2(int objId, int objKey) {
+ return doSomeAnimation(objId, objKey, 0);
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h
new file mode 100644
index 0000000000..bab0ffc8ca
--- /dev/null
+++ b/engines/fullpipe/motion.h
@@ -0,0 +1,372 @@
+/* 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 FULLPIPE_MOTION_H
+#define FULLPIPE_MOTION_H
+
+namespace Fullpipe {
+
+class Statics;
+class Movement;
+class MctlConnectionPoint;
+
+int startWalkTo(int objId, int objKey, int x, int y, int a5);
+int doSomeAnimation(int objId, int objKey, int a3);
+int doSomeAnimation2(int objId, int objKey);
+
+class MotionController : public CObject {
+public:
+ int _field_4;
+ bool _isEnabled;
+
+public:
+ MotionController() : _isEnabled(true), _field_4(0) {}
+ virtual ~MotionController() {}
+ virtual bool load(MfcArchive &file);
+ virtual void methodC() {}
+ virtual void method10() {}
+ virtual void clearEnabled() { _isEnabled = false; }
+ virtual void setEnabled() { _isEnabled = true; }
+ virtual void addObject(StaticANIObject *obj) {}
+ virtual int removeObject(StaticANIObject *obj) { return 0; }
+ virtual void freeItems() {}
+ virtual int method28() { return 0; }
+ virtual int method2C() { return 0; }
+ virtual int method30() { return 0; }
+ virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
+ virtual int changeCallback() { return 0; }
+ virtual int method3C() { return 0; }
+ virtual int method40() { return 0; }
+ virtual int method44() { return 0; }
+ virtual int method48() { return -1; }
+ virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
+};
+
+class MovGraphReact : public CObject {
+public:
+ int _pointCount;
+ Common::Point **_points;
+
+public:
+ MovGraphReact() : _pointCount(0), _points(0) {}
+ ~MovGraphReact() { free(_points); }
+
+ virtual void method14() {}
+ virtual void createRegion() {}
+ virtual bool pointInRegion(int x, int y);
+};
+
+class MctlCompoundArrayItem : public CObject {
+ friend class MctlCompound;
+
+protected:
+ MotionController *_motionControllerObj;
+ MovGraphReact *_movGraphReactObj;
+ Common::Array<MctlConnectionPoint *> _connectionPoints;
+ int _field_20;
+ int _field_24;
+ int _field_28;
+
+public:
+ MctlCompoundArrayItem() : _movGraphReactObj(0), _motionControllerObj(0), _field_20(0), _field_24(0), _field_28(0) {}
+};
+
+class MctlCompoundArray : public Common::Array<MctlCompoundArrayItem *>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+class MctlCompound : public MotionController {
+ MctlCompoundArray _motionControllers;
+
+ public:
+ MctlCompound() { _objtype = kObjTypeMctlCompound; }
+
+ virtual bool load(MfcArchive &file);
+
+ virtual void addObject(StaticANIObject *obj);
+ virtual int removeObject(StaticANIObject *obj);
+ virtual void freeItems();
+ virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+
+ void initMovGraph2();
+ MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr);
+};
+
+struct MGMSubItem {
+ int movement;
+ int staticsIndex;
+ int field_8;
+ int field_C;
+ int x;
+ int y;
+
+ MGMSubItem();
+};
+
+struct MGMItem {
+ int16 objId;
+ Common::Array<MGMSubItem *> subItems;
+ Common::Array<Statics *> statics;
+ Common::Array<Movement *> movements1;
+ Common::Array<Movement *> movements2;
+
+ MGMItem();
+};
+
+struct MGMInfo {
+ StaticANIObject *ani;
+ int staticsId1;
+ int staticsId2;
+ int movementId;
+ int field_10;
+ int x1;
+ int y1;
+ int field_1C;
+ int x2;
+ int y2;
+ int flags;
+};
+
+class MGM : public CObject {
+public:
+ Common::Array<MGMItem *> _items;
+
+public:
+ void clear();
+ void addItem(int objId);
+ void rebuildTables(int objId);
+ int getItemIndexById(int objId);
+
+ MessageQueue *genMovement(MGMInfo *mgminfo);
+};
+
+class MovGraphNode : public CObject {
+public:
+ int _x;
+ int _y;
+ int _distance;
+ int16 _field_10;
+ int _field_14;
+
+public:
+ MovGraphNode() : _x(0), _y(0), _distance(0), _field_10(0), _field_14(0) { _objtype = kObjTypeMovGraphNode; }
+ virtual bool load(MfcArchive &file);
+};
+
+class ReactParallel : public MovGraphReact {
+ //CRgn _rgn;
+ int _x1;
+ int _y1;
+ int _x2;
+ int _y2;
+ int _dx;
+ int _dy;
+
+ public:
+ ReactParallel();
+ virtual bool load(MfcArchive &file);
+
+ virtual void method14();
+ virtual void createRegion();
+};
+
+class ReactPolygonal : public MovGraphReact {
+ //CRgn _rgn;
+ int _field_C;
+ int _field_10;
+
+ public:
+ ReactPolygonal();
+ virtual bool load(MfcArchive &file);
+
+ virtual void method14();
+ virtual void createRegion();
+};
+
+class MovGraphLink : public CObject {
+ public:
+ MovGraphNode *_movGraphNode1;
+ MovGraphNode *_movGraphNode2;
+ DWordArray _dwordArray1;
+ DWordArray _dwordArray2;
+ int _flags;
+ int _field_38;
+ int _field_3C;
+ double _distance;
+ double _angle;
+ MovGraphReact *_movGraphReact;
+ char *_name;
+
+ public:
+ MovGraphLink();
+ virtual bool load(MfcArchive &file);
+
+ void calcNodeDistanceAndAngle();
+};
+
+struct MovGraphItem {
+ StaticANIObject *ani;
+ int field_4;
+ int field_8;
+ int field_C;
+ int field_10;
+ int field_14;
+ int field_18;
+ int field_1C;
+ int field_20;
+ int field_24;
+ int items;
+ int count;
+ int field_30;
+ int field_34;
+ int field_38;
+ int field_3C;
+
+ MovGraphItem();
+};
+
+class MovGraph : public MotionController {
+public:
+ ObList _nodes;
+ ObList _links;
+ int _field_44;
+ Common::Array<MovGraphItem *> _items;
+ int (*_callback1)(int, int, int);
+ MGM _mgm;
+
+public:
+ MovGraph();
+ virtual bool load(MfcArchive &file);
+
+ virtual void addObject(StaticANIObject *obj);
+ virtual int removeObject(StaticANIObject *obj);
+ virtual void freeItems();
+ virtual int method28();
+ virtual int method2C();
+ virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual int changeCallback();
+ virtual int method3C();
+ virtual int method44();
+ virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual int method50();
+
+ double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch);
+ void calcNodeDistancesAndAngles();
+ MovGraphNode *calcOffset(int ox, int oy);
+};
+
+class Movement;
+
+struct MG2I {
+ int _movementId;
+ Movement *_mov;
+ int _mx;
+ int _my;
+};
+
+struct MovGraph2ItemSub {
+ int _staticsId2;
+ int _staticsId1;
+ MG2I _walk[3];
+ MG2I _turn[4];
+ MG2I _turnS[4];
+};
+
+struct LinkInfo {
+ MovGraphLink *link;
+ MovGraphNode *node;
+};
+
+struct MovInfo1Sub {
+ int subIndex;
+ int x;
+ int y;
+ int distance;
+};
+
+struct MovInfo1 {
+ int field_0;
+ Common::Point pt1;
+ Common::Point pt2;
+ int distance1;
+ int distance2;
+ int subIndex;
+ int item1Index;
+ Common::Array<MovInfo1Sub *> items;
+ int itemsCount;
+ int flags;
+};
+
+struct MovGraph2Item { // 744
+ int _objectId;
+ StaticANIObject *_obj;
+ MovGraph2ItemSub _subItems[4]; // 184
+};
+
+class MovGraph2 : public MovGraph {
+public:
+ Common::Array<MovGraph2Item *> _items2;
+
+public:
+ virtual void addObject(StaticANIObject *obj);
+ virtual int removeObject(StaticANIObject *obj);
+ virtual void freeItems();
+ virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+
+ int getItemIndexByGameObjectId(int objectId);
+ int getItemSubIndexByStaticsId(int index, int staticsId);
+ int getItemSubIndexByMovementId(int index, int movId);
+ int getItemSubIndexByMGM(int idx, StaticANIObject *ani);
+
+ int getShortSide(MovGraphLink *lnk, int x, int y);
+ int findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *a3, Common::Point *a4);
+
+ bool initDirections(StaticANIObject *obj, MovGraph2Item *item);
+ void buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst);
+ MessageQueue *buildMovInfo1MessageQueue(MovInfo1 *movInfo);
+
+ MovGraphNode *findNode(int x, int y, int fuzzyMatch);
+ MovGraphLink *findLink1(int x, int y, int idx, int fuzzyMatch);
+ MovGraphLink *findLink2(int x, int y);
+ double findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj);
+
+ MessageQueue *genMovement(MovInfo1 *movinfo);
+};
+
+class MctlConnectionPoint : public CObject {
+public:
+ int _connectionX;
+ int _connectionY;
+ int _field_C;
+ int _field_10;
+ int16 _field_14;
+ int16 _field_16;
+ MessageQueue *_messageQueueObj;
+ int _motionControllerObj;
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_MOTION_H */
diff --git a/engines/fullpipe/ngiarchive.cpp b/engines/fullpipe/ngiarchive.cpp
new file mode 100644
index 0000000000..5d895c17a0
--- /dev/null
+++ b/engines/fullpipe/ngiarchive.cpp
@@ -0,0 +1,156 @@
+/* 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 "fullpipe/fullpipe.h"
+#include "common/archive.h"
+
+#include "common/file.h"
+#include "common/hash-str.h"
+#include "common/memstream.h"
+#include "common/bufferedstream.h"
+#include "common/textconsole.h"
+
+#include "fullpipe/ngiarchive.h"
+
+namespace Fullpipe {
+
+NGIArchive::NGIArchive(const Common::String &filename) : _ngiFilename(filename) {
+ Common::File ngiFile;
+
+ if (!ngiFile.open(_ngiFilename)) {
+ warning("NGIArchive::NGIArchive(): Could not find the archive file");
+ return;
+ }
+
+ ngiFile.seek(4, SEEK_SET);
+
+ unsigned int count = ngiFile.readUint16LE(); // How many entries?
+
+ ngiFile.seek(20, SEEK_SET);
+
+ unsigned int key = ngiFile.readUint16LE();
+
+ byte key1, key2;
+
+ key1 = key & 0xff;
+ key2 = (key >> 8) & 0xff;
+
+ int fatSize = count * 32;
+
+ ngiFile.seek(32, SEEK_SET);
+
+ byte *fat = (byte *)calloc(fatSize, 1);
+
+ ngiFile.read(fat, fatSize);
+
+ for (int i = 0; i < fatSize; i++) {
+ key1 = (key1 << 1) ^ key2;
+ key2 = (key2 >> 1) ^ key1;
+
+ fat[i] ^= key1;
+ }
+
+ NgiHeader header;
+ NgiHeader *head;
+
+ for (uint i = 0; i < count; i++) {
+ memcpy(header.filename, &fat[i * 32], 12);
+ header.filename[12] = 0;
+ header.flags = READ_LE_UINT32(&fat[i * 32 + 16]);
+ header.extVal = READ_LE_UINT32(&fat[i * 32 + 20]);
+ header.pos = READ_LE_UINT32(&fat[i * 32 + 24]);
+ header.size = READ_LE_UINT32(&fat[i * 32 + 28]);
+
+ if (header.flags & 0x1e0) {
+ warning("File has flags: %.8x\n", header.flags & 0x1e0);
+ }
+
+ head = new NgiHeader(header);
+
+ _headers[header.filename] = head;
+ }
+
+ free(fat);
+
+ g_fullpipe->_currArchive = this;
+
+ debug(0, "NGIArchive::NGIArchive(%s): Located %d files", filename.c_str(), _headers.size());
+}
+
+NGIArchive::~NGIArchive() {
+ debug(0, "NGIArchive Destructor Called");
+ NgiHeadersMap::iterator it = _headers.begin();
+ for ( ; it != _headers.end(); ++it) {
+ delete it->_value;
+ }
+
+ g_fullpipe->_currArchive = 0;
+}
+
+bool NGIArchive::hasFile(const Common::String &name) const {
+ return _headers.contains(name);
+}
+
+ int NGIArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int matches = 0;
+
+ NgiHeadersMap::const_iterator it = _headers.begin();
+ for ( ; it != _headers.end(); ++it) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(it->_value->filename, this)));
+ matches++;
+ }
+
+ return matches;
+}
+
+const Common::ArchiveMemberPtr NGIArchive::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *NGIArchive::createReadStreamForMember(const Common::String &name) const {
+ if (!_headers.contains(name)) {
+ return 0;
+ }
+
+ NgiHeader *hdr = _headers[name];
+
+ Common::File archiveFile;
+ archiveFile.open(_ngiFilename);
+ archiveFile.seek(hdr->pos, SEEK_SET);
+
+ byte *data = (byte *)malloc(hdr->size);
+ assert(data);
+
+ int32 len = archiveFile.read(data, hdr->size);
+ assert(len == hdr->size);
+
+ return new Common::MemoryReadStream(data, hdr->size, DisposeAfterUse::YES);
+}
+
+Common::Archive *makeNGIArchive(const Common::String &name) {
+ return new NGIArchive(name);
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/ngiarchive.h b/engines/fullpipe/ngiarchive.h
new file mode 100644
index 0000000000..a5b05a2e50
--- /dev/null
+++ b/engines/fullpipe/ngiarchive.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 FULLPIPE_NGIARCHIVE_H
+#define FULLPIPE_NGIARCHIVE_H
+
+#include "common/str.h"
+
+namespace Fullpipe {
+
+class Archive;
+
+#define NGI_FILENAME_MAX 13
+
+struct NgiHeader {
+ int32 pos;
+ int32 extVal;
+ int32 flags;
+ int32 size;
+ char filename[NGI_FILENAME_MAX];
+};
+
+typedef Common::HashMap<Common::String, NgiHeader*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> NgiHeadersMap;
+
+class NGIArchive : public Common::Archive {
+ NgiHeadersMap _headers;
+ Common::String _ngiFilename;
+
+public:
+ NGIArchive(const Common::String &name);
+ virtual ~NGIArchive();
+
+ // Archive implementation
+ virtual bool hasFile(const Common::String &name) const;
+ virtual int listMembers(Common::ArchiveMemberList &list) const;
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
+/**
+ * This factory method creates an Archive instance corresponding to the content
+ * of the NGI compressed file with the given name.
+ *
+ * May return 0 in case of a failure.
+ */
+Common::Archive *makeNGIArchive(const Common::String &name);
+
+} // End of namespace Fullpipe
+
+#endif
diff --git a/engines/fullpipe/objectnames.h b/engines/fullpipe/objectnames.h
new file mode 100644
index 0000000000..241e31b165
--- /dev/null
+++ b/engines/fullpipe/objectnames.h
@@ -0,0 +1,250 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// This file is used in order to avoid usage of constants in Russian accross the code
+
+#ifndef FULLPIPE_OBJECTNAMES_H
+#define FULLPIPE_OBJECTNAMES_H
+
+namespace Fullpipe {
+
+#define sO_Grandma "\xc1\xe0\xe1\xf3\xeb\xff" // "БабулÑ"
+#define sO_Jar_4 "\xc1\xe0\xed\xea\xe0_4" // "Банка_4"
+#define sO_Pool "\xc1\xe0\xf1\xf1\xe5\xe9\xed" // "БаÑÑейн"
+#define sO_TumyTrampie "\xc1\xe0\xf2\xf3\xf2\xe0" // "Батута"
+#define sO_WithoutBoot "\xc1\xe5\xe7 \xe1\xee\xf2\xe8\xed\xea\xe0" // "Без ботинка"
+#define sO_WithoutJug "\xc1\xe5\xe7 \xe3\xee\xf0\xf8\xea\xee\xe2" // "Без горшков"
+#define sO_WithoutCarpet "\xc1\xe5\xe7 \xea\xee\xe2\xf0\xe8\xea\xe0" // "Без коврика"
+#define sO_WithoutCoin "\xc1\xe5\xe7 \xec\xee\xed\xe5\xf2\xfb" // "Без монеты"
+#define sO_WithNothing "\xc1\xe5\xe7 \xed\xe8\xf7\xe5\xe3\xee" // "Без ничего"
+#define sO_WithoutHandle "\xc1\xe5\xe7 \xf0\xf3\xf7\xea\xe8" // "Без ручки"
+#define sO_WithoutStool "\xc1\xe5\xe7 \xf2\xe0\xe1\xf3\xf0\xe5\xf2\xea\xe8" // "Без табуретки"
+#define sO_WithoutDrawer "\xc1\xe5\xe7 \xff\xf9\xe8\xea\xe0" // "Без Ñщика"
+#define sO_Blocked "\xc1\xeb\xee\xea\xe8\xf0\xee\xe2\xe0\xed" // "Блокирован"
+#define sO_BlockedShe "\xc1\xeb\xee\xea\xe8\xf0\xee\xe2\xe0\xed\xe0" // "Блокирована"
+#define sO_Awaken "\xc1\xee\xe4\xf0\xf1\xf2\xe2\xf3\xe5\xf2" // "БодрÑтвует"
+#define sO_Boot_15 "\xc1\xee\xf2\xe8\xed\xee\xea_15" // "Ботинок_15"
+#define sO_Bottle_38 "\xc1\xf3\xf2\xfb\xeb\xea\xe0_38" // "Бутылка_38"
+#define sO_InSmokeRoom "\xc2 \xea\xf3\xf0\xe8\xeb\xea\xe5" // "В курилке"
+#define sO_InSock "\xc2 \xed\xee\xf1\xea\xe5" // "Ð’ ноÑке"
+#define sO_InGlasses "\xc2 \xee\xf7\xea\xe0\xf5" // "В очках"
+#define sO_In_14 "\xc2_14" // "Ð’_14"
+#define sO_In_32_Lies "\xc2_32 \xeb\xe5\xe6\xe8\xf2" // "В_32 лежит"
+#define sO_In_32_Stands "\xc2_32 \xf2\xee\xf0\xf7\xe8\xf2" // "В_32 торчит"
+#define sO_In_33 "\xc2_33" // "Ð’_33"
+#define sO_In_7 "\xc2_7" // "Ð’_7"
+#define sO_Together "\xc2\xe4\xe2\xee\xe5\xec" // "Вдвоем"
+#define sO_Valve1_26 "\xc2\xe5\xed\xf2\xe8\xeb\xfc\x31_26" // "Вентиль1_26"
+#define sO_Valve2_26 "\xc2\xe5\xed\xf2\xe8\xeb\xfc\x32_26" // "Вентиль2_26"
+#define sO_Valve3_26 "\xc2\xe5\xed\xf2\xe8\xeb\xfc\x33_26" // "Вентиль3_26"
+#define sO_Valve4_26 "\xc2\xe5\xed\xf2\xe8\xeb\xfc\x34_26" // "Вентиль4_26"
+#define sO_Valve5_26 "\xc2\xe5\xed\xf2\xe8\xeb\xfc\x35_26" // "Вентиль5_26"
+#define sO_Valve_34 "\xc2\xe5\xed\xf2\xe8\xeb\xfc_34" // "Вентиль_34"
+#define sO_UpperHatch_23 "\xc2\xe5\xf0\xf5\xed\xe8\xe9 \xeb\xfe\xea_23" // "Верхний люк_23"
+#define sO_Taken "\xc2\xe7\xff\xf2" // "ВзÑÑ‚"
+#define sO_HangsOnPipe "\xc2\xe8\xf1\xe8\xf2 \xed\xe0 \xf2\xf0\xf3\xe1\xe5" // "ВиÑит на трубе"
+#define sO_On "\xc2\xea\xeb" // "Вкл"
+#define sO_TurnedOn "\xc2\xea\xeb\xfe\xf7\xe5\xed" // "Включен"
+#define sO_Driver "\xc2\xee\xe4\xe8\xeb\xe0" // "Водила"
+#define sO_HareTheNooksiter "\xc2\xf3\xe3\xeb\xf3\xf1\xe5\xe4" // "ВуглуÑед"
+#define sO_Off "\xc2\xfb\xea\xeb" // "Выкл"
+#define sO_TurnedOff "\xc2\xfb\xea\xeb\xfe\xf7\xe5\xed" // "Выключен"
+#define sO_HasGrown "\xc2\xfb\xf0\xee\xf1" // "ВыроÑ"
+#define sO_Boss "\xc3\xeb\xe0\xe2\xe0\xf0\xfc" // "Главарь"
+#define sO_Jug "\xc3\xee\xf0\xf8\xee\xea" // "Горшок"
+#define sO_Strolling "\xc3\xf3\xeb\xff\xe5\xf2" // "ГулÑет"
+#define sO_Yes "\xc4\xe0" // "Да"
+#define sO_Girl "\xc4\xe5\xe2\xee\xf7\xea\xe0" // "Девочка"
+#define sO_Elephantine "\xc4\xe5\xe2\xee\xf7\xea\xe0-\xf1\xeb\xee\xed\xe8\xea" // "Девочка-Ñлоник"
+#define sO_Grandpa "\xc4\xe5\xe4\xf3\xf8\xea\xe0" // "Дедушка"
+#define sO_Plank_25 "\xc4\xee\xf1\xea\xe0_25" // "ДоÑка_25"
+#define sO_Plank_34 "\xc4\xee\xf1\xea\xe0_34" // "ДоÑка_34"
+#define sO_DudeJumped "\xc4\xff\xe4\xff \xef\xf0\xfb\xe3\xe0\xeb" // "ДÑÐ´Ñ Ð¿Ñ€Ñ‹Ð³Ð°Ð»"
+#define sO_Dude "\xc4\xff\xe4\xff" // "ДÑдÑ"
+#define sO_GuvTheDrawer "\xc4\xff\xe4\xff-\xff\xf9\xe8\xea" // "ДÑдÑ-Ñщик"
+#define sO_DudeSwinged "\xc4\xff\xe4\xff_\xea\xe0\xf2\xe0\xeb\xf1\xff" // "ДÑдÑ_каталÑÑ"
+#define sO_Eats "\xc5\xf1\xf2" // "ЕÑÑ‚"
+#define sO_Present "\xc5\xf1\xf2\xfc" // "ЕÑÑ‚ÑŒ"
+#define sO_CloseThing1 "\xc7\xe0\xea\xf0\xfb\xe2\xe0\xe5\xec\xee\xe5 1" // "Закрываемое 1"
+#define sO_CloseThing2 "\xc7\xe0\xea\xf0\xfb\xe2\xe0\xe5\xec\xee\xe5 2" // "Закрываемое 2"
+#define sO_CloseThing3 "\xc7\xe0\xea\xf0\xfb\xe2\xe0\xe5\xec\xee\xe5 3" // "Закрываемое 3"
+#define sO_CloseThing "\xc7\xe0\xea\xf0\xfb\xe2\xe0\xe5\xec\xee\xe5" // "Закрываемое"
+#define sO_Closed "\xc7\xe0\xea\xf0\xfb\xf2" // "Закрыт"
+#define sO_ClosedWithBoot "\xc7\xe0\xea\xf0\xfb\xf2\xe0 \xf1 \xe1\xee\xf2\xe8\xed\xea\xee\xec" // "Закрыта Ñ Ð±Ð¾Ñ‚Ð¸Ð½ÐºÐ¾Ð¼"
+#define sO_IsClosed "\xc7\xe0\xea\xf0\xfb\xf2\xe0" // "Закрыта"
+#define sO_HalfFull "\xc7\xe0\xef\xee\xeb\xed\xe5\xed \xed\xe0\xef\xee\xeb\xee\xe2\xe8\xed\xf3" // "Заполнен наполовину"
+#define sO_Full "\xc7\xe0\xef\xee\xeb\xed\xe5\xed \xf6\xe5\xeb\xe8\xea\xee\xec" // "Заполнен целиком"
+#define sO_MirroredTo "\xc7\xe5\xf0\xea\xe0\xeb\xfc\xed\xe0\xff \xea" // "Ð—ÐµÑ€ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ðº"
+#define sO_Playing "\xc8\xe3\xf0\xe0\xe5\xf2" // "Играет"
+#define sO_Tub "\xca\xe0\xe4\xea\xe0" // "Кадка"
+#define sO_Cactus "\xca\xe0\xea\xf2\xf3\xf1" // "КактуÑ"
+#define sO_SwingingWithBoot "\xca\xe0\xf2\xe0\xe5\xf2\xf1\xff \xf1 \xe1\xee\xf2\xe8\xed\xea\xee\xec" // "КатаетÑÑ Ñ Ð±Ð¾Ñ‚Ð¸Ð½ÐºÐ¾Ð¼"
+#define sO_Swinging "\xca\xe0\xf2\xe0\xe5\xf2\xf1\xff" // "КатаетÑÑ"
+#define sO_Swingie "\xca\xe0\xf7\xe5\xeb\xe5\xed\xff" // "КачеленÑ"
+#define sO_LiftButtons "\xca\xed\xee\xef\xea\xe8 \xeb\xe8\xf4\xf2\xe0" // "Кнопки лифта"
+#define sO_Carpet_35 "\xca\xee\xe2\xf0\xe8\xea_35" // "Коврик_35"
+#define sO_Valve_35 "\xca\xf0\xe0\xed_35" // "Кран_35"
+#define sO_Cup "\xca\xf0\xf3\xe6\xea\xe0" // "Кружка"
+#define sO_Cube "\xca\xf3\xe1\xe8\xea" // "Кубик"
+#define sO_LeftPipe_15 "\xcb\xe5\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_15" // "Ð›ÐµÐ²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_15"
+#define sO_LeftPipe_26 "\xcb\xe5\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_26" // "Ð›ÐµÐ²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_26"
+#define sO_LeftPipe_29 "\xcb\xe5\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_29" // "Ð›ÐµÐ²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_29"
+#define sO_LeftPipe_30 "\xcb\xe5\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_30" // "Ð›ÐµÐ²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_30"
+#define sO_LeftPipe_37 "\xcb\xe5\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_37" // "Ð›ÐµÐ²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_37"
+#define sO_StarsDown_24 "\xcb\xe5\xf1\xf2\xed\xe8\xf6\xe0 \xe2\xed\xe8\xe7_24" // "ЛеÑтница вниз_24"
+#define sO_StairsUp_8 "\xcb\xe5\xf1\xf2\xed\xe8\xf6\xe0 \xf1\xe2\xe5\xf0\xf5\xf3_8" // "ЛеÑтница Ñверху_8"
+#define sO_Stairway "\xcb\xe5\xf1\xf2\xed\xe8\xf6\xe0" // "ЛеÑтница"
+#define sO_Fliers "\xcb\xe5\xf2\xf3\xed\xfb" // "Летуны"
+#define sO_Hatch_26 "\xcb\xfe\xea_26" // "Люк_26"
+#define sO_Hatch_34 "\xcb\xfe\xea_34" // "Люк_34"
+#define sO_MommyOfHandle_32 "\xcc\xe0\xec\xe0 \xf0\xf3\xf7\xea\xe8_32" // "Мама ручки_32"
+#define sO_BigMumsy "\xcc\xe0\xec\xe0\xf8\xe0" // "Мамаша"
+#define sO_Bag_22 "\xcc\xe5\xf8\xee\xea_22" // "Мешок_22"
+#define sO_CoinSlot_1 "\xcc\xee\xed\xe5\xf2\xee\xef\xf0\xe8\xe5\xec\xed\xe8\xea 1" // "Монетоприемник 1"
+#define sO_CoinSlot_22 "\xcc\xee\xed\xe5\xf2\xee\xef\xf0\xe8\xe5\xec\xed\xe8\xea_22" // "Монетоприемник_22"
+#define sO_CoinSlot_35 "\xcc\xee\xed\xe5\xf2\xee\xef\xf0\xe8\xe5\xec\xed\xe8\xea_35" // "Монетоприемник_35"
+#define sO_Bridge "\xcc\xee\xf1\xf2" // "МоÑÑ‚"
+#define sO_Fly_12 "\xcc\xf3\xf5\xe0_12" // "Муха_12"
+#define sO_Fly_17 "\xcc\xf3\xf5\xe0_17" // "Муха_17"
+#define sO_OnTheFloor "\xcd\xe0 \xef\xee\xeb\xf3" // "Ðа полу"
+#define sO_OnTheSpring "\xcd\xe0 \xef\xf0\xf3\xe6\xe8\xed\xe5" // "Ðа пружине"
+#define sO_OnTheTable "\xcd\xe0 \xf1\xf2\xee\xeb\xe5" // "Ðа Ñтоле"
+#define sO_OnStool "\xcd\xe0 \xf2\xe0\xe1\xf3\xf0\xe5\xf2\xea\xe5" // "Ðа табуретке"
+#define sO_Inflater "\xcd\xe0\xe4\xf3\xe2\xe0\xf2\xe5\xeb\xfc" // "Ðадуватель"
+#define sO_NotTaken "\xcd\xe5 \xe2\xe7\xff\xf2" // "Ðе взÑÑ‚"
+#define sO_NotHanging "\xcd\xe5 \xe2\xe8\xf1\xe8\xf2" // "Ðе виÑит"
+#define sO_NotGrown "\xcd\xe5 \xe2\xfb\xf0\xee\xf1" // "Ðе выроÑ"
+#define sO_DidNotCrackEgg "\xcd\xe5 \xea\xee\xeb\xee\xeb \xff\xe9\xf6\xee" // "Ðе колол Ñйцо"
+#define sO_NotFallen "\xcd\xe5 \xef\xe0\xe4\xe0\xeb" // "Ðе падал"
+#define sO_NotAvailable "\xcd\xe5\xe4\xee\xf1\xf2\xf3\xef\xed\xe0" // "ÐедоÑтупна"
+#define sO_CannotTake "\xcd\xe5\xeb\xfc\xe7\xff \xe2\xe7\xff\xf2\xfc" // "ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð·ÑÑ‚ÑŒ"
+#define sO_No "\xcd\xe5\xf2" // "Ðет"
+#define sO_LowerHatch_23 "\xcd\xe8\xe6\xed\xe8\xe9 \xeb\xfe\xea_23" // "Ðижний люк_23"
+#define sO_LowerPipe "\xcd\xe8\xe6\xed\xff\xff \xf2\xf0\xf3\xe1\xe0" // "ÐижнÑÑ Ñ‚Ñ€ÑƒÐ±Ð°"
+#define sO_LowerPipe_21 "\xcd\xe8\xe6\xed\xff\xff \xf2\xf0\xf3\xe1\xe0_21" // "ÐижнÑÑ Ñ‚Ñ€ÑƒÐ±Ð°_21"
+#define sO_WantsNothing "\xcd\xe8\xf7\xe5\xe3\xee \xed\xe5 \xf5\xee\xf7\xe5\xf2" // "Ðичего не хочет"
+#define sO_Leg "\xcd\xee\xe3\xe0" // "Ðога"
+#define sO_FriesPit "\xcd\xee\xf0\xea\xe0 \xea\xee\xe7\xff\xe2\xea\xe8" // "Ðорка козÑвки"
+#define sO_Sock_26 "\xcd\xee\xf1\xee\xea_26" // "ÐоÑок_26"
+#define sO_ClockAxis "\xce\xf1\xfc \xf7\xe0\xf1\xee\xe2" // "ОÑÑŒ чаÑов"
+#define sO_Opened "\xce\xf2\xea\xf0\xfb\xf2" // "Открыт"
+#define sO_OpenedWithBoot "\xce\xf2\xea\xf0\xfb\xf2\xe0 \xf1 \xe1\xee\xf2\xe8\xed\xea\xee\xec" // "Открыта Ñ Ð±Ð¾Ñ‚Ð¸Ð½ÐºÐ¾Ð¼"
+#define sO_OpenedShe "\xce\xf2\xea\xf0\xfb\xf2\xe0" // "Открыта"
+#define sO_WeirdWacko "\xce\xf2\xec\xee\xf0\xee\xe6\xe5\xed\xed\xfb\xe9" // "Отмороженный"
+#define sO_NotPresent "\xce\xf2\xf1\xf3\xf2\xf1\xf2\xe2\xf3\xe5\xf2" // "ОтÑутÑтвует"
+#define sO_Error "\xce\xf8\xe8\xe1\xea\xe0" // "Ошибка"
+#define sO_Passive "\xcf\xe0\xf1\xf1\xe8\xe2\xed\xe0" // "ПаÑÑивна"
+#define sO_First "\xcf\xe5\xf0\xe2\xfb\xe9" // "Первый"
+#define sO_UpsideDown "\xcf\xe5\xf0\xe5\xe2\xe5\xf0\xed\xf3\xf2\xe0" // "Перевернута"
+#define sO_Overfull "\xcf\xe5\xf0\xe5\xef\xee\xeb\xed\xe5\xed" // "Переполнен"
+#define sO_Fireman "\xcf\xee\xe6\xe0\xf0\xed\xe8\xea" // "Пожарник"
+#define sO_ShowingHeel "\xcf\xee\xea\xe0\xe7\xfb\xe2\xe0\xe5\xf2 \xef\xff\xf2\xea\xf3" // "Показывает пÑтку"
+#define sO_FullPipe "\xcf\xee\xeb\xed\xe0\xff \xd2\xf0\xf3\xe1\xe0" // "ÐŸÐ¾Ð»Ð½Ð°Ñ Ð¢Ñ€ÑƒÐ±Ð°"
+#define sO_RightStairs_9 "\xcf\xf0\xe0\xe2\xe0\xff \xeb\xe5\xf1\xf2\xed\xe8\xf6\xe0_9" // "ÐŸÑ€Ð°Ð²Ð°Ñ Ð»ÐµÑтница_9"
+#define sO_RightPipe_17 "\xcf\xf0\xe0\xe2\xe0\xff \xf2\xf0\xf3\xe1\xe0_17" // "ÐŸÑ€Ð°Ð²Ð°Ñ Ñ‚Ñ€ÑƒÐ±Ð°_17"
+#define sO_Available "\xcf\xf0\xe8\xf1\xf3\xf2\xf1\xf2\xe2\xf3\xe5\xf2" // "ПриÑутÑтвует"
+#define sO_GulpedEgg "\xcf\xf0\xee\xe3\xeb\xee\xf7\xe5\xed\xed\xee\xe5 \xff\xe9\xf6\xee" // "Проглоченное Ñйцо"
+#define sO_GulpedEggs "\xcf\xf0\xee\xe3\xeb\xee\xf7\xe5\xed\xed\xfb\xe5 \xff\xe9\xf6\xe0" // "Проглоченные Ñйца"
+#define sO_BellyInflater "\xcf\xf3\xe7\xee\xe4\xf3\xe2" // "Пузодув"
+#define sO_Empty "\xcf\xf3\xf1\xf2" // "ПуÑÑ‚"
+#define sO_EmptyShe "\xcf\xf3\xf1\xf2\xe0\xff" // "ПуÑтаÑ"
+#define sO_WayToPipe "\xcf\xf3\xf2\xfc \xea \xf2\xf0\xf3\xe1\xe5" // "Путь к трубе"
+#define sO_Drinking "\xcf\xfc\xe5\xf2" // "Пьет"
+#define sO_BrokenInPieces "\xd0\xe0\xe7\xe1\xe8\xf2\xe0" // "Разбита"
+#define sO_Unblocked "\xd0\xe0\xe7\xe1\xeb\xee\xea\xe8\xf0\xee\xe2\xe0\xed" // "Разблокирован"
+#define sO_Unfolded "\xd0\xe0\xe7\xe2\xe5\xf0\xed\xf3\xf2" // "Развернут"
+#define sO_Jawcrucnher "\xd0\xee\xf2\xee\xf5\xf0\xf3\xf1" // "РотохруÑ"
+#define sO_UsherHand "\xd0\xf3\xea\xe0 \xc1\xe8\xeb\xe5\xf2\xe5\xf0\xf8\xe8" // "Рука Билетерши"
+#define sO_LeverHandle_23 "\xd0\xf3\xea\xee\xff\xf2\xea\xe0 \xf0\xfb\xf7\xe0\xe3\xe0_23" // "РукоÑтка рычага_23"
+#define sO_ClockHandle "\xd0\xf3\xf7\xea\xe0 \xee\xf2 \xf7\xe0\xf1\xee\xe2" // "Ручка от чаÑов"
+#define sO_Lever_23 "\xd0\xfb\xf7\xe0\xe3_23" // "Рычаг_23"
+#define sO_WithDudeOnLeft "\xd1 \xc4\xff\xe4\xe5\xe9 \xf1\xeb\xe5\xe2\xe0" // "С ДÑдей Ñлева"
+#define sO_WithDudeOnRight "\xd1 \xc4\xff\xe4\xe5\xe9 \xf1\xef\xf0\xe0\xe2\xe0" // "С ДÑдей Ñправа"
+#define sO_WithBoot "\xd1 \xe1\xe0\xf8\xec\xe0\xea\xee\xec" // "С башмаком"
+#define sO_WithBig "\xd1 \xe1\xee\xeb\xfc\xf8\xe8\xec" // "С большим"
+#define sO_WithPlunger "\xd1 \xe2\xe0\xed\xf2\xf3\xe7\xee\xec" // "С вантузом"
+#define sO_WithJug "\xd1 \xe3\xee\xf0\xf8\xea\xee\xec" // "С горшком"
+#define sO_WithGum "\xd1 \xe6\xe2\xe0\xf7\xea\xee\xe9" // "С жвачкой"
+#define sO_WithShovel "\xd1 \xeb\xee\xef\xe0\xf2\xee\xe9" // "С лопатой"
+#define sO_WithTiny "\xd1 \xec\xe0\xeb\xfb\xec" // "С малым"
+#define sO_WithHammer "\xd1 \xec\xee\xeb\xee\xf2\xea\xee\xec" // "С молотком"
+#define sO_WithCoin "\xd1 \xec\xee\xed\xe5\xf2\xee\xe9" // "С монетой"
+#define sO_WithSock "\xd1 \xed\xee\xf1\xea\xee\xec" // "С ноÑком"
+#define sO_WithCork "\xd1 \xef\xf0\xee\xe1\xea\xee\xe9" // "С пробкой"
+#define sO_WithSteering "\xd1 \xf0\xf3\xeb\xe5\xec" // "С рулем"
+#define sO_WithHandle "\xd1 \xf0\xf3\xf7\xea\xee\xe9" // "С ручкой"
+#define sO_WithApple "\xd1 \xff\xe1\xeb\xee\xea\xee\xec" // "С Ñблоком"
+#define sO_WithDrawer "\xd1 \xff\xf9\xe8\xea\xee\xec" // "С Ñщиком"
+#define sO_Sugar "\xd1\xe0\xf5\xe0\xf0\xee\xea" // "Сахарок"
+#define sO_Convoluted "\xd1\xe2\xe5\xf0\xed\xf3\xf2" // "Свернут"
+#define sO_IsFree "\xd1\xe2\xee\xe1\xee\xe4\xed\xe0" // "Свободна"
+#define sO_Sitting "\xd1\xe8\xe4\xe8\xf2" // "Сидит"
+#define sO_Laughing "\xd1\xec\xe5\xe5\xf2\xf1\xff" // "СмеетÑÑ"
+#define sO_WithEveryone "\xd1\xee \xe2\xf1\xe5\xec\xe8" // "Со вÑеми"
+#define sO_WithMop "\xd1\xee \xf8\xe2\xe0\xe1\xf0\xee\xe9" // "Со шваброй"
+#define sO_WithHose "\xd1\xee \xf8\xeb\xe0\xed\xe3\xee\xec" // "Со шлангом"
+#define sO_WithBrush "\xd1\xee \xf9\xe5\xf2\xea\xee\xe9" // "Со щеткой"
+#define sO_Sleeping "\xd1\xef\xe8\xf2" // "Спит"
+#define sO_OnRight "\xd1\xef\xf0\xe0\xe2\xe0" // "Справа"
+#define sO_StandsInBoots "\xd1\xf2\xee\xe8\xf2 \xe2 \xe1\xee\xf2\xe8\xed\xea\xe0\xf5" // "Стоит в ботинках"
+#define sO_StandsInCorner "\xd1\xf2\xee\xe8\xf2 \xe2 \xf3\xe3\xeb\xf3" // "Стоит в углу"
+#define sO_Guardian "\xd1\xf2\xee\xf0\xee\xe6" // "Сторож"
+#define sO_Guard_1 "\xd1\xf2\xf0\xe0\xe6 1" // "Страж 1"
+#define sO_Gurad_2 "\xd1\xf2\xf0\xe0\xe6 2" // "Страж 2"
+#define sO_Guard_3 "\xd1\xf2\xf0\xe0\xe6 3" // "Страж 3"
+#define sO_Stool_34 "\xd2\xe0\xe1\xf3\xf0\xe5\xf2_34" // "Табурет_34"
+#define sO_Pipe_9 "\xd2\xf0\xf3\xe1\xe0_9" // "Труба_9"
+#define sO_Pedestal_16 "\xd2\xf3\xec\xe1\xe0_16" // "Тумба_16"
+#define sO_Pedestal_17 "\xd2\xf3\xec\xe1\xe0_17" // "Тумба_17"
+#define sO_Pedestal_33 "\xd2\xf3\xec\xe1\xe0_33" // "Тумба_33"
+#define sO_NearDudesStairs "\xd3 \xc4\xff\xe4\xe8 \xed\xe0 \xeb\xe5\xf1\xf2\xed\xe8\xf6\xe5" // "У ДÑди на леÑтнице"
+#define sO_NearDude "\xd3 \xc4\xff\xe4\xe8" // "У ДÑди"
+#define sO_NearPipeWithStool "\xd3 \xf2\xf0\xf3\xe1\xfb \xf1 \xf2\xe0\xe1\xf3\xf0\xe5\xf2\xea\xee\xe9" // "У трубы Ñ Ñ‚Ð°Ð±ÑƒÑ€ÐµÑ‚ÐºÐ¾Ð¹"
+#define sO_NearPipe "\xd3 \xf2\xf0\xf3\xe1\xfb" // "У трубы"
+#define sO_Janitors "\xd3\xe1\xee\xf0\xf9\xe8\xea\xe8" // "Уборщики"
+#define sO_Janitress "\xd3\xe1\xee\xf0\xf9\xe8\xf6\xe0" // "Уборщица"
+#define sO_Gone "\xd3\xe5\xf5\xe0\xeb\xe0" // "Уехала"
+#define sO_FallenOnce "\xd3\xef\xe0\xeb \xf0\xe0\xe7" // "Упал раз"
+#define sO_FallenBrush "\xd3\xef\xe0\xeb\xe0 \xf9\xe5\xf2\xea\xe0" // "Упала щетка"
+#define sO_NotBroken "\xd6\xe5\xeb\xe0" // "Цела"
+#define sO_ScratchingBelly "\xd7\xe5\xf8\xe5\xf2 \xef\xf3\xe7\xee" // "Чешет пузо"
+#define sO_Level0 "\xdd\xf2\xe0\xe6 0" // "Этаж 0"
+#define sO_Level1 "\xdd\xf2\xe0\xe6 1" // "Этаж 1"
+#define sO_Level2 "\xdd\xf2\xe0\xe6 2" // "Этаж 2"
+#define sO_Level3 "\xdd\xf2\xe0\xe6 3" // "Этаж 3"
+#define sO_Level4 "\xdd\xf2\xe0\xe6 4" // "Этаж 4"
+#define sO_Level5 "\xdd\xf2\xe0\xe6 5" // "Этаж 5"
+#define sO_Level6 "\xdd\xf2\xe0\xe6 6" // "Этаж 6"
+#define sO_Level7 "\xdd\xf2\xe0\xe6 7" // "Этаж 7"
+#define sO_Level8 "\xdd\xf2\xe0\xe6 8" // "Этаж 8"
+#define sO_Level9 "\xdd\xf2\xe0\xe6 9" // "Этаж 9"
+#define sO_EggGulperGaveCoin "\xdf\xe9\xf6\xe5\xe3\xeb\xee\xf2 \xee\xf2\xe4\xe0\xeb \xec\xee\xed\xe5\xf2\xf3" // "Яйцеглот отдал монету"
+#define sO_EggGulper "\xdf\xe9\xf6\xe5\xe3\xeb\xee\xf2" // "Яйцеглот"
+#define sO_EggCracker "\xdf\xe9\xf6\xe5\xea\xee\xeb" // "Яйцекол"
+#define sO_NotCarryingEgg "\xdf\xe9\xf6\xee \xed\xe5 \xed\xe5\xf1\xe5\xf2" // "Яйцо не неÑет"
+#define sO_Egg1 "\xdf\xe9\xf6\xee\x31" // "Яйцо1"
+#define sO_Egg2 "\xdf\xe9\xf6\xee\x32" // "Яйцо2"
+#define sO_Egg3 "\xdf\xe9\xf6\xee\x33" // "Яйцо3"
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_OBJECTNAMES_H */
diff --git a/engines/fullpipe/objects.h b/engines/fullpipe/objects.h
new file mode 100644
index 0000000000..a12851e63b
--- /dev/null
+++ b/engines/fullpipe/objects.h
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_OBJECTS_H
+#define FULLPIPE_OBJECTS_H
+
+#include "fullpipe/utils.h"
+
+namespace Fullpipe {
+
+class MessageQueue;
+class SceneTagList;
+
+class GameProject : public CObject {
+ public:
+ int _field_4;
+ char *_headerFilename;
+ SceneTagList *_sceneTagList;
+ int _field_10;
+
+ public:
+ GameProject();
+ ~GameProject();
+ virtual bool load(MfcArchive &file);
+};
+
+struct PicAniInfo {
+ int32 type;
+ int16 objectId;
+ int16 field_6;
+ int32 field_8;
+ int16 sceneId;
+ int16 field_E;
+ int32 ox;
+ int32 oy;
+ int32 priority;
+ int16 staticsId;
+ int16 movementId;
+ int16 dynamicPhaseIndex;
+ int16 flags;
+ int32 field_24;
+ int32 someDynamicPhaseIndex;
+
+ bool load(MfcArchive &file);
+};
+
+union VarValue {
+ float floatValue;
+ int32 intValue;
+ char *stringValue;
+};
+
+class GameVar : public CObject {
+ public:
+ GameVar *_nextVarObj;
+ GameVar *_prevVarObj;
+ GameVar *_parentVarObj;
+ GameVar *_subVars;
+ GameVar *_field_14;
+ char *_varName;
+ VarValue _value;
+ int _varType;
+
+ public:
+ GameVar();
+ virtual bool load(MfcArchive &file);
+ GameVar *getSubVarByName(const char *name);
+ bool setSubVarAsInt(const char *name, int value);
+ int getSubVarAsInt(const char *name);
+ GameVar *addSubVarAsInt(const char *name, int value);
+ bool addSubVar(GameVar *subvar);
+ int getSubVarsCount();
+ GameVar *getSubVarByIndex(int idx);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_OBJECTS_H */
diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp
new file mode 100644
index 0000000000..3831831866
--- /dev/null
+++ b/engines/fullpipe/scene.cpp
@@ -0,0 +1,691 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/ngiarchive.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/gameloader.h"
+
+#include "fullpipe/constants.h"
+
+#include "common/algorithm.h"
+
+namespace Fullpipe {
+
+Scene *FullpipeEngine::accessScene(int sceneId) {
+ SceneTag *t = 0;
+
+ for (SceneTagList::iterator s = _gameProject->_sceneTagList->begin(); s != _gameProject->_sceneTagList->end(); ++s) {
+ if (s->_sceneId == sceneId) {
+ t = &(*s);
+ break;
+ }
+ }
+
+ if (!t)
+ return 0;
+
+ if (!t->_scene) {
+ t->loadScene();
+ }
+
+ return t->_scene;
+}
+
+bool SceneTagList::load(MfcArchive &file) {
+ debug(5, "SceneTagList::load()");
+
+ int numEntries = file.readUint16LE();
+
+ for (int i = 0; i < numEntries; i++) {
+ SceneTag *t = new SceneTag();
+ t->load(file);
+ push_back(*t);
+ }
+
+ return true;
+}
+
+SceneTag::SceneTag() {
+ _field_4 = 0;
+ _scene = 0;
+ _tag = 0;
+ _sceneId = 0;
+}
+
+bool SceneTag::load(MfcArchive &file) {
+ debug(5, "SceneTag::load()");
+
+ _field_4 = 0;
+ _scene = 0;
+
+ _sceneId = file.readUint16LE();
+
+ _tag = file.readPascalString();
+
+ debug(6, "sceneId: %d tag: %s", _sceneId, _tag);
+
+ return true;
+}
+
+SceneTag::~SceneTag() {
+ free(_tag);
+}
+
+void SceneTag::loadScene() {
+ char *archname = genFileName(0, _sceneId, "nl");
+
+ Common::Archive *arch = makeNGIArchive(archname);
+
+ char *fname = genFileName(0, _sceneId, "sc");
+
+ Common::SeekableReadStream *file = arch->createReadStreamForMember(fname);
+
+ _scene = new Scene();
+
+ MfcArchive archive(file);
+
+ _scene->load(archive);
+
+ if (_scene->_shadows)
+ _scene->_shadows->init();
+
+ delete file;
+
+ g_fullpipe->_currArchive = 0;
+
+ free(fname);
+ free(archname);
+}
+
+Scene::Scene() {
+ _sceneId = 0;
+ _field_BC = 0;
+ _shadows = 0;
+ _soundList = 0;
+ _libHandle = 0;
+ _sceneName = 0;
+}
+
+bool Scene::load(MfcArchive &file) {
+ debug(5, "Scene::load()");
+
+ Background::load(file);
+
+ _sceneId = file.readUint16LE();
+
+ _sceneName = file.readPascalString();
+ debug(0, "scene: <%s> %d", transCyrillic((byte *)_sceneName), _sceneId);
+
+ int count = file.readUint16LE();
+ debug(7, "scene.ani: %d", count);
+
+ for (int i = 0; i < count; i++) {
+ int aniNum = file.readUint16LE();
+ char *aniname = genFileName(0, aniNum, "ani");
+
+ Common::SeekableReadStream *f = g_fullpipe->_currArchive->createReadStreamForMember(aniname);
+
+ StaticANIObject *ani = new StaticANIObject();
+
+ MfcArchive archive(f);
+
+ ani->load(archive);
+ ani->_sceneId = _sceneId;
+
+ _staticANIObjectList1.push_back(ani);
+
+ delete f;
+ free(aniname);
+ }
+
+ count = file.readUint16LE();
+ debug(7, "scene.mq: %d", count);
+
+ for (int i = 0; i < count; i++) {
+ int qNum = file.readUint16LE();
+ char *qname = genFileName(0, qNum, "qu");
+
+ Common::SeekableReadStream *f = g_fullpipe->_currArchive->createReadStreamForMember(qname);
+ MfcArchive archive(f);
+
+ archive.readUint16LE(); // Skip 2 bytes
+
+ MessageQueue *mq = new MessageQueue();
+
+ mq->load(archive);
+
+ _messageQueueList.push_back(mq);
+
+ delete f;
+ free(qname);
+ }
+
+ count = file.readUint16LE();
+ debug(7, "scene.fa: %d", count);
+
+ for (int i = 0; i < count; i++) {
+ // There are no .FA files
+ assert(0);
+ }
+
+ _libHandle = g_fullpipe->_currArchive;
+
+ if (_picObjList.size() > 0 && _bgname && strlen(_bgname) > 1) {
+ char fname[260];
+
+ strcpy(fname, _bgname);
+ strcpy(strrchr(fname, '.') + 1, "col");
+
+ MemoryObject *col = new MemoryObject();
+ col->loadFile(fname);
+
+ _palette = col;
+ }
+
+ char *shdname = genFileName(0, _sceneId, "shd");
+
+ Shadows *shd = new Shadows();
+
+ if (shd->loadFile(shdname))
+ _shadows = shd;
+
+ free(shdname);
+
+ char *slsname = genFileName(0, _sceneId, "sls");
+
+ if (g_fullpipe->_soundEnabled) {
+ _soundList = new SoundList();
+
+ if (g_fullpipe->_flgSoundList) {
+ char *nlname = genFileName(17, _sceneId, "nl");
+
+ _soundList->loadFile(slsname, nlname);
+
+ free(nlname);
+ } else {
+ _soundList->loadFile(slsname, 0);
+ }
+ }
+
+ free(slsname);
+
+ initStaticANIObjects();
+
+ if (file.size() - file.pos() > 0)
+ error("Scene::load (%d bytes left)", file.size() - file.pos());
+
+ return true;
+}
+
+void Scene::initStaticANIObjects() {
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++)
+ ((StaticANIObject *)_staticANIObjectList1[i])->initMovements();
+}
+
+void Scene::init() {
+ _x = 0;
+ _y = 0;
+
+ g_fullpipe->_sceneRect.moveTo(0, 0);
+
+ for (uint i = 0; i < _picObjList.size(); i++)
+ ((PictureObject *)_picObjList[i])->clearFlags();
+
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++)
+ ((StaticANIObject *)_staticANIObjectList1[i])->clearFlags();
+
+ if (_staticANIObjectList2.size() != _staticANIObjectList1.size()) {
+ _staticANIObjectList2.clear();
+
+ for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s)
+ _staticANIObjectList2.push_back(*s);
+ }
+}
+
+StaticANIObject *Scene::getAniMan() {
+ StaticANIObject *aniMan = getStaticANIObject1ById(ANI_MAN, -1);
+
+ deleteStaticANIObject(aniMan);
+
+ return aniMan;
+}
+
+StaticANIObject *Scene::getStaticANIObject1ById(int obj, int a3) {
+ for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) {
+ StaticANIObject *o = (StaticANIObject *)*s;
+ if (o->_id == obj && (a3 == -1 || o->_okeyCode == a3))
+ return o;
+ }
+
+ return 0;
+}
+
+StaticANIObject *Scene::getStaticANIObject1ByName(char *name, int a3) {
+ for (uint n = 0; n < _staticANIObjectList1.size(); n++) {
+ StaticANIObject *o = (StaticANIObject *)_staticANIObjectList1[n];
+ if (!strcmp(o->_objectName, name) && (a3 == -1 || o->_okeyCode == a3))
+ return o;
+ }
+
+ return 0;
+}
+
+void Scene::deleteStaticANIObject(StaticANIObject *obj) {
+ for (uint n = 0; n < _staticANIObjectList1.size(); n++)
+ if ((StaticANIObject *)_staticANIObjectList1[n] == obj) {
+ _staticANIObjectList1.remove_at(n);
+ break;
+ }
+
+ for (uint n = 0; n < _staticANIObjectList2.size(); n++)
+ if ((StaticANIObject *)_staticANIObjectList2[n] == obj) {
+ _staticANIObjectList2.remove_at(n);
+ break;
+ }
+}
+
+void Scene::addStaticANIObject(StaticANIObject *obj, bool addList2) {
+ if (obj->_okeyCode)
+ obj->renumPictures(&_staticANIObjectList1);
+
+ _staticANIObjectList1.push_back(obj);
+
+ if (addList2) {
+ if (!obj->_okeyCode)
+ obj->clearFlags();
+
+ _staticANIObjectList2.push_back(obj);
+ }
+}
+
+void Scene::setPictureObjectsFlag4() {
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ ((PictureObject *)_picObjList[i])->_flags |= 4;
+ }
+}
+
+PictureObject *Scene::getPictureObjectById(int objId, int flags) {
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ if (((PictureObject *)_picObjList[i])->_id == objId && ((PictureObject *)_picObjList[i])->_okeyCode == flags)
+ return (PictureObject *)_picObjList[i];
+ }
+
+ return 0;
+}
+
+PictureObject *Scene::getPictureObjectByName(const char *objName, int flags) {
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ if (!strcmp(((PictureObject *)_picObjList[i])->_objectName, objName) && (((PictureObject *)_picObjList[i])->_okeyCode == flags || flags == -1))
+ return (PictureObject *)_picObjList[i];
+ }
+
+ return 0;
+}
+
+void Scene::deletePictureObject(PictureObject *obj) {
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ if (((PictureObject *)_picObjList[i]) == obj) {
+ _picObjList.remove_at(i);
+ delete obj;
+
+ return;
+ }
+ }
+}
+
+MessageQueue *Scene::getMessageQueueById(int messageId) {
+ for (uint i = 0; i < _messageQueueList.size(); i++)
+ if (((MessageQueue *)_messageQueueList[i])->_dataId == messageId)
+ return (MessageQueue *)_messageQueueList[i];
+
+ return 0;
+}
+
+MessageQueue *Scene::getMessageQueueByName(char *name) {
+ for (uint i = 0; i < _messageQueueList.size(); i++)
+ if (!strcmp(((MessageQueue *)_messageQueueList[i])->_queueName, name))
+ return (MessageQueue *)_messageQueueList[i];
+
+ return 0;
+}
+
+void Scene::preloadMovements(GameVar *var) {
+ GameVar *preload = var->getSubVarByName("PRELOAD");
+ if (!preload)
+ return;
+
+ for (GameVar *i = preload->_subVars; i; i = i->_nextVarObj) {
+ StaticANIObject *ani = getStaticANIObject1ByName(i->_varName, -1);
+
+ if (ani) {
+ GameVar *subVars = i->_subVars;
+
+ if (subVars) {
+ for (;subVars; subVars = subVars->_nextVarObj) {
+ Movement *mov = ani->getMovementByName(subVars->_varName);
+
+ if (mov)
+ mov->loadPixelData();
+ }
+ } else {
+ ani->loadMovementsPixelData();
+ }
+ }
+ }
+}
+
+void Scene::initObjectCursors(const char *varname) {
+ GameVar *cursorsVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(varname)->getSubVarByName("CURSORS");
+
+ if (!cursorsVar || !cursorsVar->_subVars)
+ return;
+
+ int maxId = 0;
+ int minId = 0xffff;
+
+ for (GameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
+ GameObject *obj = getPictureObjectByName(sub->_varName, -1);
+
+ if (obj || (obj = getStaticANIObject1ByName(sub->_varName, -1)) != 0) {
+ if (obj->_id < minId)
+ minId = obj->_id;
+ if (obj->_id > maxId)
+ maxId = obj->_id;
+ }
+ }
+
+ g_fullpipe->_minCursorId = minId;
+ g_fullpipe->_maxCursorId = maxId;
+
+ g_fullpipe->_objectIdCursors.resize(maxId - minId + 1);
+
+ for (GameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
+ GameObject *obj = getPictureObjectByName(sub->_varName, -1);
+
+ if (!obj)
+ obj = getStaticANIObject1ByName(sub->_varName, -1);
+
+ PictureObject *pic = getGameLoaderInventory()->getScene()->getPictureObjectByName(sub->_value.stringValue, -1);
+
+ if (obj && pic)
+ g_fullpipe->_objectIdCursors[obj->_id - minId] = pic->_id;
+ }
+}
+
+bool Scene::compareObjPriority(const void *p1, const void *p2) {
+ if (((const StaticANIObject *)p1)->_priority > ((const StaticANIObject *)p2)->_priority)
+ return true;
+
+ return false;
+}
+
+void Scene::objectList_sortByPriority(PtrList &list) {
+ Common::sort(list.begin(), list.end(), Scene::compareObjPriority);
+}
+
+void Scene::draw() {
+ debug(0, ">>>>> Scene::draw()");
+ updateScrolling();
+
+ drawContent(60000, 0, true);
+
+ objectList_sortByPriority(_staticANIObjectList2);
+
+ for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
+ ((StaticANIObject *)*s)->draw2();
+ }
+
+ int priority = -1;
+ for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
+ drawContent(((StaticANIObject *)*s)->_priority, priority, false);
+ ((StaticANIObject *)*s)->draw();
+
+ priority = ((StaticANIObject *)*s)->_priority;
+ }
+
+ drawContent(-1, priority, false);
+}
+
+void Scene::updateScrolling() {
+ debug(0, "STUB Scene::updateScrolling()");
+}
+
+void Scene::updateScrolling2() {
+ warning("STUB Scene::updateScrolling2()");
+}
+
+StaticANIObject *Scene::getStaticANIObjectAtPos(int x, int y) {
+ StaticANIObject *res = 0;
+
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++) {
+ StaticANIObject *p = (StaticANIObject *)_staticANIObjectList1[i];
+ int pixel;
+
+ if ((p->_field_8 & 0x100) && (p->_flags & 4) &&
+ p->getPixelAtPos(x, y, &pixel) &&
+ (!res || res->_priority >= p->_priority))
+ res = p;
+ }
+
+ return res;
+}
+
+PictureObject *Scene::getPictureObjectAtPos(int x, int y) {
+ PictureObject *res = 0;
+
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ PictureObject *p = (PictureObject *)_picObjList[i];
+ if ((p->_field_8 & 0x100) && (p->_flags & 4) &&
+ p->isPixelHitAtPos(x, y) &&
+ (!res || res->_priority >= p->_priority))
+ res = p;
+ }
+
+ return res;
+}
+
+int Scene::getPictureObjectIdAtPos(int x, int y) {
+ PictureObject *resp = 0;
+ int res = 0;
+
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ PictureObject *p = (PictureObject *)_picObjList[i];
+ if ((p->_field_8 & 0x100) && (p->_flags & 4) &&
+ p->isPixelHitAtPos(x, y) &&
+ (!res || resp->_priority >= p->_priority)) {
+ resp = p;
+ res = p->_id;
+ }
+ }
+
+ return res;
+}
+
+void Scene::update(int counterdiff) {
+ debug(0, "Scene::update(%d)", counterdiff);
+
+ for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s)
+ ((StaticANIObject *)*s)->update(counterdiff);
+}
+
+void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
+ if (!_picObjList.size() && !_bigPictureArray1Count)
+ return;
+
+ if (_palette) {
+ g_fullpipe->_globalPalette = _palette->_data;
+ }
+
+ debug(8, "Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
+
+ if (_picObjList.size() > 2) { // We need to z-sort them
+ objectList_sortByPriority(_picObjList);
+ }
+
+ if (minPri == -1 && _picObjList.size())
+ minPri = ((PictureObject *)_picObjList.back())->_priority - 1;
+
+ if (maxPri == -1)
+ maxPri = 60000;
+
+ debug(8, "-> Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
+
+ Common::Point point;
+
+ debug(8, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size());
+ if (drawBg && _bigPictureArray1Count && _picObjList.size()) {
+
+ _bigPictureArray[0][0]->getDimensions(&point);
+
+ int width = point.x;
+ int height = point.y;
+
+ debug(8, "w: %d h:%d", width, height);
+
+ ((PictureObject *)_picObjList[0])->getDimensions(&point);
+
+ debug(8, "w2: %d h2:%d", point.x, point.y);
+
+ int bgStX = g_fullpipe->_sceneRect.left % point.x;
+
+ if (bgStX < 0)
+ bgStX += point.x;
+
+ int bgNumX = bgStX / width;
+ int bgOffsetX = bgStX % width;
+
+ int bgStY = g_fullpipe->_sceneRect.top % point.y;
+
+ if (bgStY < 0)
+ bgStY += point.y;
+
+ int bgNumY = bgStY / height;
+ int bgOffsetY = bgStY % height;
+
+ int bgPosX = g_fullpipe->_sceneRect.left - bgOffsetX;
+
+ if (bgPosX < g_fullpipe->_sceneRect.right - 1) {
+ while (1) {
+ int v25 = bgNumY;
+ for (int y = g_fullpipe->_sceneRect.top - bgOffsetY; y < g_fullpipe->_sceneRect.bottom - 1;) {
+ BigPicture *v27 = _bigPictureArray[bgNumX][v25];
+ v27->draw(bgPosX, y, 0, 0);
+ y += v27->getDimensions(&point)->y;
+ v25++;
+
+ if (v25 >= _bigPictureArray2Count) {
+ if (!(((PictureObject *)_picObjList[0])->_flags & 0x20))
+ break;
+ v25 = 0;
+ }
+ }
+ _bigPictureArray[bgNumX][0]->getDimensions(&point);
+ int v32 = point.x + bgPosX;
+ bgPosX += point.x;
+ bgNumX++;
+
+ if (bgNumX >= _bigPictureArray1Count) {
+ if (!(((PictureObject *)_picObjList[0])->_flags & 0x2))
+ break;
+ bgNumX = 0;
+ }
+ if (v32 >= g_fullpipe->_sceneRect.right - 1)
+ break;
+ }
+ }
+ }
+
+
+ for (uint i = 1; i < _picObjList.size(); i++) {
+ PictureObject *obj = (PictureObject *)_picObjList[i];
+
+ debug(8, "pri: %d", obj->_priority);
+ if (obj->_priority < minPri || obj->_priority >= maxPri)
+ continue;
+
+ int objX = obj->_ox;
+ int objY = obj->_oy;
+
+ debug(8, "obj: %d %d", objX, objY);
+
+ obj->getDimensions(&point);
+
+ int width = point.x;
+ int height = point.y;
+
+ if (obj->_flags & 8) {
+ while (objX > g_fullpipe->_sceneRect.right) {
+ objX -= width;
+ obj->setOXY(objX, objY);
+ }
+ for (int j = width + objX; width + objX < g_fullpipe->_sceneRect.left; j = width + objX) {
+ objX = j;
+ obj->setOXY(j, objY);
+ }
+ }
+
+ if (obj->_flags & 0x10) {
+ while (objY > g_fullpipe->_sceneRect.bottom) {
+ objY -= height;
+ obj->setOXY(objX, objY);
+ }
+ for (int j = objY + height; objY + height < g_fullpipe->_sceneRect.top; j = objY + height) {
+ objY = j;
+ obj->setOXY(objX, j);
+ }
+ }
+ if (obj->_flags & 4)
+ obj->draw();
+
+ if (obj->_flags & 2) {
+ if (objX > g_fullpipe->_sceneRect.left) {
+ obj->setOXY(objX - width, objY);
+ obj->draw();
+ obj->setOXY(objX, objY);
+ }
+ if (width + objX < g_fullpipe->_sceneRect.right) {
+ obj->setOXY(width + objX, objY);
+ obj->draw();
+ obj->setOXY(objX, objY);
+ }
+ }
+
+ if (obj->_flags & 0x20) {
+ if (objY > g_fullpipe->_sceneRect.top) {
+ obj->setOXY(objX, objY - height);
+ obj->draw();
+ obj->setOXY(objX, objY);
+ }
+ if (height + objY < g_fullpipe->_sceneRect.bottom) {
+ obj->setOXY(objX, height + objY);
+ obj->draw();
+ obj->setOXY(objX, objY);
+ }
+ }
+ }
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scene.h b/engines/fullpipe/scene.h
new file mode 100644
index 0000000000..db0da5db31
--- /dev/null
+++ b/engines/fullpipe/scene.h
@@ -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.
+ *
+ */
+
+#ifndef FULLPIPE_SCENE_H
+#define FULLPIPE_SCENE_H
+
+#include "fullpipe/gfx.h"
+
+namespace Fullpipe {
+
+class MessageQueue;
+
+class Scene : public Background {
+ public:
+ PtrList _staticANIObjectList1;
+ PtrList _staticANIObjectList2;
+ PtrList _messageQueueList;
+ PtrList _faObjectList;
+ Shadows *_shadows;
+ SoundList *_soundList;
+ int16 _sceneId;
+ char *_sceneName;
+ int _field_BC;
+ NGIArchive *_libHandle;
+
+ public:
+ Scene();
+
+ virtual bool load(MfcArchive &file);
+
+ void initStaticANIObjects();
+ void init();
+ void draw();
+ void drawContent(int minPri, int maxPri, bool drawBG);
+ void updateScrolling();
+ void updateScrolling2();
+
+ void update(int counterdiff);
+
+ StaticANIObject *getAniMan();
+ StaticANIObject *getStaticANIObject1ById(int obj, int a3);
+ StaticANIObject *getStaticANIObject1ByName(char *name, int a3);
+ MessageQueue *getMessageQueueById(int messageId);
+ MessageQueue *getMessageQueueByName(char *name);
+
+ void deleteStaticANIObject(StaticANIObject *obj);
+ void addStaticANIObject(StaticANIObject *obj, bool addList2);
+
+ void setPictureObjectsFlag4();
+ PictureObject *getPictureObjectById(int objId, int flags);
+ PictureObject *getPictureObjectByName(const char *name, int keyCode);
+ void deletePictureObject(PictureObject *obj);
+ void preloadMovements(GameVar *var);
+
+ StaticANIObject *getStaticANIObjectAtPos(int x, int y);
+ PictureObject *getPictureObjectAtPos(int x, int y);
+ int getPictureObjectIdAtPos(int x, int y);
+
+ void initObjectCursors(const char *name);
+
+ private:
+ static bool compareObjPriority(const void *p1, const void *p2);
+ void objectList_sortByPriority(PtrList &list);
+};
+
+class SceneTag : public CObject {
+ public:
+ int _field_4;
+ char *_tag;
+ Scene *_scene;
+ int16 _sceneId;
+
+ public:
+ SceneTag();
+ ~SceneTag();
+
+ virtual bool load(MfcArchive &file);
+ void loadScene();
+};
+
+class SceneTagList : public Common::List<SceneTag>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_SCENE_H */
diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp
new file mode 100644
index 0000000000..a0f90af532
--- /dev/null
+++ b/engines/fullpipe/scenes.cpp
@@ -0,0 +1,712 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/utils.h"
+#include "fullpipe/objects.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/input.h"
+#include "fullpipe/behavior.h"
+
+#include "fullpipe/constants.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/interaction.h"
+
+namespace Fullpipe {
+
+Vars::Vars() {
+ sceneIntro_aniin1man = 0;
+ sceneIntro_needSleep = true;
+ sceneIntro_needGetup = false;
+ sceneIntro_skipIntro = true;
+ sceneIntro_playing = false;
+ sceneIntro_needBlackout = false;
+
+ swallowedEgg1 = 0;
+ swallowedEgg2 = 0;
+ swallowedEgg3 = 0;
+
+ scene01_picSc01Osk = 0;
+ scene01_picSc01Osk2 = 0;
+
+ scene02_guvTheDrawer = 0;
+ scene02_boxDelay = 0;
+ scene02_boxOpen = false;
+
+ scene03_eggeater = 0;
+ scene03_domino = 0;
+
+ scene04_bottle = 0;
+ scene04_hand = 0;
+ scene04_plank = 0;
+ scene04_clock = 0;
+ scene04_hand = 0;
+ scene04_spring = 0;
+ scene04_mamasha = 0;
+ scene04_boot = 0;
+ scene04_speaker = 0;
+
+ scene04_ladder = 0;
+ scene04_coinPut = false;
+ scene04_soundPlaying = false;
+ scene04_dynamicPhaseIndex = 0;
+
+ scene04_sceneClickX = 0;
+ scene04_sceneClickY = 0;
+
+ scene04_dudePosX = 0;
+ scene04_dudePosY = 0;
+
+ scene04_var01 = 0;
+ scene04_var02 = 0;
+ scene04_var04 = 0;
+ scene04_walkingKozyawka = 0;
+ scene04_var06 = 0;
+ scene04_var07 = 0;
+ scene04_var08 = 0;
+ scene04_var09 = 0;
+ scene04_var10 = 0;
+ scene04_var11 = 0;
+ scene04_var12 = 0;
+ scene04_var13 = 0;
+ scene04_var14 = 0;
+ scene04_var15 = 0;
+ scene04_speakerVariant = 0;
+ scene04_speakerPhase = 0;
+ scene04_var18 = 0;
+ scene04_var19 = 0;
+ scene04_var20 = 0;
+ scene04_var24 = 0;
+ scene04_var26 = 0;
+
+ selector = 0;
+}
+
+static int scenes[] = {
+ SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7, SC_8, SC_9, SC_10,
+ SC_11, SC_12, SC_13, SC_14, SC_15, SC_16, SC_17, SC_18, SC_19, SC_20,
+ SC_21, SC_22, SC_23, SC_24, SC_25, SC_26, SC_27, SC_28, SC_29, SC_30,
+ SC_31, SC_32, SC_33, SC_34, SC_35, SC_36, SC_37, SC_38, SC_DBGMENU
+};
+
+int FullpipeEngine::convertScene(int scene) {
+ if (!scene || scene >= SC_1)
+ return scene;
+
+ if (scene < 1 || scene > 39)
+ return SC_1;
+
+ return scenes[scene - 1];
+}
+
+bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
+ GameVar *sceneVar;
+ Common::Point sceneDim;
+
+ Scene *scene = accessScene(entrance->_sceneId);
+
+ if (!scene)
+ return 0;
+
+ ((PictureObject *)scene->_picObjList.front())->getDimensions(&sceneDim);
+ _sceneWidth = sceneDim.x;
+ _sceneHeight = sceneDim.y;
+
+ _sceneRect.top = 0;
+ _sceneRect.left = 0;
+ _sceneRect.right = 799;
+ _sceneRect.bottom = 599;
+
+ scene->_x = 0;
+ scene->_y = 0;
+
+ _aniMan->setOXY(0, 0);
+ _aniMan->clearFlags();
+ _aniMan->_callback1 = 0;
+ _aniMan->_callback2 = 0;
+ _aniMan->_shadowsOn = 1;
+
+ _scrollSpeed = 8;
+
+ _isSaveAllowed = true;
+ _updateFlag = true;
+ _flgCanOpenMap = true;
+
+ if (entrance->_sceneId == SC_DBGMENU) {
+ _inventoryScene = 0;
+ } else {
+ _gameLoader->loadScene(SC_INV);
+ getGameLoaderInventory()->rebuildItemRects();
+ _inventoryScene = getGameLoaderInventory()->getScene();
+ }
+ if (_soundEnabled) {
+ if (scene->_soundList) {
+ _currSoundListCount = 2;
+ _currSoundList1[0] = accessScene(SC_COMMON)->_soundList;
+ _currSoundList1[1] = scene->_soundList;
+
+ for (int i = 0; i < scene->_soundList->getCount(); i++) {
+ scene->_soundList->getSoundByIndex(i)->updateVolume();
+ }
+ } else {
+ _currSoundListCount = 1;
+ _currSoundList1[0] = accessScene(SC_COMMON)->_soundList;
+ }
+ }
+
+ getGameLoaderInteractionController()->sortInteractions(scene->_sceneId);
+ _currentScene = scene;
+ scene->addStaticANIObject(_aniMan, 1);
+ _scene2 = scene;
+ _aniMan->_movement = 0;
+ _aniMan->_statics = _aniMan->getStaticsById(ST_MAN_EMPTY);
+ _aniMan->setOXY(0, 0);
+
+ _aniMan2 = _aniMan;
+ MctlCompound *cmp = getSc2MctlCompoundBySceneId(entrance->_sceneId);
+ cmp->initMovGraph2();
+ cmp->addObject(_aniMan);
+ cmp->setEnabled();
+ getGameLoaderInteractionController()->enableFlag24();
+ setInputDisabled(0);
+
+ scene->setPictureObjectsFlag4();
+
+ for (PtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) {
+ StaticANIObject *o = (StaticANIObject *)*s;
+ o->setFlags(o->_flags & 0xFE7F);
+ }
+
+ PictureObject *p = accessScene(SC_INV)->getPictureObjectById(PIC_INV_MENU, 0);
+ p->setFlags(p->_flags & 0xFFFB);
+
+ removeMessageHandler(2, -1);
+ _updateScreenCallback = 0;
+
+ switch (entrance->_sceneId) {
+ case SC_INTRO1:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_INTRO1");
+ scene->preloadMovements(sceneVar);
+ sceneIntro_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_INTRO1");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandlerIntro, 2);
+ _updateCursorCallback = sceneIntro_updateCursor;
+ break;
+
+ case SC_1:
+ scene01_fixEntrance();
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_1");
+ scene->preloadMovements(sceneVar);
+ scene01_initScene(scene, entrance->_field_4);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_1");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler01, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_2:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_2");
+ scene->preloadMovements(sceneVar);
+ scene02_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_2");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler02, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_3:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_3");
+ scene->preloadMovements(sceneVar);
+ scene03_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_3");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler03, 2);
+ scene03_setEaterState();
+ _updateCursorCallback = scene03_updateCursor;
+ break;
+
+ case SC_4:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_4");
+ scene->preloadMovements(sceneVar);
+ scene04_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_4");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler04, 2, 2);
+ _updateCursorCallback = scene04_updateCursor;
+ break;
+
+#if 0
+ case SC_5:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_5");
+ scene->preloadMovements(sceneVar);
+ scene05_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_5");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler05, 2, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_6:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_6");
+ scene->preloadMovements(sceneVar);
+ scene06_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_6");
+ setSceneMusicParameters(sceneVar);
+ sub_415300();
+ insertMessageHandler(sceneHandler06, 2, 2);
+ _updateCursorCallback = scene06_updateCursor;
+ break;
+
+ case SC_7:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_7");
+ scene->preloadMovements(sceneVar);
+ scene07_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_7");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler07, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_8:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_8");
+ scene->preloadMovements(sceneVar);
+ scene08_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_8");
+ setSceneMusicParameters(sceneVar);
+ sub_416890();
+ addMessageHandler(sceneHandler08, 2);
+ _updateCursorCallback = scene08_updateCursor;
+ break;
+
+ case SC_9:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_9");
+ scene->preloadMovements(sceneVar);
+ scene09_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_9");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler09, 2, 2);
+ _updateCursorCallback = scene09_updateCursor;
+ break;
+
+ case SC_10:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_10");
+ scene->preloadMovements(sceneVar);
+ scene10_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_10");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler10, 2, 2);
+ _updateCursorCallback = scene10_updateCursor;
+ break;
+
+ case SC_11:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_11");
+ scene->preloadMovements(sceneVar);
+ scene11_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_11");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler11, 2, 2);
+ scene11_sub_41A980();
+ _updateCursorCallback = scene11_updateCursor;
+ break;
+
+ case SC_12:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_12");
+ scene->preloadMovements(sceneVar);
+ scene12_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_12");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler12, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_13:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_13");
+ scene->preloadMovements(sceneVar);
+ scene13_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_13");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler13, 2, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_14:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_14");
+ scene->preloadMovements(sceneVar);
+ scene14_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_14");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler14, 2, 2);
+ scene14_sub_41D2B0();
+ _updateCursorCallback = scene14_updateCursor;
+ break;
+
+ case SC_15:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_15");
+ scene->preloadMovements(sceneVar);
+ scene15_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_15");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler15, 2, 2);
+ _updateCursorCallback = scene15_updateCursor;
+ break;
+
+ case SC_16:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_16");
+ scene->preloadMovements(sceneVar);
+ scene16_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_16");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler16, 2);
+ _updateCursorCallback = scene16_updateCursor;
+ break;
+
+ case SC_17:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_17");
+ scene->preloadMovements(sceneVar);
+ scene17_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_17");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler17, 2);
+ scene17_sub_41F060();
+ _updateCursorCallback = scene17_updateCursor;
+ break;
+
+ case SC_18:
+ sub_40E1B0();
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_18");
+ scene->preloadMovements(sceneVar);
+ sub_4062D0();
+ if (dword_476C38)
+ scene18_initScene1(scene);
+ else
+ scene18_initScene2(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_18");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler18, 2, 2);
+ _updateCursorCallback = scene18_updateCursor;
+ break;
+
+ case SC_19:
+ if (!g_scene3) {
+ g_scene3 = accessScene(SC_18);
+ getGameLoader()->loadScene(SC_18);
+ scene18_initScene2(g_scene3);
+ sub_40C5F0();
+ scene19_sub_420B10(g_scene3, entrance->field_4);
+ dword_476C38 = 1;
+ }
+ sub_40C650();
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_19");
+ scene->preloadMovements(sceneVar);
+ sub_4062D0();
+ if (dword_476C38)
+ scene18_initScene1(scene);
+ else
+ scene19_initScene2();
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_19");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler19, 2);
+ scene19_sub_4211D0(scene);
+ _updateCursorCallback = scene19_updateCursor;
+ break;
+
+ case SC_20:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_20");
+ scene->preloadMovements(sceneVar);
+ scene20_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_20");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler20, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_21:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_21");
+ scene->preloadMovements(sceneVar);
+ scene21_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_21");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler21, 2, 2);
+ _updateCursorCallback = scene21_updateCursor;
+ break;
+
+ case SC_22:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_22");
+ scene->preloadMovements(sceneVar);
+ scene22_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_22");
+ setSceneMusicParameters(sceneVar);
+ scene22_sub_4228A0();
+ insertMessageHandler(sceneHandler22, 2, 2);
+ _updateCursorCallback = scene22_updateCursor;
+ break;
+
+ case SC_23:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_23");
+ scene->preloadMovements(sceneVar);
+ scene23_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_23");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler23, 2, 2);
+ scene23_sub_423B00();
+ _updateCursorCallback = scene23_updateCursor;
+ break;
+
+ case SC_24:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_24");
+ scene->preloadMovements(sceneVar);
+ scene24_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_24");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler24, 2);
+ scene24_sub_423DD0();
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_25:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_25");
+ scene->preloadMovements(sceneVar);
+ scene25_initScene(scene, entrance->field_4);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_25");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler25, 2);
+ scene25_sub_4253B0(scene, entrance->field_4);
+ _updateCursorCallback = scene25_updateCursor;
+ break;
+
+ case SC_26:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_26");
+ scene->preloadMovements(sceneVar);
+ scene26_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_26");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler26, 2, 2);
+ scene26_sub_426140(scene);
+ _updateCursorCallback = scene26_updateCursor;
+ break;
+
+ case SC_27:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_27");
+ scene->preloadMovements(sceneVar);
+ scene27_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_27");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler27, 2);
+ _updateCursorCallback = scene27_updateCursor;
+ break;
+
+ case SC_28:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_28");
+ scene->preloadMovements(sceneVar);
+ scene28_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_28");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler28, 2, 2);
+ _updateCursorCallback = scene28_updateCursor;
+ break;
+
+ case SC_29:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_29");
+ scene->preloadMovements(sceneVar);
+ scene29_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_29");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler29, 2);
+ _updateCursorCallback = scene29_updateCursor;
+ break;
+
+ case SC_30:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_30");
+ scene->preloadMovements(sceneVar);
+ scene30_initScene(scene, entrance->field_4);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_30");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler30, 2);
+ _updateCursorCallback = scene30_updateCursor;
+ break;
+
+ case SC_31:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_31");
+ scene->preloadMovements(sceneVar);
+ scene31_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_31");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler31, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_32:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_32");
+ scene->preloadMovements(sceneVar);
+ scene32_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_32");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler32, 2, 2);
+ scene32_sub_42C5C0();
+ _updateCursorCallback = scene32_updateCursor;
+ break;
+
+ case SC_33:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_33");
+ scene->preloadMovements(sceneVar);
+ scene33_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_33");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler33, 2, 2);
+ scene33_sub_42CEF0();
+ _updateCursorCallback = scene33_updateCursor;
+ break;
+
+ case SC_34:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_34");
+ scene->preloadMovements(sceneVar);
+ scene34_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_34");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler34, 2, 2);
+ scene34_sub_42DEE0();
+ _updateCursorCallback = scene34_updateCursor;
+ break;
+
+ case SC_35:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_35");
+ scene->preloadMovements(sceneVar);
+ scene35_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_35");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler35, 2, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_36:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_36");
+ scene->preloadMovements(sceneVar);
+ scene36_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_36");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler36, 2);
+ _updateCursorCallback = scene36_updateCursor;
+ break;
+
+ case SC_37:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_37");
+ scene->preloadMovements(sceneVar);
+ scene37_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_37");
+ setSceneMusicParameters(sceneVar);
+ insertMessageHandler(sceneHandler37, 2, 2);
+ _updateCursorCallback = scene37_updateCursor;
+ break;
+
+ case SC_38:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_38");
+ scene->preloadMovements(sceneVar);
+ scene38_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_38");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandler38, 2);
+ _updateCursorCallback = defaultUpdateCursor;
+ break;
+
+ case SC_FINAL1:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_FINAL1");
+ scene->preloadMovements(sceneVar);
+ sceneFinal1_initScene();
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_FINAL1");
+ setSceneMusicParameters(sceneVar);
+ addMessageHandler(sceneHandlerFinal1, 2);
+ _updateCursorCallback = sceneFinal1_updateCursor;
+ break;
+#endif
+
+ case SC_DBGMENU:
+ sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_DBGMENU");
+ scene->preloadMovements(sceneVar);
+ sceneDbgMenu_initScene(scene);
+ _behaviorManager->initBehavior(scene, sceneVar);
+ scene->initObjectCursors("SC_DBGMENU");
+ addMessageHandler(sceneHandlerDbgMenu, 2);
+ break;
+
+ default:
+ _behaviorManager->initBehavior(0, 0);
+ break;
+ }
+
+ return true;
+}
+
+int defaultUpdateCursor() {
+ g_fullpipe->updateCursorCommon();
+
+ return g_fullpipe->_cursorId;
+}
+
+void FullpipeEngine::initArcadeKeys(const char *varname) {
+ warning("STUB: FullpipeEngine::initArcadeKeys(\"%s\")", varname);
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h
new file mode 100644
index 0000000000..ed0da0a9db
--- /dev/null
+++ b/engines/fullpipe/scenes.h
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_SCENES_H
+#define FULLPIPE_SCENES_H
+
+namespace Fullpipe {
+
+class StaticANIObject;
+
+int defaultUpdateCursor();
+
+int sceneIntro_updateCursor();
+void sceneIntro_initScene(Scene *sc);
+int sceneHandlerIntro(ExCommand *cmd);
+
+void scene01_fixEntrance();
+void scene01_initScene(Scene *sc, int entrance);
+int sceneHandler01(ExCommand *cmd);
+
+void scene02_initScene(Scene *sc);
+int sceneHandler02(ExCommand *ex);
+
+void scene03_setEaterState();
+int scene03_updateCursor();
+void scene03_initScene(Scene *sc);
+int sceneHandler03(ExCommand *cmd);
+
+int scene04_updateCursor();
+void scene04_initScene(Scene *sc);
+int sceneHandler04(ExCommand *cmd);
+
+void sceneDbgMenu_initScene(Scene *sc);
+int sceneHandlerDbgMenu(ExCommand *cmd);
+
+class Vars {
+public:
+ Vars();
+
+ GameVar *swallowedEgg1;
+ GameVar *swallowedEgg2;
+ GameVar *swallowedEgg3;
+
+ StaticANIObject *sceneIntro_aniin1man;
+ bool sceneIntro_needSleep;
+ bool sceneIntro_needGetup;
+ bool sceneIntro_skipIntro;
+ bool sceneIntro_playing;
+ bool sceneIntro_needBlackout;
+
+ PictureObject *scene01_picSc01Osk;
+ PictureObject *scene01_picSc01Osk2;
+
+ StaticANIObject *scene02_guvTheDrawer;
+ int scene02_boxDelay;
+ bool scene02_boxOpen;
+
+ StaticANIObject *scene03_eggeater;
+ StaticANIObject *scene03_domino;
+
+ PictureObject *scene04_bottle;
+ StaticANIObject *scene04_hand;
+ StaticANIObject *scene04_plank;
+ StaticANIObject *scene04_clock;
+ StaticANIObject *scene04_spring;
+ StaticANIObject *scene04_mamasha;
+ StaticANIObject *scene04_boot;
+ StaticANIObject *scene04_speaker;
+
+ Common::Point scene04_jumpingKozyawki[20];
+ Common::Point scene04_jumpRotateKozyawki[20];
+
+ Common::List<StaticANIObject *> scene04_kozyawkiObjList;
+ Common::List<GameObject *> scene04_bottleObjList;
+ Common::List<StaticANIObject *> scene04_kozyawkiAni;
+
+ int scene04_ladder;
+ bool scene04_coinPut;
+ bool scene04_soundPlaying;
+ int scene04_dynamicPhaseIndex;
+ int scene04_sceneClickX;
+ int scene04_sceneClickY;
+ int scene04_dudePosX;
+ int scene04_dudePosY;
+
+ int scene04_var01;
+ int scene04_var02;
+ int scene04_var04;
+ StaticANIObject *scene04_walkingKozyawka;
+ int scene04_var06;
+ int scene04_var07;
+ int scene04_var08;
+ int scene04_var09;
+ int scene04_var10;
+ int scene04_var11;
+ int scene04_var12;
+ int scene04_var13;
+ int scene04_var14;
+ int scene04_var15;
+ int scene04_speakerVariant;
+ int scene04_speakerPhase;
+ int scene04_var18;
+ int scene04_var19;
+ int scene04_var20;
+ StaticANIObject *scene04_var24;
+ int scene04_var26;
+
+ PictureObject *selector;
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_SCENES_H */
diff --git a/engines/fullpipe/scenes/scene01.cpp b/engines/fullpipe/scenes/scene01.cpp
new file mode 100644
index 0000000000..4181bbffe3
--- /dev/null
+++ b/engines/fullpipe/scenes/scene01.cpp
@@ -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.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/behavior.h"
+
+
+namespace Fullpipe {
+
+void scene01_fixEntrance() {
+ GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
+ if (var->getSubVarAsInt("Entrance") == TrubaLeft)
+ var->setSubVarAsInt("Entrance", TrubaRight);
+}
+
+void scene01_initScene(Scene *sc, int entrance) {
+ g_vars->scene01_picSc01Osk = sc->getPictureObjectById(PIC_SC1_OSK, 0);
+ g_vars->scene01_picSc01Osk->_flags &= 0xFFFB;
+
+ g_vars->scene01_picSc01Osk2 = sc->getPictureObjectById(PIC_SC1_OSK2, 0);
+ g_vars->scene01_picSc01Osk2->_flags &= 0xFFFB;
+
+ if (g_fullpipe->getObjectState(sO_EggCracker) == g_fullpipe->getObjectEnumState(sO_EggCracker, sO_DidNotCrackEgg)) {
+ PictureObject *pic = sc->getPictureObjectById(PIC_SC1_KUCHKA, 0);
+ if (pic)
+ pic->_flags &= 0xFFFB;
+ }
+
+ if (entrance != TrubaLeft) {
+ StaticANIObject *bootAnim = sc->getStaticANIObject1ById(ANI_BOOT_1, -1);
+ if (bootAnim)
+ bootAnim->_flags &= ~0x04;
+ }
+
+ g_fullpipe->lift_setButton(sO_Level2, ST_LBN_2N);
+}
+
+int sceneHandler01(ExCommand *cmd) {
+ int res = 0;
+
+ if (cmd->_messageKind != 17)
+ return 0;
+
+ if (cmd->_messageNum > MSG_SC1_SHOWOSK) {
+ if (cmd->_messageNum == MSG_SC1_UTRUBACLICK)
+ handleObjectInteraction(g_fullpipe->_aniMan, g_fullpipe->_currentScene->getPictureObjectById(PIC_SC1_LADDER, 0), 0);
+
+ return 0;
+ }
+
+ if (cmd->_messageNum == MSG_SC1_SHOWOSK) {
+ g_vars->scene01_picSc01Osk->_flags |= 4;
+
+ g_vars->scene01_picSc01Osk->_priority = 20;
+ g_vars->scene01_picSc01Osk2->_priority = 21;
+
+ return 0;
+ }
+
+ if (cmd->_messageNum != 0x21) {
+ if (cmd->_messageNum == MSG_SC1_SHOWOSK2) {
+ g_vars->scene01_picSc01Osk2->_flags |= 4;
+ g_vars->scene01_picSc01Osk2->_priority = 20;
+ g_vars->scene01_picSc01Osk->_priority = 21;
+
+ return 0;
+ }
+
+ return 0;
+ }
+
+ if (g_fullpipe->_aniMan2) {
+ if (g_fullpipe->_aniMan2->_ox < g_fullpipe->_sceneRect.left + 200) {
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.left - 300;
+ }
+
+ if (g_fullpipe->_aniMan2->_ox > g_fullpipe->_sceneRect.right - 200)
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.right + 300;
+
+ res = 1;
+ }
+ g_fullpipe->_behaviorManager->updateBehaviors();
+
+ g_fullpipe->startSceneTrack();
+
+ return res;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene02.cpp b/engines/fullpipe/scenes/scene02.cpp
new file mode 100644
index 0000000000..dd01af4c4b
--- /dev/null
+++ b/engines/fullpipe/scenes/scene02.cpp
@@ -0,0 +1,137 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/behavior.h"
+#include "fullpipe/floaters.h"
+
+
+namespace Fullpipe {
+
+void scene02_initScene(Scene *sc) {
+ g_vars->scene02_guvTheDrawer = sc->getStaticANIObject1ById(ANI_DADAYASHIK, -1);
+
+ if (g_fullpipe->getObjectState(sO_GuvTheDrawer) == g_fullpipe->getObjectEnumState(sO_GuvTheDrawer, sO_Sleeping)) {
+ Scene *s = g_fullpipe->_currentScene;
+
+ g_fullpipe->_currentScene = sc;
+ g_vars->scene02_guvTheDrawer->changeStatics2(ST_DYAS_LIES);
+ g_fullpipe->_currentScene = s;
+ }
+
+ g_vars->scene02_boxDelay = 0;
+
+ StaticANIObject *box = sc->getStaticANIObject1ById(ANI_SC2_BOX, -1);
+
+ if (box && box->_flags & 4) {
+ g_vars->scene02_boxOpen = false;
+ } else {
+ g_vars->scene02_boxOpen = true;
+ g_vars->scene02_boxDelay = 100 * g_fullpipe->_rnd->getRandomNumber(32767) + 150;
+ }
+
+ g_fullpipe->_floaters->init(g_fullpipe->_gameLoader->_gameVar->getSubVarByName("SC_2"));
+}
+
+void sceneHandler02_ladderClick() {
+ handleObjectInteraction(g_fullpipe->_aniMan2, g_fullpipe->_currentScene->getPictureObjectById(PIC_SC2_DTRUBA, 0), 0);
+}
+
+void sceneHandler02_showLadder() {
+ g_fullpipe->_currentScene->getPictureObjectById(PIC_SC2_LADDER, 0)->_flags |= 4;
+}
+
+void sceneHandler02_hideLadder() {
+ g_fullpipe->_currentScene->getPictureObjectById(PIC_SC2_LADDER, 0)->_flags &= 0xfffb;
+ g_fullpipe->_aniMan2->_priority = 25;
+}
+
+int sceneHandler02(ExCommand *ex) {
+ int res = 0;
+
+ if (ex->_messageKind != 17)
+ return 0;
+
+ switch(ex->_messageNum) {
+ case MSG_SC2_LADDERCLICK:
+ sceneHandler02_ladderClick();
+ return 0;
+
+ case MSG_SC2_SHOWLADDER:
+ sceneHandler02_showLadder();
+ return 0;
+
+ case MSG_SC2_PUTMANUP:
+ g_fullpipe->_aniMan2->_priority = 0;
+ return 0;
+
+ case MSG_SC2_HIDELADDER:
+ sceneHandler02_hideLadder();
+ return 0;
+
+ case 33:
+ if (g_fullpipe->_aniMan2) {
+ if (g_fullpipe->_aniMan2->_ox < g_fullpipe->_sceneRect.left + 200)
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.left - 300;
+
+ if (g_fullpipe->_aniMan2->_ox > g_fullpipe->_sceneRect.right - 200)
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.right + 300;
+
+ res = 1;
+ }
+
+ if (g_vars->scene02_boxOpen) {
+ if (g_vars->scene02_boxDelay >= 1) {
+ --g_vars->scene02_boxDelay;
+ } else if (g_fullpipe->_floaters->_array2.size() >= 1) {
+ if (g_fullpipe->_floaters->_array2[0]->val5 == -50) {
+ g_fullpipe->_floaters->stopAll();
+ g_vars->scene02_boxOpen = false;
+ g_vars->scene02_boxDelay = 100 * g_fullpipe->_rnd->getRandomNumber(32767) + 150;
+ } else {
+ g_fullpipe->_floaters->_array2[0]->val3 = -50;
+ }
+ } else {
+ g_fullpipe->_floaters->genFlies(g_fullpipe->_currentScene, g_fullpipe->_rnd->getRandomNumber(700) + 100, -50, 0, 0);
+ g_vars->scene02_boxDelay = 500 * g_fullpipe->_rnd->getRandomNumber(32767) + 1000;
+ }
+ }
+
+ g_fullpipe->_floaters->update();
+ g_fullpipe->_behaviorManager->updateBehaviors();
+
+ g_fullpipe->startSceneTrack();
+ }
+
+ return res;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene03.cpp b/engines/fullpipe/scenes/scene03.cpp
new file mode 100644
index 0000000000..e9f8a240e8
--- /dev/null
+++ b/engines/fullpipe/scenes/scene03.cpp
@@ -0,0 +1,294 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/behavior.h"
+
+namespace Fullpipe {
+
+void FullpipeEngine::setSwallowedEggsState() {
+ GameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs);
+
+ g_vars->swallowedEgg1 = v->getSubVarByName(sO_Egg1);
+ g_vars->swallowedEgg2 = v->getSubVarByName(sO_Egg2);
+ g_vars->swallowedEgg3 = v->getSubVarByName(sO_Egg3);
+
+ g_vars->swallowedEgg1->_value.intValue = 0;
+ g_vars->swallowedEgg2->_value.intValue = 0;
+ g_vars->swallowedEgg3->_value.intValue = 0;
+}
+
+void scene03_initScene(Scene *sc) {
+ g_vars->scene03_eggeater = sc->getStaticANIObject1ById(ANI_EGGEATER, -1);
+ g_vars->scene03_domino = sc->getStaticANIObject1ById(ANI_DOMINO_3, -1);
+
+ GameVar *v = g_fullpipe->_gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs);
+
+ g_vars->swallowedEgg1 = v->getSubVarByName(sO_Egg1);
+ g_vars->swallowedEgg2 = v->getSubVarByName(sO_Egg2);
+ g_vars->swallowedEgg3 = v->getSubVarByName(sO_Egg3);
+
+ g_fullpipe->lift_setButton(sO_Level2, ST_LBN_2N);
+
+ g_fullpipe->lift_sub5(sc, QU_SC3_ENTERLIFT, QU_SC3_EXITLIFT);
+}
+
+void scene03_setEaterState() {
+ if (g_fullpipe->getObjectState(sO_EggGulperGaveCoin) == g_fullpipe->getObjectEnumState(sO_EggGulperGaveCoin, sO_Yes)) {
+ g_fullpipe->_behaviorManager->setBehaviorEnabled(g_vars->scene03_eggeater, ST_EGTR_SLIM, QU_EGTR_SLIMSHOW, 0);
+ g_fullpipe->_behaviorManager->setBehaviorEnabled(g_vars->scene03_eggeater, ST_EGTR_MID1, QU_EGTR_MD1_SHOW, 0);
+ g_fullpipe->_behaviorManager->setBehaviorEnabled(g_vars->scene03_eggeater, ST_EGTR_MID2, QU_EGTR_MD2_SHOW, 0);
+ }
+}
+
+int scene03_updateCursor() {
+ g_fullpipe->updateCursorCommon();
+
+ if (g_fullpipe->_cursorId == PIC_CSR_DEFAULT && g_fullpipe->_objectIdAtCursor == PIC_SC3_DOMIN && g_vars->scene03_domino) {
+ if (g_vars->scene03_domino->_flags & 4)
+ g_fullpipe->_cursorId = PIC_CSR_ITN;
+ }
+
+ return g_fullpipe->_cursorId;
+}
+
+void sceneHandler03_eaterFat() {
+ g_vars->scene03_eggeater->_flags &= 0xFF7F;
+
+ g_vars->scene03_eggeater->startAnim(MV_EGTR_FATASK, 0, -1);
+}
+
+void sceneHandler03_swallowEgg(int item) {
+ if (!g_vars->swallowedEgg1->_value.intValue) {
+ g_vars->swallowedEgg1->_value.intValue = item;
+ } else if (!g_vars->swallowedEgg2->_value.intValue) {
+ g_vars->swallowedEgg2->_value.intValue = item;
+ } else if (!g_vars->swallowedEgg3->_value.intValue) {
+ g_vars->swallowedEgg3->_value.intValue = item;
+
+ g_fullpipe->setObjectState(sO_EggGulperGaveCoin, g_fullpipe->getObjectEnumState(sO_EggGulperGaveCoin, sO_Yes));
+
+ scene03_setEaterState();
+ }
+}
+
+void sceneHandler03_giveItem(ExCommand *ex) {
+ if (ex->_parentId == ANI_INV_EGGAPL || ex->_parentId == ANI_INV_EGGDOM ||
+ ex->_parentId == ANI_INV_EGGCOIN || ex->_parentId == ANI_INV_EGGBOOT ||
+ ex->_parentId == ANI_INV_EGGGLS)
+ sceneHandler03_swallowEgg(ex->_parentId);
+}
+
+int sceneHandler03_swallowedEgg1State() {
+ return g_vars->swallowedEgg1->_value.intValue;
+}
+
+void sceneHandler03_giveCoin(ExCommand *ex) {
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(ex->_parId);
+
+ if (mq && mq->getCount() > 0) {
+ ExCommand *ex0 = mq->getExCommandByIndex(0);
+ ExCommand *ex1 = mq->getExCommandByIndex(1);
+
+ if (sceneHandler03_swallowedEgg1State()) {
+ ex0->_messageKind = 1;
+ ex1->_messageKind = 1;
+
+ getGameLoaderInventory()->removeItem(ANI_INV_COIN, 1);
+ } else {
+ ex0->_messageKind = 0;
+ ex0->_excFlags |= 1;
+
+ ex1->_messageKind = 0;
+ ex1->_excFlags |= 1;
+
+ g_vars->scene03_eggeater->_flags &= 0xFF7Fu;
+ }
+ }
+}
+
+void sceneHandler03_goLadder() {
+ handleObjectInteraction(g_fullpipe->_aniMan, g_fullpipe->_currentScene->getPictureObjectById(PIC_SC3_LADDER, 0), 0);
+}
+
+void sceneHandler03_pushEggStack() {
+ g_vars->swallowedEgg1->_value.intValue = g_vars->swallowedEgg2->_value.intValue;
+ g_vars->swallowedEgg2->_value.intValue = g_vars->swallowedEgg3->_value.intValue;
+ g_vars->swallowedEgg3->_value.intValue = 0;
+
+ if (g_vars->swallowedEgg2->_value.intValue == ANI_INV_EGGBOOT
+ && g_vars->swallowedEgg1->_value.intValue == ANI_INV_EGGAPL) {
+ g_vars->swallowedEgg1->_value.intValue = ANI_INV_EGGBOOT;
+ g_vars->swallowedEgg2->_value.intValue = ANI_INV_EGGAPL;
+ }
+}
+
+void sceneHandler03_releaseEgg() {
+ g_vars->scene03_eggeater->_flags &= 0xFF7F;
+
+ g_vars->scene03_eggeater->show1(-1, -1, -1, 0);
+}
+
+void sceneHandler03_takeEgg(ExCommand *ex) {
+ MessageQueue *mq = g_fullpipe->_globalMessageQueueList->getMessageQueueById(ex->_parId);
+
+ if (mq && mq->getCount() > 0) {
+ ExCommand *ex0 = mq->getExCommandByIndex(0);
+ ExCommand *ex1 = mq->getExCommandByIndex(1);
+
+ int egg1 = sceneHandler03_swallowedEgg1State();
+
+ if (egg1 && ex0) {
+ ex0->_parentId = egg1;
+ sceneHandler03_pushEggStack();
+ }
+
+ if ( g_vars->swallowedEgg1->_value.intValue == ANI_INV_EGGAPL
+ && !g_vars->swallowedEgg2->_value.intValue
+ && !g_vars->swallowedEgg3->_value.intValue
+ && ex1) {
+
+ if (ex1->_objtype == kObjTypeObjstateCommand) {
+ ObjstateCommand *com = (ObjstateCommand *)ex1;
+
+ com->_value = g_fullpipe->getObjectEnumState(sO_EggGulper, sO_WantsNothing);
+ }
+ }
+ }
+}
+
+int sceneHandler03(ExCommand *ex) {
+ if (ex->_messageKind != 17) {
+ if (ex->_messageKind == 57)
+ sceneHandler03_giveItem(ex);
+ return 0;
+ }
+
+ switch (ex->_messageNum) {
+ case MSG_LIFT_EXITLIFT:
+ g_fullpipe->lift_exitSeq(ex);
+ break;
+
+ case MSG_LIFT_CLOSEDOOR:
+ g_fullpipe->lift_closedoorSeq();
+ break;
+
+ case MSG_SC3_ONTAKECOIN:
+ sceneHandler03_eaterFat();
+ break;
+
+ case MSG_LIFT_STARTEXITQUEUE:
+ g_fullpipe->lift_startExitQueue();
+ break;
+
+ case MSG_SC3_RELEASEEGG:
+ sceneHandler03_releaseEgg();
+ break;
+
+ case MSG_LIFT_CLICKBUTTON:
+ g_fullpipe->lift_animation3();
+ break;
+
+ case MSG_SC3_HIDEDOMINO:
+ g_vars->scene03_domino->_flags &= 0xFFFB;
+ break;
+
+ case MSG_SC3_TAKEEGG:
+ sceneHandler03_takeEgg(ex);
+ break;
+
+ case MSG_LIFT_GO:
+ g_fullpipe->lift_goAnimation();
+ break;
+
+ case MSG_SC3_UTRUBACLICK:
+ sceneHandler03_goLadder();
+ break;
+
+ case MSG_SC3_TESTFAT:
+ sceneHandler03_giveCoin(ex);
+ break;
+
+ case 64:
+ g_fullpipe->lift_sub05(ex);
+ break;
+
+ case 93:
+ {
+ StaticANIObject *ani = g_fullpipe->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY);
+ if (ani && ani->_id == ANI_LIFTBUTTON) {
+ g_fullpipe->lift_sub1(ani);
+ ex->_messageKind = 0;
+
+ return 0;
+ }
+
+ if (g_fullpipe->_currentScene->getPictureObjectIdAtPos(ex->_sceneClickX, ex->_sceneClickY) == PIC_SC3_DOMIN) {
+ if (g_vars->scene03_domino)
+ if (g_vars->scene03_domino->_flags & 4)
+ if (g_fullpipe->_aniMan->isIdle())
+ if (!(g_fullpipe->_aniMan->_flags & 0x100) && g_fullpipe->_msgObjectId2 != g_vars->scene03_domino->_id) {
+ handleObjectInteraction(g_fullpipe->_aniMan, g_vars->scene03_domino, ex->_keyCode);
+ ex->_messageKind = 0;
+
+ return 0;
+ }
+ }
+
+ break;
+ }
+
+ case 97:
+ {
+ int res = 0;
+
+ if (g_fullpipe->_aniMan2) {
+ if (g_fullpipe->_aniMan2->_ox < g_fullpipe->_sceneRect.left + 200)
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.left - 300;
+
+ if (g_fullpipe->_aniMan2->_ox > g_fullpipe->_sceneRect.right - 200)
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan2->_ox - g_fullpipe->_sceneRect.right + 300;
+
+ res = 1;
+ }
+
+ g_fullpipe->_behaviorManager->updateBehaviors();
+
+ g_fullpipe->startSceneTrack();
+
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp
new file mode 100644
index 0000000000..f2fbfd3ef4
--- /dev/null
+++ b/engines/fullpipe/scenes/scene04.cpp
@@ -0,0 +1,731 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+#include "fullpipe/utils.h"
+#include "fullpipe/gfx.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/behavior.h"
+
+namespace Fullpipe {
+
+static const int scene04_speakerPhases[] = {
+ 0, 1, 2, 3, -1, -1,
+ 0, 2, 3, -1, -1, -1,
+ 0, 2, -1, -1, -1, -1
+};
+
+void scene04_speakerCallback(int *phase) {
+ if (g_vars->scene04_soundPlaying) {
+ if (g_vars->scene04_speakerPhase >= 0) {
+ *phase = scene04_speakerPhases[g_vars->scene04_speakerPhase + 6 * g_vars->scene04_speakerVariant];
+
+ g_vars->scene04_speakerPhase++;
+
+ if (scene04_speakerPhases[g_vars->scene04_speakerPhase + 6 * g_vars->scene04_speakerVariant] < 0) {
+ g_vars->scene04_speakerPhase = 0;
+ g_vars->scene04_speakerVariant = g_fullpipe->_rnd->getRandomNumber(2);
+ }
+ } else {
+ ++g_vars->scene04_speakerPhase;
+ }
+ }
+}
+
+void scene04_initScene(Scene *sc) {
+ g_vars->scene04_var01 = 0;
+ g_vars->scene04_bottle = sc->getPictureObjectById(PIC_SC4_BOTTLE, 0);
+ g_vars->scene04_hand = sc->getStaticANIObject1ById(ANI_HAND, -1);
+ g_vars->scene04_plank = sc->getStaticANIObject1ById(ANI_PLANK, -1);
+ g_vars->scene04_clock = sc->getStaticANIObject1ById(ANI_CLOCK, -1);
+ g_vars->scene04_spring = sc->getStaticANIObject1ById(ANI_SPRING, -1);
+ g_vars->scene04_mamasha = sc->getStaticANIObject1ById(ANI_MAMASHA_4, -1);
+ g_vars->scene04_boot = sc->getStaticANIObject1ById(ANI_SC4_BOOT, -1);
+ g_vars->scene04_ladder = 0;
+
+ StaticANIObject *koz = sc->getStaticANIObject1ById(ANI_KOZAWKA, -1);
+
+ if (koz) {
+ Movement *kozmov = koz->getMovementById(MV_KZW_JUMP);
+ if (kozmov) {
+ uint kozsize = kozmov->_currMovement ? kozmov->_currMovement->_dynamicPhases.size() : kozmov->_dynamicPhases.size();
+
+ for (uint i = 0; i < kozsize; i++) {
+ kozmov->setDynamicPhaseIndex(i);
+
+ if (kozmov->_framePosOffsets) {
+ g_vars->scene04_jumpingKozyawki[i] = *kozmov->_framePosOffsets[kozmov->_currDynamicPhaseIndex];
+ } else {
+ kozmov->_somePoint.x = 0;
+ kozmov->_somePoint.y = 0;
+ g_vars->scene04_jumpingKozyawki[i] = kozmov->_somePoint;
+ }
+ }
+ }
+
+ kozmov = koz->getMovementById(MV_KZW_JUMPROTATE);
+ if (kozmov) {
+ uint kozsize = kozmov->_currMovement ? kozmov->_currMovement->_dynamicPhases.size() : kozmov->_dynamicPhases.size();
+
+ for (uint i = 0; i < kozsize; i++) {
+ kozmov->setDynamicPhaseIndex(i);
+
+ if (kozmov->_framePosOffsets) {
+ g_vars->scene04_jumpRotateKozyawki[i] = *kozmov->_framePosOffsets[kozmov->_currDynamicPhaseIndex];
+ } else {
+ kozmov->_somePoint.x = 0;
+ kozmov->_somePoint.y = 0;
+ g_vars->scene04_jumpRotateKozyawki[i] = kozmov->_somePoint;
+ }
+ }
+ }
+ }
+
+ Interaction *plank = getGameLoaderInteractionController()->getInteractionByObjectIds(ANI_PLANK, 0, 0);
+ if (plank)
+ plank->_flags |= 8;
+
+ if (g_fullpipe->getObjectState(sO_Jar_4) == g_fullpipe->getObjectEnumState(sO_Jar_4, sO_UpsideDown)) {
+ g_vars->scene04_bottleObjList.clear();
+ g_vars->scene04_kozyawkiObjList.clear();
+
+ sc->getPictureObjectById(PIC_SC4_BOTTLE, 0)->_flags &= 0xfffb;
+ sc->getPictureObjectById(PIC_SC4_MASK, 0)->_flags &= 0xfffb;
+ sc->getStaticANIObject1ById(ANI_SPRING, 0)->_flags &= 0xfffb;
+
+ g_vars->scene04_var18 = 0;
+ g_vars->scene04_var19 = 0;
+ } else {
+ StaticANIObject *spring = sc->getStaticANIObject1ById(ANI_SPRING, -1);
+
+ if (spring)
+ spring->_callback2 = 0;
+
+ g_vars->scene04_bottleObjList.clear();
+ g_vars->scene04_bottleObjList.push_back(sc->getPictureObjectById(PIC_SC4_BOTTLE, 0));
+ g_vars->scene04_bottleObjList.push_back(sc->getPictureObjectById(PIC_SC4_MASK, 0));
+
+ g_vars->scene04_kozyawkiObjList.clear();
+
+ if (koz) {
+ koz->loadMovementsPixelData();
+
+ koz->_statics = koz->getStaticsById(ST_KZW_EMPTY);
+ koz->setOXY(0, 0);
+ koz->hide();
+
+ g_vars->scene04_kozyawkiObjList.push_back(koz);
+
+ for (int i = 0; i < 6; i++) {
+ StaticANIObject *koz1 = new StaticANIObject(koz);
+
+ sc->addStaticANIObject(koz1, 1);
+ koz1->_statics = koz->getStaticsById(ST_KZW_EMPTY);
+ koz1->setOXY(0, 0);
+ koz1->hide();
+ g_vars->scene04_kozyawkiObjList.push_back(koz1);
+ }
+ }
+ sc->getPictureObjectById(PIC_SC4_BOTTLE2, 0)->_flags &= 0xfffb;
+
+ g_vars->scene04_var18 = 1;
+ g_vars->scene04_var19 = 1;
+ }
+
+ g_vars->scene04_var02 = 0;
+ g_vars->scene04_soundPlaying = false;
+ g_vars->scene04_var04 = 0;
+ g_vars->scene04_walkingKozyawka = 0;
+ g_vars->scene04_var06 = 2;
+ g_vars->scene04_dynamicPhaseIndex = 0;
+
+ g_vars->scene04_kozyawkiAni.clear();
+
+ g_fullpipe->setObjectState(sO_LowerPipe, g_fullpipe->getObjectEnumState(sO_LowerPipe, sO_IsClosed));
+
+ g_vars->scene04_var07 = 0;
+ g_vars->scene04_var08 = 0;
+ g_vars->scene04_coinPut = 0;
+ g_vars->scene04_var09 = 0;
+ g_vars->scene04_var10 = 0;
+ g_vars->scene04_var11 = 0;
+ g_vars->scene04_var12 = 0;
+ g_vars->scene04_var13 = 1;
+ g_vars->scene04_var14 = 0;
+ g_vars->scene04_var15 = 1;
+
+ if (g_fullpipe->getObjectState(sO_BigMumsy) != g_fullpipe->getObjectEnumState(sO_BigMumsy, sO_Gone))
+ g_vars->scene04_mamasha->hide();
+
+ g_vars->scene04_speaker = sc->getStaticANIObject1ById(ANI_SPEAKER_4, -1);
+ g_vars->scene04_speaker->_callback2 = scene04_speakerCallback;
+ g_vars->scene04_speaker->startAnim(MV_SPK4_PLAY, 0, -1);
+
+ g_vars->scene04_speakerVariant = 0;
+ g_vars->scene04_speakerPhase = 0;
+
+ g_fullpipe->initArcadeKeys("SC_4");
+}
+
+bool sceneHandler04_friesAreWalking() {
+ warning("STUB: sceneHandler04_friesAreWalking()");
+
+ return false;
+}
+
+int scene04_updateCursor() {
+ g_fullpipe->updateCursorCommon();
+
+ if (g_fullpipe->_objectIdAtCursor == PIC_SC4_LRTRUBA) {
+ if (!g_vars->scene04_var19) {
+ g_fullpipe->_cursorId = PIC_CSR_DEFAULT;
+
+ return g_fullpipe->_cursorId;
+ }
+ } else if (g_fullpipe->_objectIdAtCursor == ANI_PLANK || g_fullpipe->_objectIdAtCursor == PIC_SC4_PLANK) {
+ if (g_fullpipe->_objectIdAtCursor == ANI_PLANK && g_fullpipe->_cursorId != PIC_CSR_ITN)
+ return g_fullpipe->_cursorId;
+
+ if (g_fullpipe->_objectIdAtCursor == ANI_PLANK || (g_fullpipe->_objectIdAtCursor == PIC_SC4_PLANK && g_fullpipe->_cursorId == PIC_CSR_DEFAULT)) {
+ if (sceneHandler04_friesAreWalking()) {
+ g_fullpipe->_cursorId = PIC_CSR_ARCADE1;
+ return g_fullpipe->_cursorId;
+ }
+ if (g_vars->scene04_soundPlaying) {
+ g_fullpipe->_cursorId = PIC_CSR_DEFAULT;
+ return g_fullpipe->_cursorId;
+ }
+ }
+ }
+
+ if (g_fullpipe->_objectIdAtCursor == PIC_CSR_ITN && g_fullpipe->_objectIdAtCursor == PIC_SC4_DOWNTRUBA)
+ g_fullpipe->_cursorId = PIC_CSR_GOD;
+
+ return g_fullpipe->_cursorId;
+}
+
+void sceneHandlers_sub01(ExCommand *ex) {
+ warning("sceneHandlers_sub01()");
+}
+
+void sceneHandler04_checkBigBallClick() {
+ StaticANIObject *ball = g_fullpipe->_currentScene->getStaticANIObject1ById(ANI_BIGBALL, -1);
+
+ if (ball)
+ for (uint i = 0; i < ball->_movements.size(); i++)
+ ((Movement *)ball->_movements[i])->_counterMax = 73;
+
+ g_vars->scene04_var13 = 1;
+}
+
+void sceneHandler04_clickBottle() {
+ if (!g_vars->scene04_var02)
+ g_vars->scene04_var20 += 5;
+}
+
+void sceneHandler04_clickButton() {
+ StaticANIObject *but = g_fullpipe->_currentScene->getStaticANIObject1ById(ANI_BUTTON, -1);
+
+ if (but) {
+ if (!g_vars->scene04_clock->_movement ||
+ (g_vars->scene04_clock->_movement->_id == MV_CLK_GO && g_vars->scene04_clock->_movement->_currDynamicPhaseIndex > 3 &&
+ g_vars->scene04_clock->_movement->_currDynamicPhaseIndex < 105)) {
+ if (!g_vars->scene04_hand->_movement && !g_vars->scene04_var02) {
+ but->startAnim(MV_BTN_CLICK, 0, -1);
+ g_vars->scene04_hand->startAnim(MV_HND_POINT, 0, -1);
+ }
+ }
+ }
+}
+
+void sceneHandler04_clickLadder() {
+ warning("sceneHandler04_clickLadder()");
+}
+
+void sceneHandler04_sub13() {
+ warning("sceneHandler04_sub13()");
+}
+
+void sceneHandler04_clickPlank() {
+ if (sceneHandler04_friesAreWalking())
+ sceneHandler04_sub13();
+ else if (g_vars->scene04_var01)
+ g_fullpipe->playSound(SND_4_033, 0);
+ else if (!g_vars->scene04_soundPlaying)
+ chainQueue(QU_PNK_CLICK, 0);
+}
+
+void sceneHandler04_dropBottle() {
+ g_vars->scene04_var12 = 1;
+ g_vars->scene04_var26 = 10;
+ g_vars->scene04_var06 = 0;
+
+ while (g_vars->scene04_kozyawkiAni.size()) {
+ StaticANIObject *koz = g_vars->scene04_kozyawkiAni.front();
+ g_vars->scene04_kozyawkiAni.pop_front();
+
+ for (Common::List<GameObject *>::iterator it = g_vars->scene04_bottleObjList.begin(); it != g_vars->scene04_bottleObjList.end(); ++it)
+ if (*it == koz) {
+ g_vars->scene04_bottleObjList.erase(it);
+ break;
+ }
+
+ koz->queueMessageQueue(0);
+ koz->hide();
+
+ g_vars->scene04_kozyawkiObjList.push_back(koz);
+ }
+
+ g_vars->scene04_hand->changeStatics2(ST_HND_EMPTY);
+
+ g_vars->scene04_hand->setOXY(429, 21);
+ g_vars->scene04_hand->_priority = 15;
+}
+
+void sceneHandler04_gotoLadder(int par) {
+ warning("sceneHandler04_gotoLadder()");
+}
+
+void sceneHandler04_lowerPlank() {
+ g_vars->scene04_plank->startAnim(MV_PNK_WEIGHTRIGHT, 0, -1);
+}
+
+void sceneHandler04_manFromBottle() {
+ warning("sceneHandler04_manFromBottle()");
+}
+
+void sceneHandler04_manToBottle() {
+ g_vars->scene04_bottleObjList.push_back(g_fullpipe->_aniMan);
+ g_vars->scene04_var20 = 5;
+ g_vars->scene04_var06 += 9;
+ g_fullpipe->_aniMan2 = g_fullpipe->_aniMan;
+ g_vars->scene04_var10 = 1;
+}
+
+void sceneHandler04_raisePlank() {
+ g_vars->scene04_plank->startAnim(MV_PNK_WEIGHTLEFT, 0, -1);
+}
+
+void sceneHandler04_shootKozyawka() {
+ warning("sceneHandler04_shootKozyawka()");
+}
+
+void sceneHandler04_showCoin() {
+ StaticANIObject *ani = g_fullpipe->_currentScene->getStaticANIObject1ById(ANI_SC4_COIN, -1);
+
+ if (ani) {
+ ani->show1(MV_BDG_OPEN, MV_MAN_GOU, MV_SC4_COIN_default, 0);
+
+ ani->_priority = 40;
+ }
+}
+
+void sceneHandler04_stopSound() {
+ warning("sceneHandler04_stopSound()");
+}
+
+void sceneHandler04_sub1(ExCommand *ex) {
+ g_fullpipe->_aniMan->changeStatics2(ST_MAN_SIT);
+
+ MessageQueue *mq = new MessageQueue(g_fullpipe->_currentScene->getMessageQueueById(QU_SC4_MANFROMBOTTLE), 0, 0);
+
+ if (ex) {
+ ExCommand *newex = new ExCommand(ex);
+
+ mq->_exCommands.push_back(newex);
+ }
+
+ mq->_flags |= 1;
+ mq->chain(0);
+
+ g_vars->scene04_var10 = 0;
+ g_fullpipe->_behaviorManager->setFlagByStaticAniObject(g_fullpipe->_aniMan, 1);
+}
+
+void sceneHandler04_walkKozyawka() {
+ if (g_vars->scene04_kozyawkiObjList.size()) {
+ g_vars->scene04_walkingKozyawka = g_vars->scene04_kozyawkiObjList.front();
+ g_vars->scene04_kozyawkiObjList.pop_front();
+
+ MessageQueue *mq = new MessageQueue(g_fullpipe->_currentScene->getMessageQueueById(QU_KOZAW_WALK), 0, 1);
+ mq->replaceKeyCode(-1, g_vars->scene04_walkingKozyawka->_okeyCode);
+ mq->chain(0);
+ }
+}
+
+void sceneHandler04_sub4() {
+ warning("sceneHandler04_sub4()");
+}
+
+void sceneHandler04_sub5() {
+ warning("sceneHandler04_sub5()");
+}
+
+void sceneHandler04_sub6() {
+ warning("sceneHandler04_sub6()");
+}
+
+void sceneHandler04_sub7() {
+ warning("sceneHandler04_sub7()");
+}
+
+void sceneHandler04_sub8(ExCommand *ex) {
+ warning("sceneHandler04_sub8()");
+}
+
+void sceneHandler04_sub9(StaticANIObject *ani) {
+ warning("sceneHandler04_sub9()");
+}
+
+void sceneHandler04_sub15() {
+ warning("sceneHandler04_sub15()");
+}
+
+void sceneHandler04_sub17() {
+ warning("sceneHandler04_sub17()");
+}
+
+void sceneHandler04_takeBottle() {
+ warning("sceneHandler04_takeBottle()");
+}
+
+void sceneHandler04_takeKozyawka() {
+ warning("sceneHandler04_takeKozyawka()");
+}
+
+void sceneHandler04_testPlank(ExCommand *ex) {
+ warning("sceneHandler04_testPlank()");
+}
+
+void sceneHandler04_bottleUpdateObjects(int off) {
+ warning("sceneHandler04_bottleUpdateObjects()");
+}
+
+void sceneHandler04_updateBottle() {
+ Common::Point point;
+
+ int yoff;
+
+ if (g_vars->scene04_hand->_movement)
+ yoff = g_vars->scene04_hand->_movement->_oy;
+ else
+ yoff = g_vars->scene04_hand->_oy;
+
+ int newy = g_vars->scene04_hand->getSomeXY(point)->y + yoff + 140;
+
+ sceneHandler04_bottleUpdateObjects(newy - g_vars->scene04_spring->_oy);
+
+ g_vars->scene04_spring->setOXY(g_vars->scene04_spring->_ox, newy);
+}
+
+void sceneHandler04_winArcade() {
+ warning("sceneHandler04_winArcade()");
+}
+
+int sceneHandler04(ExCommand *ex) {
+ if (ex->_messageKind != 17)
+ return 0;
+
+ switch (ex->_messageNum) {
+ case MSG_UPDATEBOTTLE:
+ sceneHandler04_updateBottle();
+ break;
+
+ case MSG_CLICKBOTTLE:
+ sceneHandler04_clickBottle();
+ break;
+
+ case MSG_SHOOTKOZAW:
+ sceneHandler04_shootKozyawka();
+ break;
+
+ case MSG_SHAKEBOTTLE:
+ if (!g_vars->scene04_var02)
+ ++g_vars->scene04_var20;
+ break;
+
+ case MSG_STARTHAND:
+ g_vars->scene04_var09 = 1;
+ g_vars->scene04_coinPut = 0;
+
+ if (g_vars->scene04_var10)
+ sceneHandler04_sub1(0);
+
+ sceneHandler04_sub15();
+ sceneHandler04_stopSound();
+ break;
+
+ case MSG_TAKEKOZAW:
+ sceneHandler04_takeKozyawka();
+ break;
+
+ case MSG_CLICKBUTTON:
+ sceneHandler04_clickButton();
+ break;
+
+ case MSG_CLICKPLANK:
+ sceneHandler04_clickPlank();
+ break;
+
+ case MSG_RAISEPLANK:
+ sceneHandler04_raisePlank();
+ break;
+
+ case MSG_KOZAWRESTART:
+ if (g_vars->scene04_walkingKozyawka) {
+ g_vars->scene04_kozyawkiObjList.push_back(g_vars->scene04_walkingKozyawka);
+ g_vars->scene04_walkingKozyawka->hide();
+ g_vars->scene04_walkingKozyawka = 0;
+ }
+
+ if (g_vars->scene04_soundPlaying)
+ sceneHandler04_walkKozyawka();
+
+ break;
+
+ case MSG_LOWERPLANK:
+ sceneHandler04_lowerPlank();
+ break;
+
+ case MSG_TESTPLANK:
+ sceneHandler04_testPlank(ex);
+ break;
+
+ case 33:
+ {
+ g_vars->scene04_dudePosX = g_fullpipe->_aniMan->_ox;
+ g_vars->scene04_dudePosY = g_fullpipe->_aniMan->_oy;
+
+ int res = 0;
+
+ if (g_fullpipe->_aniMan2) {
+ if (g_fullpipe->_aniMan->_ox < g_fullpipe->_sceneRect.left + 200) {
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan->_ox - g_fullpipe->_sceneRect.left - 300;
+ g_fullpipe->_aniMan->_ox = g_vars->scene04_dudePosX;
+ }
+ if (g_fullpipe->_aniMan->_ox > g_fullpipe->_sceneRect.right - 200) {
+ g_fullpipe->_currentScene->_x = g_fullpipe->_aniMan->_ox - g_fullpipe->_sceneRect.right + 300;
+ }
+
+ res = 1;
+
+ if (g_vars->scene04_soundPlaying) {
+ if (g_fullpipe->_aniMan->_movement) {
+ if (g_fullpipe->_aniMan->_movement->_id == MV_MAN_TOLADDER) {
+ g_fullpipe->_aniMan2 = 0;
+
+ if (g_fullpipe->_sceneRect.left > 380)
+ g_fullpipe->_currentScene->_x = 380 - g_fullpipe->_sceneRect.left;
+ }
+ }
+ }
+ } else {
+ if (g_fullpipe->_aniMan->_movement && g_fullpipe->_aniMan->_movement->_id == MV_MAN_GOD)
+ g_fullpipe->_aniMan2 = g_fullpipe->_aniMan;
+ }
+
+ sceneHandler04_sub4();
+
+ if (g_vars->scene04_var07 && !g_vars->scene04_var09)
+ sceneHandler04_sub5();
+
+ if (g_vars->scene04_var12)
+ sceneHandler04_sub6();
+
+ if (g_vars->scene04_var08)
+ sceneHandler04_clickLadder();
+
+ if (g_vars->scene04_var10 && g_vars->scene04_hand->_movement)
+ sceneHandler04_sub1(0);
+
+ if (g_vars->scene04_coinPut && g_vars->scene04_var18 && !g_vars->scene04_var09 && !g_vars->scene04_soundPlaying)
+ sceneHandler04_sub7();
+
+ if (g_vars->scene04_var01) {
+ if (!g_vars->scene04_soundPlaying) {
+ g_fullpipe->startSceneTrack();
+
+ g_fullpipe->_behaviorManager->updateBehaviors();
+ return res;
+ }
+
+ g_vars->scene04_var14++;
+
+ if (g_vars->scene04_var14 > 600)
+ sceneHandler04_sub17();
+ }
+
+ if (g_vars->scene04_soundPlaying) {
+ g_fullpipe->_behaviorManager->updateBehaviors();
+
+ return res;
+ }
+
+ g_fullpipe->startSceneTrack();
+
+ g_fullpipe->_behaviorManager->updateBehaviors();
+
+ return res;
+ }
+
+ case 29:
+ {
+ int picid = g_fullpipe->_currentScene->getPictureObjectIdAtPos(ex->_sceneClickX, ex->_sceneClickY);
+
+ if (g_vars->scene04_var10) {
+ sceneHandler04_sub1(ex);
+
+ break;
+ }
+
+ if (picid == PIC_SC4_LADDER) {
+ if (!g_vars->scene04_var04) {
+ g_vars->scene04_sceneClickX = ex->_sceneClickX;
+ g_vars->scene04_sceneClickY = ex->_sceneClickY;
+
+ sceneHandler04_clickLadder();
+
+ ex->_messageKind = 0;
+
+ break;
+ }
+
+ sceneHandler04_gotoLadder(0);
+
+ break;
+ }
+
+ StaticANIObject *ani = g_fullpipe->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY);
+
+ if ((ani && ani->_id == ANI_PLANK) || picid == PIC_SC4_PLANK) {
+ sceneHandler04_clickPlank();
+
+ ex->_messageKind = 0;
+ } else if (g_vars->scene04_var01) {
+ sceneHandler04_sub8(ex);
+ } else if (!ani || !canInteractAny(g_fullpipe->_aniMan, ani, ex->_keyCode)) {
+ PictureObject *pic = g_fullpipe->_currentScene->getPictureObjectById(picid, 0);
+
+ if (!pic || !canInteractAny(g_fullpipe->_aniMan, pic,ex->_keyCode)) {
+ if ((g_fullpipe->_sceneRect.right - ex->_sceneClickX < 47 && g_fullpipe->_sceneRect.right < g_fullpipe->_sceneWidth - 1)
+ || (ex->_sceneClickX - g_fullpipe->_sceneRect.left < 47 && g_fullpipe->_sceneRect.left > 0))
+ sceneHandlers_sub01(ex);
+ }
+ }
+ }
+
+ break;
+
+ case MSG_SC4_HIDEBOOT:
+ g_vars->scene04_boot->_flags &= 0xfffb;
+ break;
+
+ case MSG_CMN_WINARCADE:
+ sceneHandler04_winArcade();
+ break;
+
+ case MSG_SC4_HANDOVER:
+ g_vars->scene04_var09 = 0;
+ g_vars->scene04_var19 = 1;
+ break;
+
+ case MSG_SC4_DROPBOTTLE:
+ sceneHandler04_dropBottle();
+ break;
+
+ case MSG_SC4_COINOUT:
+ g_vars->scene04_clock->changeStatics2(ST_CLK_CLOSED);
+ g_vars->scene04_coinPut = 0;
+ sceneHandler04_stopSound();
+
+ if (g_vars->scene04_kozyawkiAni.size() && !g_vars->scene04_var02) {
+ g_vars->scene04_var09 = 1;
+
+ if (g_vars->scene04_var10)
+ sceneHandler04_sub1(0);
+
+ sceneHandler04_sub15();
+ }
+
+ break;
+
+ case MSG_SC4_KOZAWFALL:
+ {
+ ExCommand *exnew;
+
+ if (g_vars->scene04_var11) {
+ sceneHandler04_sub9(g_vars->scene04_var24);
+
+ g_vars->scene04_var11 = 0;
+
+ exnew = new ExCommand(0, 35, SND_4_010, 0, 0, 0, 1, 0, 0, 0);
+ } else {
+ exnew = new ExCommand(0, 35, SND_4_012, 0, 0, 0, 1, 0, 0, 0);
+ }
+
+ exnew->_field_14 = 5;
+ exnew->_excFlags |= 2;
+ exnew->postMessage();
+ break;
+ }
+
+ case MSG_SC4_MANFROMBOTTLE:
+ sceneHandler04_manFromBottle();
+ break;
+
+ case MSG_SC4_CLICKLADDER:
+ sceneHandler04_clickLadder();
+ break;
+
+ case MSG_SC4_MANTOBOTTLE:
+ sceneHandler04_manToBottle();
+ break;
+
+ case MSG_SHOWCOIN:
+ sceneHandler04_showCoin();
+ break;
+
+ case MSG_TAKEBOTTLE:
+ sceneHandler04_takeBottle();
+ break;
+
+ case MSG_GOTOLADDER:
+ sceneHandler04_gotoLadder(0);
+ break;
+
+ case MSG_SC4_COINPUT:
+ g_vars->scene04_coinPut = 1;
+ break;
+ }
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/sceneDbg.cpp b/engines/fullpipe/scenes/sceneDbg.cpp
new file mode 100644
index 0000000000..83f3b64ee5
--- /dev/null
+++ b/engines/fullpipe/scenes/sceneDbg.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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/input.h"
+
+#include "fullpipe/interaction.h"
+
+namespace Fullpipe {
+
+void sceneDbgMenu_initScene(Scene *sc) {
+ g_vars->selector = sc->getPictureObjectById(PIC_SCD_SEL, 0);
+ getGameLoaderInteractionController()->disableFlag24();
+ setInputDisabled(0);
+}
+
+GameObject *sceneHandlerDbgMenu_getObjectAtXY(int x, int y) {
+ if (g_fullpipe->_currentScene)
+ for (uint i = 0; i < g_fullpipe->_currentScene->_picObjList.size(); i++) {
+ PictureObject *pic = (PictureObject *)g_fullpipe->_currentScene->_picObjList[i];
+
+ if (x >= pic->_ox && y >= pic->_oy) {
+ Common::Point point;
+
+ pic->getDimensions(&point);
+
+ if (x <= pic->_ox + point.x && y <= pic->_oy + point.y && pic != g_vars->selector)
+ return pic;
+ }
+ }
+
+ return 0;
+}
+
+int sceneHandlerDbgMenu(ExCommand *ex) {
+ if (ex->_messageKind != 17)
+ return 0;
+
+ int mx = g_fullpipe->_mouseScreenPos.x + g_fullpipe->_sceneRect.left;
+ int my = g_fullpipe->_mouseScreenPos.y + g_fullpipe->_sceneRect.top;
+
+ if (ex->_messageNum == 29) {
+ GameObject *obj = sceneHandlerDbgMenu_getObjectAtXY(mx, my);
+ if (obj && canInteractAny(0, obj, -3) ) {
+ getGameLoaderInteractionController()->enableFlag24();
+ handleObjectInteraction(0, obj, 0);
+ }
+ return 0;
+ }
+ if (ex->_messageNum != 33) {
+ if (ex->_messageNum == MSG_RESTARTGAME) {
+ g_fullpipe->_needRestart = true;
+ return 0;
+ }
+ return 0;
+ }
+
+ g_fullpipe->_cursorId = PIC_CSR_DEFAULT;
+ GameObject *obj = g_fullpipe->_currentScene->getStaticANIObjectAtPos(mx, my);
+ if (obj) {
+ if (canInteractAny(0, obj, -3)) {
+ g_fullpipe->_cursorId = PIC_CSR_DEFAULT;
+ g_fullpipe->setCursor(PIC_CSR_DEFAULT);
+ return 0;
+ }
+ } else {
+ obj = sceneHandlerDbgMenu_getObjectAtXY(mx, my);
+ if (obj && canInteractAny(0, obj, -3) ) {
+ g_vars->selector->_flags |= 4;
+ g_vars->selector->setOXY(obj->_ox, obj->_oy);
+ g_fullpipe->_cursorId = PIC_CSR_DEFAULT;
+ g_fullpipe->setCursor(PIC_CSR_DEFAULT);
+ return 0;
+ }
+ g_vars->selector->_flags &= 0xFFFB;
+ }
+ g_fullpipe->setCursor(g_fullpipe->_cursorId);
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/sceneIntro.cpp b/engines/fullpipe/scenes/sceneIntro.cpp
new file mode 100644
index 0000000000..d60f90faf7
--- /dev/null
+++ b/engines/fullpipe/scenes/sceneIntro.cpp
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/constants.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/modal.h"
+#include "fullpipe/statics.h"
+
+namespace Fullpipe {
+
+int sceneIntro_updateCursor() {
+ g_fullpipe->_cursorId = 0;
+
+ return 0;
+}
+
+void sceneIntro_initScene(Scene *sc) {
+ g_fullpipe->_gameLoader->loadScene(SC_INTRO2);
+
+ g_vars->sceneIntro_aniin1man = sc->getStaticANIObject1ById(ANI_IN1MAN, -1);
+ g_vars->sceneIntro_needSleep = true;
+ g_vars->sceneIntro_needGetup = false;
+ g_vars->sceneIntro_playing = true;
+ g_vars->sceneIntro_needBlackout = false;
+
+ if (g_fullpipe->_recordEvents || g_fullpipe->_inputArFlag)
+ g_vars->sceneIntro_skipIntro = false;
+
+ g_fullpipe->_modalObject = new ModalIntro;
+}
+
+void sceneHandlerIntro_part1() {
+ g_fullpipe->_currentScene = g_fullpipe->accessScene(SC_INTRO1);
+ chainQueue(QU_INTR_FINISH, 0);
+}
+
+void sceneHandlerIntro_part2() {
+ g_fullpipe->_currentScene = g_fullpipe->accessScene(SC_INTRO2);
+ chainQueue(QU_IN2_DO, 0);
+}
+
+int sceneHandlerIntro(ExCommand *ex) {
+ if (ex->_messageKind != 17)
+ return 0;
+
+ switch (ex->_messageNum) {
+ case MSG_INTR_ENDINTRO:
+ g_vars->sceneIntro_playing = 0;
+ return 0;
+
+ case MSG_INTR_SWITCHTO1:
+ sceneHandlerIntro_part1();
+ return 0;
+
+ case MSG_INTR_GETUPMAN:
+ g_vars->sceneIntro_needSleep = 0;
+ g_vars->sceneIntro_needGetup = 1;
+ return 0;
+
+ case MSG_INTR_SWITCHTO2:
+ sceneHandlerIntro_part2();
+ return 0;
+
+ case 33:
+ // fall through
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (g_vars->sceneIntro_needSleep) {
+ if (!g_vars->sceneIntro_aniin1man->_movement && g_vars->sceneIntro_aniin1man->_statics->_staticsId == ST_IN1MAN_SLEEP)
+ g_vars->sceneIntro_aniin1man->startAnim(MV_IN1MAN_SLEEP, 0, -1);
+ } else if (g_vars->sceneIntro_needGetup && !g_vars->sceneIntro_aniin1man->_movement &&
+ g_vars->sceneIntro_aniin1man->_statics->_staticsId == ST_IN1MAN_SLEEP) {
+ g_vars->sceneIntro_needGetup = 0;
+
+ chainQueue(QU_INTR_GETUPMAN, 0);
+ }
+
+ g_fullpipe->startSceneTrack();
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp
new file mode 100644
index 0000000000..6da848a621
--- /dev/null
+++ b/engines/fullpipe/sound.cpp
@@ -0,0 +1,140 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/sound.h"
+#include "fullpipe/ngiarchive.h"
+
+namespace Fullpipe {
+
+SoundList::SoundList() {
+ _soundItems = 0;
+ _soundItemsCount = 0;
+ _libHandle = 0;
+}
+
+bool SoundList::load(MfcArchive &file, char *fname) {
+ debug(5, "SoundList::load()");
+
+ _soundItemsCount = file.readUint32LE();
+ _soundItems = (Sound **)calloc(_soundItemsCount, sizeof(Sound *));
+
+ if (fname) {
+ _libHandle = (NGIArchive *)makeNGIArchive(fname);
+ } else {
+ _libHandle = 0;
+ }
+
+ for (int i = 0; i < _soundItemsCount; i++) {
+ Sound *snd = new Sound();
+
+ _soundItems[i] = snd;
+ snd->load(file, _libHandle);
+ }
+
+ return true;
+
+}
+
+bool SoundList::loadFile(const char *fname, char *libname) {
+ Common::File file;
+
+ if (!file.open(fname))
+ return false;
+
+ MfcArchive archive(&file);
+
+ return load(archive, libname);
+}
+
+Sound::Sound() {
+ _id = 0;
+ _directSoundBuffer = 0;
+ _soundData = 0;
+ _objectId = 0;
+ memset(_directSoundBuffers, 0, sizeof(_directSoundBuffers));
+ _description = 0;
+}
+
+
+bool Sound::load(MfcArchive &file, NGIArchive *archive) {
+ debug(5, "Sound::load()");
+
+ MemoryObject::load(file);
+
+ _id = file.readUint32LE();
+ _description = file.readPascalString();
+
+ assert(g_fullpipe->_gameProjectVersion >= 6);
+
+ _objectId = file.readUint16LE();
+
+ if (archive && archive->hasFile(_memfilename)) {
+ Common::SeekableReadStream *s = archive->createReadStreamForMember(_memfilename);
+
+ _soundData = (byte *)calloc(s->size(), 1);
+
+ s->read(_soundData, s->size());
+
+ delete s;
+ }
+
+ return true;
+}
+
+void Sound::updateVolume() {
+ debug(3, "STUB Sound::updateVolume()");
+}
+
+void Sound::setPanAndVolumeByStaticAni() {
+ debug(3, "STUB Sound::setPanAndVolumeByStaticAni()");
+}
+
+void FullpipeEngine::setSceneMusicParameters(GameVar *var) {
+ warning("STUB: FullpipeEngine::setSceneMusicParameters()");
+}
+
+void FullpipeEngine::startSceneTrack() {
+ debug(3, "STUB: FullpipeEngine::startSceneTrack()");
+}
+
+void FullpipeEngine::stopAllSounds() {
+ warning("STUB: FullpipeEngine::stopAllSounds()");
+}
+
+void FullpipeEngine::toggleMute() {
+ warning("STUB: FullpipeEngine::toggleMute()");
+}
+
+void FullpipeEngine::playSound(int id, int flag) {
+ warning("STUB: FullpipeEngine::playSounds(%d, %d)", id, flag);
+}
+
+void global_messageHandler_handleSound(ExCommand *cmd) {
+ debug(0, "STUB: global_messageHandler_handleSound()");
+}
+
+
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/sound.h b/engines/fullpipe/sound.h
new file mode 100644
index 0000000000..e2b271fe2c
--- /dev/null
+++ b/engines/fullpipe/sound.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 FULLPIPE_SOUND_H
+#define FULLPIPE_SOUND_H
+
+namespace Fullpipe {
+
+class Sound : public MemoryObject {
+ int _id;
+ char *_description;
+ int16 _objectId;
+ int _directSoundBuffer;
+ int _directSoundBuffers[7];
+ byte *_soundData;
+
+ public:
+ Sound();
+ virtual bool load(MfcArchive &file, NGIArchive *archive);
+ virtual bool load(MfcArchive &file) { assert(0); return false; } // Disable base class
+ void updateVolume();
+
+ void setPanAndVolumeByStaticAni();
+};
+
+class SoundList : public CObject {
+ Sound **_soundItems;
+ int _soundItemsCount;
+ NGIArchive *_libHandle;
+
+ public:
+ SoundList();
+ virtual bool load(MfcArchive &file, char *fname);
+ virtual bool load(MfcArchive &file) { assert(0); return false; } // Disable base class
+ bool loadFile(const char *fname, char *libname);
+
+ int getCount() { return _soundItemsCount; }
+ Sound *getSoundByIndex(int idx) { return _soundItems[idx]; }
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_SOUND_H */
diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp
new file mode 100644
index 0000000000..747015e9a1
--- /dev/null
+++ b/engines/fullpipe/stateloader.cpp
@@ -0,0 +1,321 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "common/file.h"
+#include "common/array.h"
+#include "common/list.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/interaction.h"
+
+#include "fullpipe/constants.h"
+
+namespace Fullpipe {
+
+bool FullpipeEngine::loadGam(const char *fname, int scene) {
+ _gameLoader = new GameLoader();
+
+ if (!_gameLoader->loadFile(fname))
+ return false;
+
+ _currSoundListCount = 0;
+ initObjectStates();
+ // set_g_messageQueueCallback1(messageQueueCallback1); // substituted with direct call
+
+ addMessageHandlerByIndex(global_messageHandler1, 0, 4);
+
+ _inventory = getGameLoaderInventory();
+ _inventory->setItemFlags(ANI_INV_MAP, 0x10003);
+ _inventory->addItem(ANI_INV_MAP, 1);
+
+ _inventory->rebuildItemRects();
+
+ for (PtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) {
+ ((MemoryObject *)((PictureObject *)*p)->_picture)->load();
+ }
+
+ // _sceneSwitcher = sceneSwitcher; // substituted with direct call
+ _gameLoader->_preloadCallback = preloadCallback;
+ // _readSavegameCallback = gameLoaderReadSavegameCallback; // TODO
+
+ _aniMan = accessScene(SC_COMMON)->getAniMan();
+ _scene2 = 0;
+
+ _movTable = _aniMan->countMovements();
+
+ _aniMan->setSpeed(1);
+
+ PictureObject *pic = accessScene(SC_INV)->getPictureObjectById(PIC_INV_MENU, 0);
+
+ pic->setFlags(pic->_flags & 0xFFFB);
+
+ // Not used in full game
+ //_evalVersionPic = accessScene(SC_COMMON)->getPictureObjectById(PIC_CMN_EVAL, 0);
+
+ initMap();
+ initCursors();
+
+ setMusicAllowed(_gameLoader->_gameVar->getSubVarAsInt("MUSIC_ALLOWED"));
+
+ if (scene) {
+ _gameLoader->loadScene(scene);
+ _gameLoader->gotoScene(scene, TrubaLeft);
+ } else {
+ if (_flgPlayIntro) {
+ _gameLoader->loadScene(SC_INTRO1);
+ _gameLoader->gotoScene(SC_INTRO1, TrubaUp);
+ } else {
+ _gameLoader->loadScene(SC_1);
+ _gameLoader->gotoScene(SC_1, TrubaLeft);
+ }
+ }
+
+ if (!_currentScene)
+ return false;
+
+ return true;
+}
+
+GameProject::GameProject() {
+ _field_4 = 0;
+ _headerFilename = 0;
+ _field_10 = 12;
+
+ _sceneTagList = 0;
+}
+
+bool GameProject::load(MfcArchive &file) {
+ debug(5, "GameProject::load()");
+
+ _field_4 = 0;
+ _headerFilename = 0;
+ _field_10 = 12;
+
+ g_fullpipe->_gameProjectVersion = file.readUint32LE();
+ g_fullpipe->_pictureScale = file.readUint16LE();
+ g_fullpipe->_scrollSpeed = file.readUint32LE();
+
+ _headerFilename = file.readPascalString();
+
+ debug(1, "_gameProjectVersion = %d", g_fullpipe->_gameProjectVersion);
+ debug(1, "_pictureScale = %d", g_fullpipe->_pictureScale);
+ debug(1, "_scrollSpeed = %d", g_fullpipe->_scrollSpeed);
+ debug(1, "_headerFilename = %s", _headerFilename);
+
+ _sceneTagList = new SceneTagList();
+
+ _sceneTagList->load(file);
+
+ if (g_fullpipe->_gameProjectVersion >= 3)
+ _field_4 = file.readUint32LE();
+
+ if (g_fullpipe->_gameProjectVersion >= 5) {
+ file.readUint32LE();
+ file.readUint32LE();
+ }
+
+ return true;
+}
+
+GameProject::~GameProject() {
+ free(_headerFilename);
+}
+
+GameVar::GameVar() {
+ _subVars = 0;
+ _parentVarObj = 0;
+ _nextVarObj = 0;
+ _prevVarObj = 0;
+ _field_14 = 0;
+ _varType = 0;
+ _value.floatValue = 0;
+ _varName = 0;
+}
+
+bool GameVar::load(MfcArchive &file) {
+ _varName = file.readPascalString();
+ _varType = file.readUint32LE();
+
+ debugN(6, "[%03d] ", file.getLevel());
+ for (int i = 0; i < file.getLevel(); i++)
+ debugN(6, " ");
+
+ debugN(6, "<%s>: ", transCyrillic((byte *)_varName));
+
+ switch (_varType) {
+ case 0:
+ _value.intValue = file.readUint32LE();
+ debug(6, "d --> %d", _value.intValue);
+ break;
+ case 1:
+ _value.intValue = file.readUint32LE(); // FIXME
+ debug(6, "f --> %f", _value.floatValue);
+ break;
+ case 2:
+ _value.stringValue = file.readPascalString();
+ debug(6, "s --> %s", _value.stringValue);
+ break;
+ default:
+ error("Unknown var type: %d (0x%x)", _varType, _varType);
+ }
+
+ file.incLevel();
+ _parentVarObj = (GameVar *)file.readClass();
+ _prevVarObj = (GameVar *)file.readClass();
+ _nextVarObj = (GameVar *)file.readClass();
+ _field_14 = (GameVar *)file.readClass();
+ _subVars = (GameVar *)file.readClass();
+ file.decLevel();
+
+ return true;
+}
+
+GameVar *GameVar::getSubVarByName(const char *name) {
+ GameVar *sv = 0;
+
+ if (_subVars != 0) {
+ sv = _subVars;
+ for (;sv && scumm_stricmp(sv->_varName, name); sv = sv->_nextVarObj)
+ ;
+ }
+ return sv;
+}
+
+bool GameVar::setSubVarAsInt(const char *name, int value) {
+ GameVar *var = getSubVarByName(name);
+
+ if (var) {
+ if (var->_varType == 0) {
+ var->_value.intValue = value;
+
+ return true;
+ }
+ return false;
+ }
+
+ var = new GameVar();
+ var->_varType = 0;
+ var->_value.intValue = value;
+ var->_varName = (char *)calloc(strlen(name) + 1, 1);
+ strcpy(var->_varName, name);
+
+ return addSubVar(var);
+}
+
+int GameVar::getSubVarAsInt(const char *name) {
+ GameVar *var = getSubVarByName(name);
+
+ if (var)
+ return var->_value.intValue;
+ else
+ return 0;
+}
+
+GameVar *GameVar::addSubVarAsInt(const char *name, int value) {
+ if (getSubVarByName(name)) {
+ return 0;
+ } else {
+ GameVar *var = new GameVar();
+
+ var->_varType = 0;
+ var->_value.intValue = value;
+
+ var->_varName = (char *)calloc(strlen(name) + 1, 1);
+ strcpy(var->_varName, name);
+
+ return (addSubVar(var) != 0) ? var : 0;
+ }
+}
+
+bool GameVar::addSubVar(GameVar *subvar) {
+ GameVar *var = _subVars;
+
+ if (var) {
+ for (GameVar *i = var->_nextVarObj; i; i = i->_nextVarObj)
+ var = i;
+
+ var->_nextVarObj = subvar;
+ subvar->_prevVarObj = var;
+ subvar->_parentVarObj = this;
+
+ return true;
+ } else {
+ _subVars = subvar;
+ subvar->_parentVarObj = this;
+
+ return true;
+ }
+
+ return false;
+}
+
+int GameVar::getSubVarsCount() {
+ int res;
+ GameVar *sub = _subVars;
+
+ for (res = 0; sub; res++)
+ sub = sub->_nextVarObj;
+
+ return res;
+}
+
+GameVar *GameVar::getSubVarByIndex(int idx) {
+ GameVar *sub = _subVars;
+
+ while (idx--) {
+ sub = sub->_nextVarObj;
+
+ if (!sub)
+ return 0;
+ }
+
+ return sub;
+}
+
+bool PicAniInfo::load(MfcArchive &file) {
+ debug(5, "PicAniInfo::load()");
+
+ type = file.readUint32LE();
+ objectId = file.readUint16LE();
+ field_6 = file.readUint16LE();
+ field_8 = file.readUint32LE();
+ sceneId = file.readUint16LE();
+ field_E = file.readUint16LE();
+ ox = file.readUint32LE();
+ oy = file.readUint32LE();
+ priority = file.readUint32LE();
+ staticsId = file.readUint16LE();
+ movementId = file.readUint16LE();
+ dynamicPhaseIndex = file.readUint16LE();
+ flags = file.readUint16LE();
+ field_24 = file.readUint32LE();
+ someDynamicPhaseIndex = file.readUint32LE();
+
+ return true;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp
new file mode 100644
index 0000000000..b82875f638
--- /dev/null
+++ b/engines/fullpipe/statics.cpp
@@ -0,0 +1,1910 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/ngiarchive.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/interaction.h"
+
+#include "fullpipe/constants.h"
+#include "fullpipe/objectnames.h"
+
+namespace Fullpipe {
+
+StepArray::StepArray() {
+ _points = 0;
+ _maxPointIndex = 0;
+ _currPointIndex = 0;
+ _pointsCount = 0;
+ _isEos = 0;
+}
+
+StepArray::~StepArray() {
+ if (_pointsCount) {
+ for (int i = 0; i < _pointsCount; i++)
+ delete _points[i];
+
+ delete _points;
+
+ _points = 0;
+ }
+}
+
+void StepArray::clear() {
+ _currPointIndex = 0;
+ _maxPointIndex = 0;
+ _isEos = 0;
+
+ for (int i = 0; i < _pointsCount; i++) {
+ _points[i]->x = 0;
+ _points[i]->y = 0;
+ }
+}
+
+Common::Point *StepArray::getCurrPoint(Common::Point *point) {
+ if (_isEos || _points == 0) {
+ point->x = 0;
+ point->y = 0;
+ } else {
+ point = _points[_currPointIndex];
+ }
+ return point;
+}
+
+Common::Point *StepArray::getPoint(Common::Point *point, int index, int offset) {
+ if (index == -1)
+ index = _currPointIndex;
+
+ if (index + offset > _maxPointIndex - 1)
+ offset = _maxPointIndex - index;
+
+ point->x = 0;
+ point->y = 0;
+
+ while (offset >= 1) {
+ point->x += _points[index]->x;
+ point->y += _points[index]->y;
+
+ index++;
+ offset--;
+ }
+
+ return point;
+}
+
+bool StepArray::gotoNextPoint() {
+ if (_currPointIndex < _maxPointIndex) {
+ _currPointIndex++;
+ return true;
+ } else {
+ _isEos = 1;
+ return false;
+ }
+}
+
+StaticANIObject::StaticANIObject() {
+ _shadowsOn = 1;
+ _field_30 = 0;
+ _field_34 = 1;
+ _initialCounter = 0;
+ _messageQueueId = 0;
+ _animExFlag = 0;
+ _counter = 0;
+ _movement = 0;
+ _statics = 0;
+ _flags = 0;
+ _callback1 = 0;
+ _callback2 = 0;
+ _sceneId = -1;
+ _someDynamicPhaseIndex = -1;
+
+ _field_32 = 0;
+ _field_96 = 0;
+ _messageNum = 0;
+ _objtype = kObjTypeStaticANIObject;
+}
+
+StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) {
+ _shadowsOn = src->_shadowsOn;
+ _field_30 = src->_field_30;
+ _field_34 = 1;
+ _initialCounter = 0;
+
+ _field_32 = 0;
+ _field_96 = 0;
+ _messageNum = 0;
+
+ _messageQueueId = 0;
+ _animExFlag = 0;
+ _counter = 0;
+ _someDynamicPhaseIndex = -1;
+ _sceneId = src->_sceneId;
+ _callback1 = src->_callback1;
+ _callback2 = src->_callback2;
+ _objtype = kObjTypeStaticANIObject;
+
+ for (uint i = 0; i < src->_staticsList.size(); i++)
+ _staticsList.push_back(new Statics((Statics *)src->_staticsList[i], 0));
+
+ _movement = 0;
+ _statics = 0;
+
+ for (uint i = 0; i < src->_movements.size(); i++) {
+ Movement *newmov;
+ Movement *mov = (Movement *)src->_movements[i];
+
+ if (mov->_currMovement) {
+ // WORKAROUND: Original uses weird construction here:
+ // new Movement(getMovementById(src->getMovementIdById(mov->_id)), this);
+ newmov = new Movement(src->getMovementById(src->getMovementIdById(mov->_id)), this);
+ newmov->_id = mov->_id;
+ } else {
+ newmov = new Movement(mov, 0, -1, this);
+ }
+
+ _movements.push_back(newmov);
+ }
+}
+
+bool StaticANIObject::load(MfcArchive &file) {
+ debug(5, "StaticANIObject::load()");
+
+ GameObject::load(file);
+
+ int count = file.readUint16LE();
+
+ for (int i = 0; i < count; i++) {
+ Statics *st = new Statics();
+
+ st->load(file);
+ _staticsList.push_back(st);
+ }
+
+ count = file.readUint16LE();
+ debug(7, "Movements: %d", count);
+
+ for (int i = 0; i < count; i++) {
+ int movNum = file.readUint16LE();
+
+ char *movname = genFileName(_id, movNum, "mov");
+
+ Common::SeekableReadStream *f = g_fullpipe->_currArchive->createReadStreamForMember(movname);
+
+ Movement *mov = new Movement();
+
+ MfcArchive archive(f);
+
+ mov->load(archive, this);
+
+ _movements.push_back(mov);
+
+ delete f;
+ free(movname);
+ }
+
+ Common::Point pt;
+ if (count) { // We have movements
+ ((Movement *)_movements[0])->getCurrDynamicPhaseXY(pt);
+ } else {
+ pt.x = pt.y = 100;
+ }
+
+ setOXY(pt.x, pt.y);
+
+ return true;
+}
+
+void StaticANIObject::setOXY(int x, int y) {
+ _ox = x;
+ _oy = y;
+
+ if (_movement)
+ _movement->setOXY(x, y);
+}
+
+void StaticANIObject::clearFlags() {
+ _flags = 0;
+
+ deleteFromGlobalMessageQueue();
+ _messageQueueId = 0;
+ _movement = 0;
+ _statics = 0;
+ _animExFlag = 0;
+ _counter = 0;
+ _messageNum = 0;
+ _stepArray.clear();
+}
+
+void StaticANIObject::setFlags40(bool state) {
+ if (state) {
+ _flags |= 0x40;
+ } else {
+ if (_flags & 0x40)
+ _flags ^= 0x40;
+ }
+}
+
+void StaticANIObject::deleteFromGlobalMessageQueue() {
+ while (_messageQueueId) {
+ if (g_fullpipe->_globalMessageQueueList->getMessageQueueById(_messageQueueId)) {
+ if (!isIdle())
+ return;
+
+ g_fullpipe->_globalMessageQueueList->deleteQueueById(_messageQueueId);
+ } else {
+ _messageQueueId = 0;
+ }
+ }
+}
+
+void StaticANIObject::queueMessageQueue(MessageQueue *mq) {
+ if (isIdle() && !(_flags & 0x80)) {
+ deleteFromGlobalMessageQueue();
+ _messageQueueId = 0;
+ _messageNum = 0;
+
+ if (_flags & 2)
+ _flags ^= 2;
+
+ if (mq) {
+ _animExFlag = 0;
+ if (_movement)
+ _messageQueueId = mq->_id;
+ else
+ mq->sendNextCommand();
+ } else {
+ _messageQueueId = 0;
+ }
+ }
+}
+
+MessageQueue *StaticANIObject::getMessageQueue() {
+ if (this->_messageQueueId <= 0)
+ return 0;
+
+ return g_fullpipe->_globalMessageQueueList->getMessageQueueById(_messageQueueId);
+}
+
+bool StaticANIObject::trySetMessageQueue(int msgNum, int qId) {
+ if (_messageQueueId || !msgNum) {
+ updateGlobalMessageQueue(qId, _id);
+ return false;
+ }
+
+ _flags |= 2;
+
+ _messageNum = msgNum;
+ _messageQueueId = qId;
+
+ return true;
+}
+
+bool StaticANIObject::isIdle() {
+ if (_messageQueueId) {
+ MessageQueue *m = g_fullpipe->_globalMessageQueueList->getMessageQueueById(_messageQueueId);
+
+ if (m && m->getFlags() & 1)
+ return false;
+ }
+
+ return true;
+}
+
+Statics *StaticANIObject::getStaticsById(int itemId) {
+ for (uint i = 0; i < _staticsList.size(); i++)
+ if (((Statics *)_staticsList[i])->_staticsId == itemId)
+ return (Statics *)_staticsList[i];
+
+ return 0;
+}
+
+Statics *StaticANIObject::getStaticsByName(char *name) {
+ for (uint i = 0; i < _staticsList.size(); i++)
+ if (!strcmp(((Statics *)_staticsList[i])->_staticsName, name))
+ return (Statics *)_staticsList[i];
+
+ return 0;
+}
+
+Movement *StaticANIObject::getMovementById(int itemId) {
+ for (uint i = 0; i < _movements.size(); i++)
+ if (((Movement *)_movements[i])->_id == itemId)
+ return (Movement *)_movements[i];
+
+ return 0;
+}
+
+int StaticANIObject::getMovementIdById(int itemId) {
+ for (uint i = 0; i < _movements.size(); i++) {
+ Movement *mov = (Movement *)_movements[i];
+ if (mov->_currMovement) {
+ if (mov->_id == itemId)
+ return mov->_id;
+ if (mov->_currMovement->_id == itemId)
+ return mov->_id;
+ }
+ }
+
+ return 0;
+}
+
+Movement *StaticANIObject::getMovementByName(char *name) {
+ for (uint i = 0; i < _movements.size(); i++)
+ if (!strcmp(((Movement *)_movements[i])->_objectName, name))
+ return (Movement *)_movements[i];
+
+ return 0;
+}
+
+bool StaticANIObject::getPixelAtPos(int x, int y, int *pixel) {
+ bool res = false;
+ Picture *pic;
+
+ if (_movement)
+ pic = _movement->_currDynamicPhase;
+ else
+ pic = _statics;
+
+ if (!pic)
+ return false;
+
+ int ongoing;
+ int xani, yani;
+ int oxani, oyani;
+ Common::Point point;
+
+ if (_movement)
+ ongoing = _movement->_currMovement != 0;
+ else
+ ongoing = _statics->_staticsId & 0x4000;
+
+ if (_movement) {
+ _movement->getCurrDynamicPhaseXY(point);
+ xani = point.x;
+ yani = point.y;
+ oxani = _movement->_ox;
+ oyani = _movement->_oy;
+ } else {
+ _statics->getSomeXY(point);
+ xani = point.x;
+ yani = point.y;
+ oxani = _ox;
+ oyani = _oy;
+ }
+
+ int xtarget = x - (oxani - xani);
+ int ytarget = y - (oyani - yani);
+
+ if (ongoing && _movement)
+ xtarget = pic->getDimensions(&point)->x - xtarget;
+
+ x = pic->_x;
+ y = pic->_y;
+ pic->_x = 0;
+ pic->_y = 0;
+ if (pic->isPixelHitAtPos(xtarget, ytarget)) {
+ *pixel = pic->getPixelAtPos(xtarget, ytarget);
+
+ res = true;
+ } else {
+ res = false;
+ }
+ pic->_x = x;
+ pic->_y = y;
+
+ return res;
+}
+
+void Movement::draw(bool flipFlag, int angle) {
+ debug(3, "Movement::draw(%d, %d)", flipFlag, angle);
+
+ Common::Point point;
+
+ getCurrDynamicPhaseXY(point);
+
+ int x = _ox - point.x;
+ int y = _oy - point.y;
+
+ if (_currDynamicPhase->getPaletteData())
+ g_fullpipe->_globalPalette = _currDynamicPhase->getPaletteData();
+
+ if (_currDynamicPhase->getAlpha() < 0xFF) {
+ warning("Movement::draw: alpha < 0xff: %d", _currDynamicPhase->getAlpha());
+ //vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, _currDynamicPhase->getAlpha());
+ }
+
+ Bitmap *bmp;
+ if (_currMovement) {
+ bmp = _currDynamicPhase->getPixelData()->reverseImage();
+ } else {
+ bmp = _currDynamicPhase->getPixelData();
+ }
+
+ if (flipFlag) {
+ bmp->flipVertical()->drawShaded(1, x, y + 30 + _currDynamicPhase->_rect->bottom, _currDynamicPhase->_paletteData);
+ } if (angle) {
+ bmp->drawRotated(x, y, angle, _currDynamicPhase->_paletteData);
+ } else {
+ bmp->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ }
+
+ if (_currDynamicPhase->_rect->top) {
+ if (!_currDynamicPhase->_convertedBitmap) {
+ //v12 = Picture_getPixelData(v5);
+ //v13 = Bitmap_convertTo16Bit565(v12, (unsigned int *)&_currDynamicPhase->rect);
+ //_currDynamicPhase->convertedBitmap = v13;
+ }
+
+ if (_currDynamicPhase->_convertedBitmap) {
+ if (_currMovement) {
+ //vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, LOBYTE(_currDynamicPhase->rect.top));
+ _currDynamicPhase->_convertedBitmap->reverseImage()->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ //vrtSetAlphaBlendMode(g_vrtDrawHandle, 0, 255);
+ } else {
+ //vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, LOBYTE(_currDynamicPhase->rect.top));
+ _currDynamicPhase->_convertedBitmap->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ //vrtSetAlphaBlendMode(g_vrtDrawHandle, 0, 255);
+ }
+ }
+ }
+}
+
+
+void StaticANIObject::loadMovementsPixelData() {
+ for (uint i = 0; i < _movements.size(); i++)
+ ((Movement *)_movements[i])->loadPixelData();
+}
+
+Statics *StaticANIObject::addReverseStatics(Statics *st) {
+ Statics *res = getStaticsById(st->_staticsId ^ 0x4000);
+
+ if (!res) {
+ res = new Statics(st, true);
+
+ _staticsList.push_back(res);
+ }
+
+ return res;
+}
+
+void StaticANIObject::draw() {
+ if ((_flags & 4) == 0)
+ return;
+
+ Common::Point point;
+ Common::Rect rect;
+
+ debug(0, "StaticANIObject::draw() (%s) [%d] [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy);
+
+ if (_shadowsOn && g_fullpipe->_currentScene && g_fullpipe->_currentScene->_shadows
+ && (getCurrDimensions(point)->x != 1 || getCurrDimensions(point)->y != 1)) {
+
+ DynamicPhase *dyn;
+
+ if (!_movement || _flags & 0x20)
+ dyn = _statics;
+ else
+ dyn = _movement->_currDynamicPhase;
+
+ if (!dyn) {
+ warning("HACK: StaticANIObject::draw(): dyn is missing");
+ return;
+ }
+
+ if (dyn->getDynFlags() & 4) {
+ rect = *dyn->_rect;
+
+ DynamicPhase *shd = g_fullpipe->_currentScene->_shadows->findSize(rect.width(), rect.height());
+ if (shd) {
+ shd->getDimensions(&point);
+ int midx = _ox - point.x / 2 - dyn->_someX;
+ int midy = _oy - point.y / 2 - dyn->_someY + rect.bottom - 3;
+ int shdw = point.y;
+
+ int px;
+ if (!_movement || (_flags & 0x20))
+ px = _statics->getCenter(&point)->x;
+ else
+ px = _movement->getCenter(&point)->x;
+
+ if (_shadowsOn != 1)
+ midy = _shadowsOn - shdw / 2;
+
+ shd->draw(px + midx, midy, 0, 0);
+ }
+ }
+ }
+
+ int angle = 0;
+ if (_field_30 & 0xC000) {
+ if (_field_30 & 0x8000)
+ angle = -(_field_30 ^ 0x8000);
+ else
+ angle = _field_30 ^ 0x4000;
+ }
+
+ if (!_movement || (_flags & 0x20)) {
+ _statics->getSomeXY(point);
+ _statics->_x = _ox - point.x;
+ _statics->_y = _oy - point.y;
+ _statics->draw(_statics->_x, _statics->_y, 0, angle);
+ } else {
+ _movement->draw(0, angle);
+ }
+}
+
+void StaticANIObject::draw2() {
+ debug(0, "StatciANIObject::draw2(): id: (%s) %d [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy);
+
+ if ((_flags & 4) && (_flags & 0x10)) {
+ if (_movement) {
+ _movement->draw(1, 0);
+ } else {
+ Common::Point point;
+
+ _statics->getSomeXY(point);
+
+ _statics->draw(_ox - point.x, _oy - point.y, 1, 0);
+ }
+ }
+}
+
+MovTable *StaticANIObject::countMovements() {
+ GameVar *preloadSubVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("PRELOAD");
+
+ if (!preloadSubVar || preloadSubVar->getSubVarsCount() == 0)
+ return 0;
+
+ MovTable *movTable = new MovTable;
+
+ movTable->count = _movements.size();
+ movTable->movs = (int16 *)calloc(_movements.size(), sizeof(int16));
+
+ for (uint i = 0; i < _movements.size(); i++) {
+ GameObject *obj = (GameObject *)_movements[i];
+ movTable->movs[i] = 2;
+
+ for (GameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) {
+ if (scumm_stricmp(obj->getName(), sub->_varName) == 0) {
+ movTable->movs[i] = 1;
+ break;
+ }
+ }
+ }
+
+ return movTable;
+}
+
+void StaticANIObject::setSpeed(int speed) {
+ GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("SpeedUp");
+
+ if (!var)
+ return;
+
+ for (var = var->_subVars; var; var = var->_nextVarObj) {
+ Movement *mov = getMovementById(var->_value.intValue);
+
+ if (mov) {
+ if (speed) {
+ if (mov->_counterMax == 83)
+ mov->_counterMax = 41;
+ } else if (mov->_counterMax == 41) {
+ mov->_counterMax = 83;
+ }
+ }
+ }
+
+}
+
+void StaticANIObject::setAlpha(int alpha) {
+ for (uint i = 0; i < _movements.size(); i++)
+ ((Movement *)_movements[i])->setAlpha(alpha);
+
+ for (uint i = 0; i < _staticsList.size(); i++)
+ ((Statics *)_staticsList[i])->setAlpha(alpha);
+}
+
+void StaticANIObject::initMovements() {
+ for (uint i = 0; i < _movements.size(); i++)
+ ((Movement *)_movements[i])->removeFirstPhase();
+}
+
+Common::Point *StaticANIObject::getCurrDimensions(Common::Point &p) {
+ Picture *pic;
+
+ if (_movement)
+ pic = _movement->_currDynamicPhase;
+ else
+ pic = _statics;
+
+ if (pic) {
+ Common::Point point;
+
+ pic->getDimensions(&point);
+ p.x = point.x;
+ p.y = point.y;
+ } else {
+ p.x = 0;
+ p.y = 0;
+ }
+
+ return &p;
+}
+
+Common::Point *StaticANIObject::getSomeXY(Common::Point &p) {
+ if (_movement) {
+ _movement->getCurrDynamicPhaseXY(p);
+
+ return &p;
+ }
+
+ if (_statics)
+ _statics->getSomeXY(p);
+
+ return &p;
+}
+
+void StaticANIObject::update(int counterdiff) {
+ int mqid;
+
+ debug(6, "StaticANIObject::update() (%s) [%d] [%d, %d] fl: %x", transCyrillic((byte *)_objectName), _id, _ox, _oy, _flags);
+
+ if (_flags & 2) {
+ _messageNum--;
+ if (_messageNum)
+ return;
+
+ mqid = _messageQueueId;
+ _messageQueueId = 0;
+ _flags ^= 2;
+
+ updateGlobalMessageQueue(mqid, _id);
+ return;
+ }
+
+ Common::Point point;
+ ExCommand *ex, *newex;
+
+ if (_movement) {
+ _movement->_counter += counterdiff;
+
+ if (_movement->_counter < _movement->_counterMax)
+ return;
+
+ _movement->_counter = 0;
+
+ if (_flags & 1) {
+ if (_counter) {
+ _counter--;
+
+ return;
+ }
+
+ DynamicPhase *dyn = _movement->_currDynamicPhase;
+ if (dyn->_initialCountdown == dyn->_countdown) {
+
+ ex = dyn->getExCommand();
+ if (ex && ex->_messageKind != 35) {
+ newex = new ExCommand(ex);
+ newex->_excFlags |= 2;
+ if (newex->_messageKind == 17) {
+ newex->_parentId = _id;
+ newex->_keyCode = _okeyCode;
+ }
+ newex->sendMessage();
+
+ if (!_movement)
+ return;
+ }
+ }
+
+ if (dyn->_initialCountdown != dyn->_countdown || dyn->_field_68 == 0) {
+ newex = new ExCommand(_id, 17, dyn->_field_68, 0, 0, 0, 1, 0, 0, 0);
+ newex->_excFlags = 2;
+ newex->_keyCode = _okeyCode;
+ newex->sendMessage();
+
+ if (!_movement)
+ return;
+ }
+
+ if (!_movement->gotoNextFrame(_callback1, _callback2)) {
+ stopAnim_maybe();
+ } else {
+ setOXY(_movement->_ox, _movement->_oy);
+ _counter = _initialCounter;
+
+ if (dyn->_initialCountdown == dyn->_countdown) {
+ ex = dyn->getExCommand();
+ if (ex) {
+ if (ex->_messageKind == 35) {
+ newex = new ExCommand(ex);
+ newex->_excFlags |= 2;
+ newex->sendMessage();
+ }
+ }
+ }
+ if (!_movement)
+ return;
+
+ _stepArray.getCurrPoint(&point);
+ setOXY(point.x + _ox, point.y + _oy);
+ _stepArray.gotoNextPoint();
+ if (_someDynamicPhaseIndex == _movement->_currDynamicPhaseIndex)
+ adjustSomeXY();
+ }
+ } else if (_flags & 0x20) {
+ _flags ^= 0x20;
+ _flags |= 1;
+
+ _movement->gotoFirstFrame();
+ _movement->getCurrDynamicPhaseXY(point);
+
+ Common::Point pointS;
+ _statics->getSomeXY(pointS);
+ _movement->setOXY(_ox + point.x + _movement->_mx - pointS.x,
+ _oy + point.y + _movement->_my - pointS.y);
+ }
+ } else {
+ if (_statics) {
+ if (_messageQueueId) {
+ if (_statics->_countdown) {
+ _statics->_countdown--;
+ return;
+ }
+ mqid = _messageQueueId;
+ _messageQueueId = 0;
+ updateGlobalMessageQueue(mqid, _id);
+ }
+ }
+ }
+}
+
+void StaticANIObject::updateStepPos() {
+ Common::Point point;
+
+ int ox = _movement->_ox;
+ int oy = _movement->_oy;
+
+ _movement->calcSomeXY(point, 1);
+ int x = point.x;
+ int y = point.y;
+
+ _stepArray.getPoint(&point, -1, _stepArray.getPointsCount());
+ x += point.x;
+ y += point.y;
+
+ _statics = _movement->_staticsObj2;
+ _movement = 0;
+
+ setOXY(ox + x, oy + y);
+}
+
+void StaticANIObject::stopAnim_maybe() {
+ debug(6, "StaticANIObject::stopAnim_maybe()");
+
+ if (!(_flags & 1))
+ return;
+
+ _flags ^= 1;
+
+ int oid = 0;
+ int oldmqid = _messageQueueId;
+ Common::Point point;
+
+ if (_movement) {
+ setOXY(_movement->_ox, _movement->_oy);
+
+ if (_flags & 0x40) {
+ if (!_movement->_currMovement && !_movement->_currDynamicPhaseIndex) {
+ _statics = _movement->_staticsObj1;
+ _movement->getCurrDynamicPhaseXY(point);
+ _ox -= point.x;
+ _oy -= point.y;
+
+ _ox -= _movement->_mx;
+ _oy -= _movement->_my;
+
+ _statics->getSomeXY(point);
+ if (_movement->_currMovement) {
+ _oy += point.y;
+ _ox -= point.x;
+ _ox += _statics->getDimensions(&point)->x;
+ } else {
+ _ox += point.x;
+ _oy += point.y;
+ }
+ }
+ }
+
+ if (_movement->_currDynamicPhaseIndex || !(_flags & 0x40))
+ _statics = _movement->_staticsObj2;
+
+ _statics->getSomeXY(point);
+
+ _statics->_x = _ox - point.x;
+ _statics->_y = _oy - point.y;
+ oid = _movement->_id;
+ _movement = 0;
+
+ ExCommand *ex = new ExCommand(_id, 17, 24, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _okeyCode;
+ ex->_excFlags = 2;
+ ex->postMessage();
+ }
+
+ int mqid = _messageQueueId;
+
+ if (_animExFlag) {
+ _messageQueueId = 0;
+ startAnimEx(oid, mqid, -1, -1);
+ } else {
+ if (_messageQueueId == oldmqid) {
+ _messageQueueId = 0;
+ if (_field_34 == 1)
+ updateGlobalMessageQueue(mqid, _id);
+ }
+ }
+}
+
+void StaticANIObject::adjustSomeXY() {
+ warning("STUB: StaticANIObject::adjustSomeXY()");
+}
+
+MessageQueue *StaticANIObject::changeStatics1(int msgNum) {
+ warning("STUB: StaticANIObject::changeStatics1(%d)", msgNum);
+
+ return 0;
+}
+
+void StaticANIObject::changeStatics2(int objId) {
+ warning("STUB: StaticANIObject::changeStatics2(%d)", objId);
+}
+
+void StaticANIObject::hide() {
+ if (!_messageQueueId) {
+ if (_flags & 4)
+ _flags ^= 4;
+ }
+}
+
+void StaticANIObject::show1(int x, int y, int movId, int mqId) {
+ debug(0, "StaticANIObject::show1(%d, %d, %d, %d)", x, y, movId, mqId);
+
+ if (_messageQueueId)
+ return;
+
+ if (movId == -1) {
+ _flags |= 4u;
+ if (x != -1 && y != -1) {
+ setOXY(x, y);
+ }
+
+ return;
+ }
+
+ Movement *mov = getMovementById(movId);
+ if (!mov)
+ return;
+
+ if (x != -1 && y != -1) {
+ setOXY(x, y);
+ }
+
+ _statics = mov->_staticsObj1;
+
+ Common::Point point;
+
+ mov->_staticsObj1->getSomeXY(point);
+ _statics->_x = x - point.x;
+ _statics->_y = y - point.y;
+
+ _statics->_countdown = _statics->_initialCountdown;
+
+ _flags |= 4;
+ _ox = x;
+ _oy = y;
+ _movement = 0;
+
+ if (mov->_currMovement)
+ _flags |= 8;
+ else if (_flags & 8)
+ _flags ^= 8;
+
+ if (_flags & 1)
+ _flags ^= 1;
+
+ _messageQueueId = mqId;
+}
+
+void StaticANIObject::show2(int x, int y, int movementId, int mqId) {
+ warning("STUB: StaticANIObject::show2(%d, %d, %d, %d)", x, y, movementId, mqId);
+}
+
+void StaticANIObject::playIdle() {
+ if (isIdle())
+ adjustSomeXY();
+}
+
+void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x, int y, Common::Point **points, int pointsCount, int someDynamicPhaseIndex) {
+ warning("STUB: StaticANIObject::startAnimSteps()");
+}
+
+bool StaticANIObject::startAnimEx(int movid, int parId, int flag1, int flag2) {
+ bool res = startAnim(movid, parId, -1);
+ if (res)
+ _animExFlag = 1;
+
+ _someDynamicPhaseIndex = -1;
+ return res;
+}
+
+bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhaseIdx) {
+ if (_flags & 0x80)
+ return false;
+
+ debug(0, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy);
+
+ if (_messageQueueId) {
+ updateGlobalMessageQueue(messageQueueId, _id);
+ return false;
+ }
+
+ Movement *mov = 0;
+
+ for (uint i = 0; i < _movements.size(); i++) {
+
+ if (((Movement *)_movements[i])->_id == movementId) {
+ mov = (Movement *)_movements[i];
+ break;
+ }
+ }
+
+ if (!mov) {
+ updateGlobalMessageQueue(messageQueueId, _id);
+ return false;
+ }
+
+ if (mov == _movement) {
+ _flags |= 1;
+ _messageQueueId = messageQueueId;
+
+ return true;
+ }
+
+ int newx = _ox;
+ int newy = _oy;
+ Common::Point point;
+
+ debug(0, "0 %d %d", newx, newy);
+ if (_movement) {
+ _movement->getCurrDynamicPhaseXY(point);
+
+ newx -= point.x;
+ newy -= point.y;
+
+ debug(0, "1 %d %d", newx, newy);
+ } else if (_statics) {
+ _statics->getSomeXY(point);
+
+ newx -= point.x;
+ newy -= point.y;
+ debug(0, "2 %d %d - %d %d assa", newx, newy, point.x, point.y);
+ }
+
+ _movement = mov;
+
+ _stepArray.clear();
+
+ if (_flags & 0x40)
+ _movement->gotoLastFrame();
+ else
+ _movement->gotoFirstFrame();
+
+ if (!(_flags & 0x40)) {
+ if (!_movement->_currDynamicPhaseIndex) {
+ _stepArray.getCurrPoint(&point);
+ newx += point.x + _movement->_mx;
+ newy += point.y + _movement->_my;
+
+ debug(0, "3 %d %d", newx, newy);
+ _stepArray.gotoNextPoint();
+
+ ExCommand *ex = _movement->_currDynamicPhase->getExCommand();
+ if (ex) {
+ if (ex->_messageKind == 35) {
+ ExCommand *newex = new ExCommand(ex);
+ newex->_excFlags |= 2;
+ newex->sendMessage();
+ }
+ }
+ }
+ }
+
+ _movement->getCurrDynamicPhaseXY(point);
+ setOXY(point.x + newx, point.y + newy);
+
+ if (_movement->_staticsObj2->_staticsId & 0x4000)
+ _flags |= 8;
+ else
+ _flags &= 0xFFF7;
+
+ _flags |= 1;
+
+ _messageQueueId = messageQueueId;
+ _movement->_currDynamicPhase->_countdown = _movement->_currDynamicPhase->_initialCountdown;
+ _movement->_counter = 0;
+
+ _counter = _initialCounter;
+ _someDynamicPhaseIndex = dynPhaseIdx;
+
+ _stepArray.clear();
+
+ ExCommand *newex = new ExCommand(_id, 17, 23, 0, 0, movementId, 1, 0, 0, 0);
+
+ newex->_keyCode = _okeyCode;
+ newex->_excFlags = 2;
+
+ newex->postMessage();
+
+ return true;
+}
+
+Statics::Statics() {
+ _staticsId = 0;
+ _picture = 0;
+ _staticsName = 0;
+}
+
+Statics::~Statics() {
+ delete _picture;
+ free(_staticsName);
+}
+
+Statics::Statics(Statics *src, bool reverse) : DynamicPhase(src, reverse) {
+ _staticsId = src->_staticsId;
+
+ if (reverse) {
+ _staticsId ^= 0x4000;
+ int newlen = strlen(src->_staticsName) + strlen(sO_MirroredTo) + 1;
+ _staticsName = (char *)calloc(newlen, 1);
+
+ snprintf(_staticsName, newlen, "%s%s", sO_MirroredTo, src->_staticsName);
+ } else {
+ _staticsName = (char *)calloc(strlen(src->_staticsName) + 1, 1);
+ strncpy(_staticsName, src->_staticsName, strlen(src->_staticsName) + 1);
+ }
+
+ _memfilename = (char *)calloc(strlen(src->_memfilename) + 1, 1);
+ strncpy(_memfilename, src->_memfilename, strlen(src->_memfilename) + 1);
+
+ _picture = new Picture();
+}
+
+bool Statics::load(MfcArchive &file) {
+ debug(5, "Statics::load()");
+
+ DynamicPhase::load(file);
+
+ _staticsId = file.readUint16LE();
+
+ _staticsName = file.readPascalString();
+ debug(7, "statics: <%s> id: %d (%x)", transCyrillic((byte *)_staticsName), _staticsId, _staticsId);
+
+ _picture = new Picture();
+ _picture->load(file);
+
+ return true;
+}
+
+Common::Point *Statics::getSomeXY(Common::Point &p) {
+ p.x = _someX;
+ p.y = _someY;
+
+ return &p;
+}
+
+Common::Point *Statics::getCenter(Common::Point *p) {
+ Common::Rect rect;
+
+ rect = *_rect;
+
+ if (_staticsId & 0x4000) {
+ Common::Point point;
+
+ getDimensions(&point);
+ rect.moveTo(point.x - _rect->right, _rect->top);
+ }
+
+ p->x = rect.left + _rect->width() / 2;
+ p->y = rect.top + _rect->height() / 2;
+
+ return p;
+}
+
+Movement::Movement() {
+ _lastFrameSpecialFlag = 0;
+ _flipFlag = 0;
+ _updateFlag1 = 0;
+ _staticsObj1 = 0;
+ _staticsObj2 = 0;
+ _mx = 0;
+ _my = 0;
+ _m2x = 0;
+ _m2y = 0;
+ _field_50 = 1;
+ _field_78 = 0;
+ _framePosOffsets = 0;
+ _field_84 = 0;
+ _currDynamicPhase = 0;
+ _field_8C = 0;
+ _currDynamicPhaseIndex = 0;
+ _field_94 = 0;
+ _currMovement = 0;
+ _counter = 0;
+ _counterMax = 83;
+
+ _somePoint.x = 0;
+ _somePoint.y = 0;
+}
+
+Movement::Movement(Movement *src, StaticANIObject *ani) {
+ _lastFrameSpecialFlag = 0;
+ _flipFlag = src->_flipFlag;
+ _updateFlag1 = src->_updateFlag1;
+ _staticsObj1 = 0;
+ _staticsObj2 = 0;
+ _mx = 0;
+ _my = 0;
+ _m2x = 0;
+ _m2y = 0;
+
+ _field_78 = 0;
+ _framePosOffsets = 0;
+ _field_84 = 0;
+ _currDynamicPhase = 0;
+ _field_8C = 0;
+ _currDynamicPhaseIndex = src->_currDynamicPhaseIndex;
+ _field_94 = 0;
+
+ _somePoint.x = 0;
+ _somePoint.y = 0;
+
+ _currMovement = src;
+ _ox = src->_ox;
+ _oy = src->_oy;
+
+ initStatics(ani);
+
+ _counterMax = src->_counterMax;
+ _counter = src->_counter;
+ _field_50 = src->_field_50;
+
+ updateCurrDynamicPhase();
+}
+
+Movement::Movement(Movement *src, int *oldIdxs, int newSize, StaticANIObject *ani) : GameObject(src) {
+ _lastFrameSpecialFlag = 0;
+ _updateFlag1 = 1;
+ _staticsObj1 = 0;
+ _staticsObj2 = 0;
+ _mx = 0;
+ _my = 0;
+ _m2x = 0;
+ _m2y = 0;
+
+ _field_78 = 0;
+ _framePosOffsets = 0;
+ _field_84 = 0;
+ _currDynamicPhase = 0;
+ _field_8C = 0;
+ _currDynamicPhaseIndex = 0;
+ _field_94 = 0;
+
+ _somePoint.x = 0;
+ _somePoint.y = 0;
+
+ _field_50 = src->_field_50;
+ _flipFlag = src->_flipFlag;
+ _currMovement = 0;
+ _mx = src->_mx;
+ _my = src->_my;
+ _m2x = src->_m2x;
+ _m2y = src->_m2y;
+
+ if (newSize != -1) {
+ if (newSize >= (int)src->_dynamicPhases.size() + 1)
+ newSize = src->_dynamicPhases.size() + 1;
+ } else {
+ newSize = src->_dynamicPhases.size();
+ }
+
+ _framePosOffsets = (Common::Point **)calloc(newSize, sizeof(Common::Point *));
+
+ for (int i = 0; i < newSize; i++)
+ _framePosOffsets[i] = new Common::Point();
+
+ if (oldIdxs) {
+ for (int i = 0; i < newSize - 1; i++, oldIdxs++) {
+ if (oldIdxs[i] == -1) {
+ _dynamicPhases.push_back(src->_staticsObj1);
+
+ _framePosOffsets[i]->x = 0;
+ _framePosOffsets[i]->y = 0;
+ } else {
+ src->setDynamicPhaseIndex(oldIdxs[i]);
+
+ _dynamicPhases.push_back(src->_currDynamicPhase);
+
+ _framePosOffsets[i]->x = src->_framePosOffsets[oldIdxs[i]]->x;
+ _framePosOffsets[i]->y = src->_framePosOffsets[oldIdxs[i]]->y;
+ }
+ }
+ _staticsObj1 = (Statics *)_dynamicPhases.front();
+ _staticsObj2 = (Statics *)_dynamicPhases.back();
+ } else {
+ for (int i = 0; i < newSize; i++) {
+ src->setDynamicPhaseIndex(i);
+
+ if (i < newSize - 1)
+ _dynamicPhases.push_back(new DynamicPhase(src->_currDynamicPhase, 0));
+
+ _framePosOffsets[i]->x = src->_framePosOffsets[i]->x;
+ _framePosOffsets[i]->y = src->_framePosOffsets[i]->y;
+ }
+
+ _staticsObj1 = ani->getStaticsById(src->_staticsObj1->_staticsId);
+ _staticsObj2 = ani->getStaticsById(src->_staticsObj2->_staticsId);
+
+ _dynamicPhases.push_back(_staticsObj2);
+
+ this->_updateFlag1 = src->_updateFlag1;
+ }
+
+ updateCurrDynamicPhase();
+ removeFirstPhase();
+
+ _counterMax = src->_counterMax;
+ _counter = src->_counter;
+}
+
+bool Movement::load(MfcArchive &file) {
+ warning("STUB: Movement::load");
+ return true;
+}
+
+bool Movement::load(MfcArchive &file, StaticANIObject *ani) {
+ GameObject::load(file);
+
+ int dynCount = file.readUint16LE();
+
+ debug(7, "dynCount: %d _id: %d", dynCount, _id);
+ if (dynCount != 0xffff || _id == MV_MAN_TURN_LU) {
+ _framePosOffsets = (Common::Point **)calloc(dynCount + 2, sizeof(Common::Point *));
+
+ for (int i = 0; i < dynCount + 2; i++)
+ _framePosOffsets[i] = new Common::Point();
+
+ for (int i = 0; i < dynCount; i++) {
+ DynamicPhase *ph = new DynamicPhase();
+ ph->load(file);
+
+ _dynamicPhases.push_back(ph);
+
+ _framePosOffsets[i]->x = ph->_x;
+ _framePosOffsets[i]->y = ph->_y;
+ }
+
+ int staticsid = file.readUint16LE();
+
+ _staticsObj1 = ani->getStaticsById(staticsid);
+
+ if (!_staticsObj1 && (staticsid & 0x4000)) {
+ Statics *s = ani->getStaticsById(staticsid ^ 0x4000);
+ _staticsObj1 = ani->addReverseStatics(s);
+ }
+
+ _mx = file.readUint32LE();
+ _my = file.readUint32LE();
+
+ staticsid = file.readUint16LE();
+
+ _staticsObj2 = ani->getStaticsById(staticsid);
+
+ if (!_staticsObj2 && (staticsid & 0x4000)) {
+ Statics *s = ani->getStaticsById(staticsid ^ 0x4000);
+ _staticsObj2 = ani->addReverseStatics(s);
+ }
+
+ _m2x = file.readUint32LE();
+ _m2y = file.readUint32LE();
+
+ if (_staticsObj2) {
+ _dynamicPhases.push_back(_staticsObj2);
+
+ _framePosOffsets[_dynamicPhases.size() - 1]->x = _m2x;
+ _framePosOffsets[_dynamicPhases.size() - 1]->y = _m2y;
+ }
+
+ } else {
+ int movid = file.readUint16LE();
+
+ _currMovement = ani->getMovementById(movid);
+ _staticsObj1 = 0;
+ _staticsObj2 = 0;
+
+ initStatics(ani);
+ }
+
+ if (_staticsObj1 && _staticsObj2) {
+ if ((_staticsObj1->_staticsId ^ _staticsObj2->_staticsId) & 0x4000)
+ _flipFlag = 1;
+ }
+
+ if (g_fullpipe->_gameProjectVersion >= 8)
+ _field_50 = file.readUint32LE();
+
+ if (g_fullpipe->_gameProjectVersion < 12)
+ _counterMax = 83;
+ else
+ _counterMax = file.readUint32LE();
+
+ _counter = 0;
+ updateCurrDynamicPhase();
+
+ return true;
+}
+
+Common::Point *Movement::getCurrDynamicPhaseXY(Common::Point &p) {
+ p.x = _currDynamicPhase->_someX;
+ p.y = _currDynamicPhase->_someY;
+
+ return &p;
+}
+
+Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) {
+ int oldox = _ox;
+ int oldoy = _oy;
+ int oldidx = _currDynamicPhaseIndex;
+
+ int x = 0;
+ int y = 0;
+
+ if (!idx) {
+ Common::Point point;
+
+ _staticsObj1->getSomeXY(point);
+ int y1 = _my - point.y;
+ int x1 = _mx - point.x;
+
+ setDynamicPhaseIndex(0);
+
+ x = _currDynamicPhase->_someX + x1;
+ y = _currDynamicPhase->_someY + y1;
+ }
+
+ setOXY(x, y);
+
+ while (_currDynamicPhaseIndex != idx)
+ gotoNextFrame(0, 0);
+
+ p.x = _ox;
+ p.y = _oy;
+
+ setDynamicPhaseIndex(oldidx);
+ setOXY(oldox, oldoy);
+
+ return &p;
+}
+
+void Movement::setAlpha(int alpha) {
+ if (_currMovement)
+ for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) {
+ ((DynamicPhase *)_currMovement->_dynamicPhases[i])->setAlpha(alpha);
+ }
+ else
+ for (uint i = 0; i < _dynamicPhases.size(); i++) {
+ ((DynamicPhase *)_dynamicPhases[i])->setAlpha(alpha);
+ }
+}
+
+Common::Point *Movement::getDimensionsOfPhase(Common::Point *p, int phaseIndex) {
+ int idx = phaseIndex;
+
+ if (idx == -1)
+ idx = _currDynamicPhaseIndex;
+
+ DynamicPhase *dyn;
+
+ if (_currMovement)
+ dyn = (DynamicPhase *)_currMovement->_dynamicPhases[idx];
+ else
+ dyn = (DynamicPhase *)_dynamicPhases[idx];
+
+ Common::Point point;
+
+ dyn->getDimensions(&point);
+
+ *p = point;
+
+ return p;
+}
+
+void Movement::initStatics(StaticANIObject *ani) {
+ if (!_currMovement)
+ return;
+
+ debug(7, "Movement::initStatics()");
+
+ _staticsObj2 = ani->addReverseStatics(_currMovement->_staticsObj2);
+ _staticsObj1 = ani->addReverseStatics(_currMovement->_staticsObj1);
+
+ _mx = _currMovement->_mx;
+ _my = _currMovement->_my;
+
+ _currMovement->setDynamicPhaseIndex(_currMovement->_updateFlag1 != 0 ? 1 : 0);
+
+ Common::Point point;
+
+ int x1 = _currMovement->_staticsObj1->getDimensions(&point)->x - _mx;
+
+ _mx = x1 - _currMovement->_currDynamicPhase->getDimensions(&point)->x;
+
+ _currMovement->setDynamicPhaseIndex(_currMovement->_currDynamicPhaseIndex);
+
+ _m2x = _currMovement->_m2x;
+ _m2y = _currMovement->_m2y;
+ _currMovement->gotoLastFrame();
+
+ x1 = _currMovement->_staticsObj2->getDimensions(&point)->x;
+ _m2x = _currMovement->_currDynamicPhase->getDimensions(&point)->x - _m2x - x1;
+}
+
+void Movement::updateCurrDynamicPhase() {
+ debug(7, "Movement::updateCurrDynamicPhase()");
+
+ if (_currMovement) {
+ if (_currMovement->_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _currMovement->_dynamicPhases.size())
+ return;
+
+ if (_currMovement->_dynamicPhases[_currDynamicPhaseIndex])
+ _currDynamicPhase = (DynamicPhase *)_currMovement->_dynamicPhases[_currDynamicPhaseIndex];
+ } else {
+ if (_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _dynamicPhases.size())
+ return;
+
+ if (_dynamicPhases[_currDynamicPhaseIndex])
+ _currDynamicPhase = (DynamicPhase *)_dynamicPhases[_currDynamicPhaseIndex];
+ }
+}
+
+int Movement::calcDuration() {
+ int res = 0;
+
+ if (_currMovement)
+ for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) {
+ res += ((DynamicPhase *)_currMovement->_dynamicPhases[i])->_initialCountdown;
+ }
+ else
+ for (uint i = 0; i < _dynamicPhases.size(); i++) {
+ res += ((DynamicPhase *)_dynamicPhases[i])->_initialCountdown;
+ }
+
+ return res;
+}
+
+void Movement::setDynamicPhaseIndex(int index) {
+ debug(7, "Movement::setDynamicPhaseIndex(%d)", index);
+ while (_currDynamicPhaseIndex < index)
+ gotoNextFrame(0, 0);
+
+ while (_currDynamicPhaseIndex > index)
+ gotoPrevFrame();
+}
+
+DynamicPhase *Movement::getDynamicPhaseByIndex(int idx) {
+ debug(7, "Movement::updateCurrDynamicPhase()");
+
+ if (_currMovement) {
+ if (_currMovement->_dynamicPhases.size() == 0 || (uint)idx >= _currMovement->_dynamicPhases.size())
+ return 0;
+
+ return (DynamicPhase *)_currMovement->_dynamicPhases[idx];
+ } else {
+ if (_dynamicPhases.size() == 0 || (uint)idx >= _dynamicPhases.size())
+ return 0;
+
+ return (DynamicPhase *)_dynamicPhases[idx];
+ }
+}
+
+void Movement::loadPixelData() {
+ Movement *mov = this;
+ for (Movement *i = _currMovement; i; i = i->_currMovement)
+ mov = i;
+
+ for (uint i = 0; i < _dynamicPhases.size(); i++) {
+ if ((Statics *)_dynamicPhases[i] != mov->_staticsObj2 || !(mov->_staticsObj2->_staticsId & 0x4000))
+ ((Statics *)_dynamicPhases[i])->getPixelData();
+ }
+
+ if (!(mov->_staticsObj1->_staticsId & 0x4000))
+ mov->_staticsObj1->getPixelData();
+}
+
+void Movement::removeFirstPhase() {
+ if (_updateFlag1) {
+ if (!_currDynamicPhaseIndex)
+ gotoNextFrame(0, 0);
+
+ if (!_currMovement) {
+ _dynamicPhases.remove_at(0);
+
+ for (uint i = 0; i < _dynamicPhases.size(); i++) {
+ _framePosOffsets[i - 1]->x = _framePosOffsets[i]->x;
+ _framePosOffsets[i - 1]->y = _framePosOffsets[i]->y;
+ }
+ }
+ _currDynamicPhaseIndex--;
+ }
+
+ updateCurrDynamicPhase();
+ _updateFlag1 = 0;
+}
+
+bool Movement::gotoNextFrame(int callback1, void (*callback2)(int *)) {
+ debug(8, "Movement::gotoNextFrame()");
+
+ if (!callback2) {
+ if (_currMovement) {
+ if ((uint)_currDynamicPhaseIndex == _currMovement->_dynamicPhases.size() - 1
+ && !(((DynamicPhase *)(_currMovement->_dynamicPhases.back()))->_countdown)) {
+ return false;
+ }
+ } else if ((uint)_currDynamicPhaseIndex == _dynamicPhases.size() - 1
+ && !(((DynamicPhase *)(_dynamicPhases.back()))->_countdown)) {
+ return false;
+ }
+ }
+
+ if (_currDynamicPhase->_countdown) {
+ _currDynamicPhase->_countdown--;
+ return true;
+ }
+
+ Common::Point point;
+
+ getCurrDynamicPhaseXY(point);
+ _ox -= point.x;
+ _oy -= point.y;
+
+ int deltax = 0;
+
+ if (_currMovement)
+ deltax = _currMovement->getDimensionsOfPhase(&point, _currDynamicPhaseIndex)->x;
+
+ int oldDynIndex = _currDynamicPhaseIndex;
+
+ if (callback2)
+ callback2(&_currDynamicPhaseIndex);
+ else
+ _currDynamicPhaseIndex++;
+
+ bool result = true;
+
+ if (_currMovement) {
+ if (_currMovement->_dynamicPhases.size() <= (uint)_currDynamicPhaseIndex) {
+ _currDynamicPhaseIndex = _currMovement->_dynamicPhases.size() - 1;
+ result = (callback2 == 0);
+ }
+ if (_currDynamicPhaseIndex < 0) {
+ _currDynamicPhaseIndex = 0;
+ result = false;
+ }
+ if (_currMovement->_framePosOffsets) {
+ if (callback1) {
+ point = *_currMovement->_framePosOffsets[_currDynamicPhaseIndex];
+ //callback1(_currDynamicPhaseIndex, &point, _ox, _oy);
+
+ _ox += deltax - point.x;
+ _oy += point.y;
+
+ _ox -= _currMovement->getDimensionsOfPhase(&point, _currDynamicPhaseIndex)->x;
+ } else if (oldDynIndex >= _currDynamicPhaseIndex) {
+ while (oldDynIndex > _currDynamicPhaseIndex) {
+ _ox += deltax;
+ deltax = _currMovement->getDimensionsOfPhase(&point, oldDynIndex)->x;
+
+ _ox += _currMovement->_framePosOffsets[oldDynIndex]->x;
+ _oy -= _currMovement->_framePosOffsets[oldDynIndex]->y;
+ oldDynIndex--;
+
+ _ox -= _currMovement->getDimensionsOfPhase(&point, oldDynIndex)->x;
+ }
+ } else {
+ for (int i = oldDynIndex + 1; i <= _currDynamicPhaseIndex; i++) {
+ _ox += deltax;
+ deltax = _currMovement->getDimensionsOfPhase(&point, i)->x;
+ _ox -= _currMovement->_framePosOffsets[i]->x;
+ _oy += _currMovement->_framePosOffsets[i]->y;
+ _ox -= _currMovement->getDimensionsOfPhase(&point, i)->x;
+ }
+ }
+ }
+ } else {
+ if (_dynamicPhases.size() <= (uint)_currDynamicPhaseIndex) {
+ _currDynamicPhaseIndex = _dynamicPhases.size() - 1;
+ result = (callback2 == 0);
+ }
+ if (_currDynamicPhaseIndex < 0) {
+ _currDynamicPhaseIndex = 0;
+ result = false;
+ }
+
+ if (_framePosOffsets) {
+ if (callback1) {
+ point.x = _framePosOffsets[_currDynamicPhaseIndex]->x;
+ point.y = _framePosOffsets[_currDynamicPhaseIndex]->y;
+
+ //callback1(_currDynamicPhaseIndex, &point, _ox, _oy);
+ _ox += point.x;
+ _oy += point.y;
+ } else if (oldDynIndex >= _currDynamicPhaseIndex) {
+ for (int i = oldDynIndex; i > _currDynamicPhaseIndex; i--) {
+ _ox -= _framePosOffsets[i]->x;
+ _oy -= _framePosOffsets[i]->y;
+ }
+ } else {
+ for (int i = oldDynIndex + 1; i <= _currDynamicPhaseIndex; i++) {
+ _ox += _framePosOffsets[i]->x;
+ _oy += _framePosOffsets[i]->y;
+ }
+ }
+ }
+ }
+
+ updateCurrDynamicPhase();
+ getCurrDynamicPhaseXY(point);
+ _ox += point.x;
+ _oy += point.y;
+
+ _currDynamicPhase->_countdown = _currDynamicPhase->_initialCountdown;
+
+ return result;
+}
+
+bool Movement::gotoPrevFrame() {
+ debug(8, "Movement::gotoPrevFrame()");
+
+ if (!_currDynamicPhaseIndex) {
+ gotoLastFrame();
+ return false;
+ }
+
+ Common::Point point;
+
+ getCurrDynamicPhaseXY(point);
+
+ _ox -= point.x;
+ _oy -= point.y;
+
+ if (_currMovement) {
+ if (_currMovement->_framePosOffsets) {
+ _ox += _currMovement->getDimensionsOfPhase(&point, _currDynamicPhaseIndex)->x;
+ _ox += _currMovement->_framePosOffsets[_currDynamicPhaseIndex]->x;
+ _oy -= _currMovement->_framePosOffsets[_currDynamicPhaseIndex]->y;
+ }
+
+ _currDynamicPhaseIndex--;
+ if (_currDynamicPhaseIndex < 0)
+ _currDynamicPhaseIndex = _currMovement->_dynamicPhases.size() - 1;
+
+ _ox -= _currMovement->getDimensionsOfPhase(&point, _currDynamicPhaseIndex)->x;
+ } else {
+ if (_framePosOffsets) {
+ _ox -= _framePosOffsets[_currDynamicPhaseIndex]->x;
+ _oy -= _framePosOffsets[_currDynamicPhaseIndex]->y;
+ }
+
+ _currDynamicPhaseIndex--;
+ if (_currDynamicPhaseIndex < 0)
+ _currDynamicPhaseIndex = _dynamicPhases.size() - 1;
+ }
+
+ updateCurrDynamicPhase();
+ getCurrDynamicPhaseXY(point);
+
+ _ox += point.x;
+ _oy += point.y;
+
+ return true;
+}
+
+void Movement::gotoFirstFrame() {
+ while (_currDynamicPhaseIndex)
+ gotoPrevFrame();
+}
+
+void Movement::gotoLastFrame() {
+ if (_currMovement) {
+ while ((uint)_currDynamicPhaseIndex != _currMovement->_dynamicPhases.size() - 1)
+ gotoNextFrame(0, 0);
+ } else {
+ while ((uint)_currDynamicPhaseIndex != _dynamicPhases.size() - 1)
+ gotoNextFrame(0, 0);
+ }
+}
+
+Common::Point *Movement::getCenter(Common::Point *p) {
+ Common::Rect rect;
+
+ rect = *_currDynamicPhase->_rect;
+
+ if (_currMovement) {
+ Common::Point point;
+
+ _currMovement->getDimensionsOfPhase(&point, _currDynamicPhaseIndex);
+
+ rect.moveTo(point.x - _currDynamicPhase->_rect->right, _currDynamicPhase->_rect->top);
+ }
+
+ p->x = rect.left + _currDynamicPhase->_rect->width() / 2;
+ p->y = rect.top + _currDynamicPhase->_rect->height() / 2;
+
+ return p;
+}
+
+DynamicPhase::DynamicPhase() {
+ _someX = 0;
+ _rect = 0;
+ _field_7C = 0;
+ _field_7E = 0;
+ _dynFlags = 0;
+ _someY = 0;
+}
+
+DynamicPhase::~DynamicPhase() {
+ delete _rect;
+}
+
+DynamicPhase::DynamicPhase(DynamicPhase *src, bool reverse) {
+ _field_7C = src->_field_7C;
+ _field_7E = 0;
+ _rect = new Common::Rect();
+
+ debug(0, "DynamicPhase::DynamicPhase(src, %d)", reverse);
+
+ if (reverse) {
+ if (!src->_bitmap)
+ src->init();
+
+ _bitmap = src->_bitmap->reverseImage();
+ _data = _bitmap->_pixels;
+ _dataSize = src->_dataSize;
+
+ if (g_fullpipe->_currArchive) {
+ _mfield_14 = 0;
+ _libHandle = g_fullpipe->_currArchive;
+ }
+
+ _mflags |= 1;
+
+ _someX = src->_someX;
+ _someY = src->_someY;
+ } else {
+ _mfield_14 = src->_mfield_14;
+ _mfield_8 = src->_mfield_8;
+ _mflags = src->_mflags;
+
+ _memfilename = (char *)calloc(strlen(src->_memfilename) + 1, 1);
+ strncpy(_memfilename, src->_memfilename, strlen(src->_memfilename) + 1);
+ _dataSize = src->_dataSize;
+ _mfield_10 = src->_mfield_10;
+ _libHandle = src->_libHandle;
+
+ _bitmap = src->_bitmap;
+ if (_bitmap)
+ _field_54 = 1;
+
+ _someX = src->_someX;
+ _someY = src->_someY;
+ }
+
+ *_rect = *src->_rect;
+
+ _width = src->_width;
+ _height = src->_height;
+ _field_7C = src->_field_7C;
+
+ if (src->getExCommand())
+ _exCommand = new ExCommand(src->getExCommand());
+ else
+ _exCommand = 0;
+
+ _initialCountdown = src->_initialCountdown;
+ _field_6A = src->_field_6A;
+ _dynFlags = src->_dynFlags;
+
+ setPaletteData(src->getPaletteData());
+
+ copyMemoryObject2(src);
+}
+
+bool DynamicPhase::load(MfcArchive &file) {
+ debug(5, "DynamicPhase::load()");
+
+ StaticPhase::load(file);
+
+ _field_7C = file.readUint16LE();
+ _rect = new Common::Rect();
+ _rect->left = file.readUint32LE();
+ _rect->top = file.readUint32LE();
+ _rect->right = file.readUint32LE();
+ _rect->bottom = file.readUint32LE();
+
+ assert (g_fullpipe->_gameProjectVersion >= 1);
+
+ _someX = file.readUint32LE();
+ _someY = file.readUint32LE();
+
+ assert (g_fullpipe->_gameProjectVersion >= 12);
+
+ _dynFlags = file.readUint32LE();
+
+ return true;
+}
+
+StaticPhase::StaticPhase() {
+ _field_6A = 1;
+ _initialCountdown = 0;
+ _countdown = 0;
+ _field_68 = 0;
+ _exCommand = 0;
+}
+
+StaticPhase::~StaticPhase() {
+ delete _exCommand;
+}
+
+bool StaticPhase::load(MfcArchive &file) {
+ debug(5, "StaticPhase::load()");
+
+ Picture::load(file);
+
+ _initialCountdown = file.readUint16LE();
+ _field_6A = file.readUint16LE();
+
+ if (g_fullpipe->_gameProjectVersion >= 12) {
+ _exCommand = (ExCommand *)file.readClass();
+
+ return true;
+ }
+
+ assert (g_fullpipe->_gameProjectVersion >= 12);
+
+ return true;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h
new file mode 100644
index 0000000000..15de4ab3be
--- /dev/null
+++ b/engines/fullpipe/statics.h
@@ -0,0 +1,257 @@
+/* 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 FULLPIPE_STATICS_H
+#define FULLPIPE_STATICS_H
+
+#include "fullpipe/gfx.h"
+
+namespace Fullpipe {
+
+class ExCommand;
+
+class StepArray : public CObject {
+ int _currPointIndex;
+ Common::Point **_points;
+ int _maxPointIndex;
+ int _pointsCount;
+ int _isEos;
+
+ public:
+ StepArray();
+ ~StepArray();
+ void clear();
+
+ int getCurrPointIndex() { return _currPointIndex; }
+ int getPointsCount() { return _maxPointIndex; }
+
+ Common::Point *getCurrPoint(Common::Point *point);
+ Common::Point *getPoint(Common::Point *point, int index, int offset);
+ bool gotoNextPoint();
+};
+
+class StaticPhase : public Picture {
+ public:
+ int16 _initialCountdown;
+ int16 _countdown;
+ int16 _field_68;
+ int16 _field_6A;
+ ExCommand *_exCommand;
+
+ public:
+ StaticPhase();
+ virtual ~StaticPhase();
+
+ virtual bool load(MfcArchive &file);
+
+ ExCommand *getExCommand() { return _exCommand; }
+};
+
+class DynamicPhase : public StaticPhase {
+ public:
+ int _someX;
+ int _someY;
+ Common::Rect *_rect;
+ int16 _field_7C;
+ int16 _field_7E;
+ int _dynFlags;
+
+ public:
+ DynamicPhase();
+ DynamicPhase(DynamicPhase *src, bool reverse);
+ virtual ~DynamicPhase();
+
+ virtual bool load(MfcArchive &file);
+
+ int getDynFlags() { return _dynFlags; }
+};
+
+class Statics : public DynamicPhase {
+ public:
+ int16 _staticsId;
+ char *_staticsName;
+ Picture *_picture;
+
+ public:
+ Statics();
+ Statics(Statics *src, bool reverse);
+ virtual ~Statics();
+
+ virtual bool load(MfcArchive &file);
+ Statics *getStaticsById(int itemId);
+
+ Common::Point *getSomeXY(Common::Point &p);
+ Common::Point *getCenter(Common::Point *p);
+};
+
+class StaticANIObject;
+
+class Movement : public GameObject {
+ public:
+ Common::Point _somePoint;
+ int _lastFrameSpecialFlag;
+ int _flipFlag;
+ int _updateFlag1;
+ Statics *_staticsObj1;
+ Statics *_staticsObj2;
+ int _mx;
+ int _my;
+ int _m2x;
+ int _m2y;
+ int _field_50;
+ int _counterMax;
+ int _counter;
+ PtrList _dynamicPhases;
+ int _field_78;
+ Common::Point **_framePosOffsets;
+ Movement *_currMovement;
+ int _field_84;
+ DynamicPhase *_currDynamicPhase;
+ int _field_8C;
+ int _currDynamicPhaseIndex;
+ int _field_94;
+
+ public:
+ Movement();
+ Movement(Movement *src, StaticANIObject *ani);
+ Movement(Movement *src, int *flag1, int flag2, StaticANIObject *ani);
+
+ virtual bool load(MfcArchive &file);
+ bool load(MfcArchive &file, StaticANIObject *ani);
+
+ Common::Point *getCurrDynamicPhaseXY(Common::Point &p);
+ Common::Point *getCenter(Common::Point *p);
+ Common::Point *getDimensionsOfPhase(Common::Point *p, int phaseIndex);
+
+ Common::Point *calcSomeXY(Common::Point &p, int idx);
+
+ void initStatics(StaticANIObject *ani);
+ void updateCurrDynamicPhase();
+
+ void setAlpha(int alpha);
+
+ void setDynamicPhaseIndex(int index);
+ DynamicPhase *getDynamicPhaseByIndex(int idx);
+
+ int calcDuration();
+
+ void removeFirstPhase();
+ bool gotoNextFrame(int callback1, void (*callback2)(int *));
+ bool gotoPrevFrame();
+ void gotoFirstFrame();
+ void gotoLastFrame();
+
+ void loadPixelData();
+
+ void draw(bool flipFlag, int angle);
+};
+
+class StaticANIObject : public GameObject {
+ public:
+ Movement *_movement;
+ Statics *_statics;
+ int _shadowsOn;
+ int16 _field_30;
+ int16 _field_32;
+ int _field_34;
+ int _initialCounter;
+ int _callback1;
+ void (*_callback2)(int *);
+ PtrList _movements;
+ PtrList _staticsList;
+ StepArray _stepArray;
+ int16 _field_96;
+ int _messageQueueId;
+ int _messageNum;
+ int _animExFlag;
+ int _counter;
+ int _someDynamicPhaseIndex;
+
+ public:
+ int16 _sceneId;
+
+ public:
+ StaticANIObject();
+ StaticANIObject(StaticANIObject *src);
+
+ virtual bool load(MfcArchive &file);
+
+ void setOXY(int x, int y);
+ Statics *getStaticsById(int id);
+ Statics *getStaticsByName(char *name);
+ Movement *getMovementById(int id);
+ int getMovementIdById(int itemId);
+ Movement *getMovementByName(char *name);
+ Common::Point *getCurrDimensions(Common::Point &p);
+
+ Common::Point *getSomeXY(Common::Point &p);
+
+ void clearFlags();
+ void setFlags40(bool state);
+ bool isIdle();
+ void setAlpha(int alpha);
+
+ void deleteFromGlobalMessageQueue();
+ void queueMessageQueue(MessageQueue *msg);
+ MessageQueue *getMessageQueue();
+ bool trySetMessageQueue(int msgNum, int qId);
+
+ void initMovements();
+ void loadMovementsPixelData();
+
+ void setSomeDynamicPhaseIndex(int val) { _someDynamicPhaseIndex = val; }
+ void adjustSomeXY();
+
+ bool startAnim(int movementId, int messageQueueId, int dynPhaseIdx);
+ bool startAnimEx(int movid, int parId, int flag1, int flag2);
+ void startAnimSteps(int movementId, int messageQueueId, int x, int y, Common::Point **points, int pointsCount, int someDynamicPhaseIndex);
+
+ void hide();
+ void show1(int x, int y, int movementId, int mqId);
+ void show2(int x, int y, int movementId, int mqId);
+ void playIdle();
+ void update(int counterdiff);
+
+ Statics *addReverseStatics(Statics *ani);
+ void draw();
+ void draw2();
+
+ MovTable *countMovements();
+ void setSpeed(int speed);
+
+ void updateStepPos();
+ void stopAnim_maybe();
+
+ MessageQueue *changeStatics1(int msgNum);
+ void changeStatics2(int objId);
+
+ bool getPixelAtPos(int x, int y, int *pixel);
+};
+
+struct MovTable {
+ int count;
+ int16 *movs;
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_STATICS_H */
diff --git a/engines/fullpipe/utils.cpp b/engines/fullpipe/utils.cpp
new file mode 100644
index 0000000000..3a65801951
--- /dev/null
+++ b/engines/fullpipe/utils.cpp
@@ -0,0 +1,501 @@
+/* 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 "fullpipe/fullpipe.h"
+
+#include "common/file.h"
+#include "common/memstream.h"
+
+#include "fullpipe/objects.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/ngiarchive.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/interaction.h"
+
+namespace Fullpipe {
+
+bool CObject::loadFile(const char *fname) {
+ Common::File file;
+
+ if (!file.open(fname))
+ return false;
+
+ MfcArchive archive(&file);
+
+ return load(archive);
+}
+
+bool ObList::load(MfcArchive &file) {
+ debug(5, "ObList::load()");
+ int count = file.readCount();
+
+ debug(9, "ObList::count: %d:", count);
+
+ for (int i = 0; i < count; i++) {
+ debug(9, "ObList::[%d]", i);
+ CObject *t = file.readClass();
+
+ push_back(t);
+ }
+
+ return true;
+}
+
+bool ObArray::load(MfcArchive &file) {
+ debug(5, "ObArray::load()");
+ int count = file.readCount();
+
+ resize(count);
+
+ for (int i = 0; i < count; i++) {
+ CObject *t = file.readClass();
+
+ push_back(*t);
+ }
+
+ return true;
+}
+
+bool DWordArray::load(MfcArchive &file) {
+ debug(5, "DWordArray::load()");
+ int count = file.readCount();
+
+ debug(9, "DWordArray::count: %d", count);
+
+ resize(count);
+
+ for (int i = 0; i < count; i++) {
+ int32 t = file.readUint32LE();
+
+ push_back(t);
+ }
+
+ return true;
+}
+
+char *MfcArchive::readPascalString(bool twoByte) {
+ char *tmp;
+ int len;
+
+ if (twoByte)
+ len = readUint16LE();
+ else
+ len = readByte();
+
+ tmp = (char *)calloc(len + 1, 1);
+ read(tmp, len);
+
+ debug(9, "readPascalString: %d <%s>", len, transCyrillic((byte *)tmp));
+
+ return tmp;
+}
+
+MemoryObject::MemoryObject() {
+ _memfilename = 0;
+ _mfield_8 = 0;
+ _mfield_C = 0;
+ _mfield_10 = -1;
+ _mfield_14 = 1;
+ _dataSize = 0;
+ _mflags = 0;
+ _libHandle = 0;
+ _data = 0;
+}
+
+MemoryObject::~MemoryObject() {
+ freeData();
+ if (_memfilename)
+ free(_memfilename);
+}
+
+bool MemoryObject::load(MfcArchive &file) {
+ debug(5, "MemoryObject::load()");
+ _memfilename = file.readPascalString();
+
+ if (char *p = strchr(_memfilename, '\\')) {
+ for (char *d = _memfilename; *p;) {
+ p++;
+ *d++ = *p;
+ }
+ }
+
+ if (g_fullpipe->_currArchive) {
+ _mfield_14 = 0;
+ _libHandle = g_fullpipe->_currArchive;
+ }
+
+ return true;
+}
+
+void MemoryObject::loadFile(char *filename) {
+ debug(5, "MemoryObject::loadFile(<%s>)", filename);
+
+ if (!*filename)
+ return;
+
+ if (!_data) {
+ NGIArchive *arr = g_fullpipe->_currArchive;
+
+ if (g_fullpipe->_currArchive != _libHandle && _libHandle)
+ g_fullpipe->_currArchive = _libHandle;
+
+ Common::SeekableReadStream *s = g_fullpipe->_currArchive->createReadStreamForMember(filename);
+
+ if (s) {
+ assert(s->size() > 0);
+
+ _dataSize = s->size();
+
+ debug(5, "Loading %s (%d bytes)", filename, _dataSize);
+ _data = (byte *)calloc(_dataSize, 1);
+ s->read(_data, _dataSize);
+
+ delete s;
+ } else {
+ warning("MemoryObject::loadFile(): reading failure");
+ }
+
+ g_fullpipe->_currArchive = arr;
+ }
+}
+
+byte *MemoryObject::getData() {
+ load();
+
+ if (_mfield_14 || _mflags & 1) {
+ return _data;
+ } else {
+ error("Unhandled packed data");
+ }
+}
+
+byte *MemoryObject::loadData() {
+ load();
+ return _data;
+}
+
+void MemoryObject::freeData() {
+ debug(8, "MemoryObject::freeData(): file: %s", _memfilename);
+
+ if (_data)
+ free(_data);
+
+ _data = 0;
+}
+
+bool MemoryObject::testFlags() {
+ if (_mfield_8)
+ return false;
+
+ if (_mflags & 1)
+ return true;
+
+ return false;
+}
+
+MemoryObject2::MemoryObject2() {
+ _rows = 0;
+}
+
+MemoryObject2::~MemoryObject2() {
+ if (_rows)
+ free(_rows);
+}
+
+bool MemoryObject2::load(MfcArchive &file) {
+ debug(5, "MemoryObject2::load()");
+ MemoryObject::load(file);
+
+ _mflags |= 1;
+
+ debug(5, "MemoryObject2::load: <%s>", _memfilename);
+
+ if (_memfilename && *_memfilename) {
+ MemoryObject::loadFile(_memfilename);
+ }
+
+ return true;
+}
+
+void MemoryObject2::copyData(byte *src, int dataSize) {
+ if (_data)
+ freeData();
+
+ _dataSize = dataSize;
+ _data = (byte *)malloc(dataSize);
+
+ memcpy(_data, src, _dataSize);
+}
+
+int MfcArchive::readCount() {
+ int count = readUint16LE();
+
+ if (count == 0xffff)
+ count = readUint32LE();
+
+ return count;
+}
+
+double MfcArchive::readDouble() {
+ // FIXME: This is utterly cruel and unportable
+ // Some articles on the matter:
+ // http://randomascii.wordpress.com/2013/02/07/float-precision-revisited-nine-digit-float-portability/
+ // http://randomascii.wordpress.com/2012/01/11/tricks-with-the-floating-point-format/
+
+ union {
+ struct {
+ int32 a;
+ int32 b;
+ } i;
+ double d;
+ } tmp;
+
+ tmp.i.a = readUint32LE();
+ tmp.i.b = readUint32LE();
+
+ return tmp.d;
+}
+
+enum {
+ kNullObject,
+ kInteraction,
+ kMessageQueue,
+ kExCommand,
+ kObjstateCommand,
+ kGameVar,
+ kMctlCompound,
+ kMovGraph,
+ kMovGraphLink,
+ kMovGraphNode,
+ kReactParallel,
+ kReactPolygonal
+};
+
+const struct {
+ const char *name;
+ int id;
+} classMap[] = {
+ { "CInteraction", kInteraction },
+ { "MessageQueue", kMessageQueue },
+ { "ExCommand", kExCommand },
+ { "CObjstateCommand", kObjstateCommand },
+ { "CGameVar", kGameVar },
+ { "CMctlCompound", kMctlCompound },
+ { "CMovGraph", kMovGraph },
+ { "CMovGraphLink", kMovGraphLink },
+ { "CMovGraphNode", kMovGraphNode },
+ { "CReactParallel", kReactParallel },
+ { "CReactPolygonal", kReactPolygonal },
+ { 0, 0 }
+};
+
+static const char *lookupObjectId(int id) {
+ for (int i = 0; classMap[i].name; i++) {
+ if (classMap[i].id == id)
+ return classMap[i].name;
+ }
+
+ return "";
+}
+
+static CObject *createObject(int objectId) {
+ switch (objectId) {
+ case kNullObject:
+ return 0;
+ case kInteraction:
+ return new Interaction();
+ case kMessageQueue:
+ return new MessageQueue();
+ case kExCommand:
+ return new ExCommand();
+ case kObjstateCommand:
+ return new ObjstateCommand();
+ case kGameVar:
+ return new GameVar();
+ case kMctlCompound:
+ return new MctlCompound();
+ case kMovGraph:
+ return new MovGraph();
+ case kMovGraphLink:
+ return new MovGraphLink();
+ case kMovGraphNode:
+ return new MovGraphNode();
+ case kReactParallel:
+ return new ReactParallel();
+ case kReactPolygonal:
+ return new ReactPolygonal();
+ default:
+ error("Unknown objectId: %d", objectId);
+ }
+
+ return 0;
+}
+
+MfcArchive::MfcArchive(Common::SeekableReadStream *stream) {
+ for (int i = 0; classMap[i].name; i++) {
+ _classMap[classMap[i].name] = classMap[i].id;
+ }
+
+ _lastIndex = 1;
+ _level = 0;
+
+ _stream = stream;
+
+ _objectMap.push_back(0);
+ _objectIdMap.push_back(kNullObject);
+}
+
+CObject *MfcArchive::readClass() {
+ bool isCopyReturned;
+ CObject *res = parseClass(&isCopyReturned);
+
+ if (res && !isCopyReturned)
+ res->load(*this);
+
+ return res;
+}
+
+CObject *MfcArchive::parseClass(bool *isCopyReturned) {
+ char *name;
+ int objectId = 0;
+ CObject *res = 0;
+
+ uint obTag = readUint16LE();
+
+ debug(7, "parseClass::obTag = %d (%04x) at 0x%08x", obTag, obTag, pos() - 2);
+
+ if (obTag == 0xffff) {
+ int schema = readUint16LE();
+
+ debug(7, "parseClass::schema = %d", schema);
+
+ name = readPascalString(true);
+ debug(7, "parseClass::class <%s>", name);
+
+ if (!_classMap.contains(name)) {
+ error("Unknown class in MfcArchive: <%s>", name);
+ }
+
+ objectId = _classMap[name];
+
+ debug(7, "tag: %d 0x%x (%x)", _objectMap.size() - 1, _objectMap.size() - 1, objectId);
+
+ res = createObject(objectId);
+ _objectMap.push_back(res);
+ _objectIdMap.push_back(objectId);
+
+ _objectMap.push_back(res); // Basically a hack, but behavior is all correct
+ _objectIdMap.push_back(objectId);
+
+ *isCopyReturned = false;
+ } else if ((obTag & 0x8000) == 0) {
+ if (_objectMap.size() < obTag) {
+ error("Object index too big: %d at 0x%08x", obTag, pos() - 2);
+ }
+ debug(7, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag]));
+
+ res = _objectMap[obTag];
+
+ *isCopyReturned = true;
+ } else {
+
+ obTag &= ~0x8000;
+
+ if (_objectMap.size() < obTag) {
+ error("Object index too big: %d at 0x%08x", obTag, pos() - 2);
+ }
+
+ debug(7, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag]));
+
+ objectId = _objectIdMap[obTag];
+
+ res = createObject(objectId);
+ _objectMap.push_back(res);
+ _objectIdMap.push_back(objectId);
+
+ *isCopyReturned = false;
+ }
+
+ return res;
+}
+
+char *genFileName(int superId, int sceneId, const char *ext) {
+ char *s = (char *)calloc(256, 1);
+
+ if (superId) {
+ snprintf(s, 255, "%04d%04d.%s", superId, sceneId, ext);
+ } else {
+ snprintf(s, 255, "%04d.%s", sceneId, ext);
+ }
+
+ debug(7, "genFileName: %s", s);
+
+ return s;
+}
+
+// Translates cp-1251..utf-8
+byte *transCyrillic(byte *s) {
+ static byte tmp[1024];
+
+ static int trans[] = { 0xa8, 0xd081, 0xb8, 0xd191, 0xc0, 0xd090,
+ 0xc1, 0xd091, 0xc2, 0xd092, 0xc3, 0xd093, 0xc4, 0xd094,
+ 0xc5, 0xd095, 0xc6, 0xd096, 0xc7, 0xd097, 0xc8, 0xd098,
+ 0xc9, 0xd099, 0xca, 0xd09a, 0xcb, 0xd09b, 0xcc, 0xd09c,
+ 0xcd, 0xd09d, 0xce, 0xd09e, 0xcf, 0xd09f, 0xd0, 0xd0a0,
+ 0xd1, 0xd0a1, 0xd2, 0xd0a2, 0xd3, 0xd0a3, 0xd4, 0xd0a4,
+ 0xd5, 0xd0a5, 0xd6, 0xd0a6, 0xd7, 0xd0a7, 0xd8, 0xd0a8,
+ 0xd9, 0xd0a9, 0xda, 0xd0aa, 0xdb, 0xd0ab, 0xdc, 0xd0ac,
+ 0xdd, 0xd0ad, 0xde, 0xd0ae, 0xdf, 0xd0af, 0xe0, 0xd0b0,
+ 0xe1, 0xd0b1, 0xe2, 0xd0b2, 0xe3, 0xd0b3, 0xe4, 0xd0b4,
+ 0xe5, 0xd0b5, 0xe6, 0xd0b6, 0xe7, 0xd0b7, 0xe8, 0xd0b8,
+ 0xe9, 0xd0b9, 0xea, 0xd0ba, 0xeb, 0xd0bb, 0xec, 0xd0bc,
+ 0xed, 0xd0bd, 0xee, 0xd0be, 0xef, 0xd0bf, 0xf0, 0xd180,
+ 0xf1, 0xd181, 0xf2, 0xd182, 0xf3, 0xd183, 0xf4, 0xd184,
+ 0xf5, 0xd185, 0xf6, 0xd186, 0xf7, 0xd187, 0xf8, 0xd188,
+ 0xf9, 0xd189, 0xfa, 0xd18a, 0xfb, 0xd18b, 0xfc, 0xd18c,
+ 0xfd, 0xd18d, 0xfe, 0xd18e, 0xff, 0xd18f };
+
+ int i = 0;
+
+ for (byte *p = s; *p; p++) {
+ if (*p < 128) {
+ tmp[i++] = *p;
+ } else {
+ int j;
+ for (j = 0; trans[j]; j += 2) {
+ if (trans[j] == *p) {
+ tmp[i++] = (trans[j + 1] >> 8) & 0xff;
+ tmp[i++] = trans[j + 1] & 0xff;
+ break;
+ }
+ }
+
+ assert(trans[j]);
+ }
+ }
+
+ tmp[i] = 0;
+
+ return tmp;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/utils.h b/engines/fullpipe/utils.h
new file mode 100644
index 0000000000..64f56ced0a
--- /dev/null
+++ b/engines/fullpipe/utils.h
@@ -0,0 +1,155 @@
+/* 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 FULLPIPE_UTILS_H
+#define FULLPIPE_UTILS_H
+
+#include "common/hash-str.h"
+#include "common/array.h"
+#include "common/file.h"
+
+namespace Fullpipe {
+
+class CObject;
+class NGIArchive;
+
+typedef Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ClassMap;
+
+class MfcArchive : public Common::SeekableReadStream {
+ ClassMap _classMap;
+ Common::Array<CObject *> _objectMap;
+ Common::Array<int> _objectIdMap;
+
+ int _lastIndex;
+ int _level;
+
+ Common::SeekableReadStream *_stream;
+
+ public:
+ MfcArchive(Common::SeekableReadStream *file);
+
+ char *readPascalString(bool twoByte = false);
+ int readCount();
+ double readDouble();
+ CObject *parseClass(bool *isCopyReturned);
+ CObject *readClass();
+
+ void incLevel() { _level++; }
+ void decLevel() { _level--; }
+ int getLevel() { return _level; }
+
+ virtual bool eos() const { return _stream->eos(); }
+ virtual uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
+ virtual int32 pos() const { return _stream->pos(); }
+ virtual int32 size() const { return _stream->size(); }
+ virtual bool seek(int32 offset, int whence = SEEK_SET) { return _stream->seek(offset, whence); }
+};
+
+enum ObjType {
+ kObjTypeDefault,
+ kObjTypeMovGraph,
+ kObjTypeMovGraphLink,
+ kObjTypeMovGraphNode,
+ kObjTypeMctlCompound,
+ kObjTypeObjstateCommand,
+ kObjTypePictureObject,
+ kObjTypeStaticANIObject
+};
+
+class CObject {
+public:
+ ObjType _objtype;
+
+ CObject() : _objtype(kObjTypeDefault) {}
+ virtual bool load(MfcArchive &in) { return true; }
+ virtual ~CObject() {}
+
+ bool loadFile(const char *fname);
+};
+
+class ObList : public Common::List<CObject *>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+class MemoryObject : CObject {
+ friend class Picture;
+ friend class Scene;
+
+ protected:
+ char *_memfilename;
+ int _mfield_8;
+ int _mfield_C;
+ int _mfield_10;
+ char _mfield_14;
+ byte *_data;
+ int _dataSize;
+ int _mflags;
+ NGIArchive *_libHandle;
+
+ public:
+ MemoryObject();
+ virtual ~MemoryObject();
+
+ virtual bool load(MfcArchive &file);
+ void loadFile(char *filename);
+ void load() { loadFile(_memfilename); }
+ byte *getData();
+ byte *loadData();
+
+ bool testFlags();
+
+ void freeData();
+};
+
+class MemoryObject2 : public MemoryObject {
+ friend class Picture;
+
+ protected:
+ byte **_rows;
+
+ public:
+ MemoryObject2();
+ virtual ~MemoryObject2();
+ virtual bool load(MfcArchive &file);
+
+ void copyData(byte *src, int dataSize);
+};
+
+class ObArray : public Common::Array<CObject>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+class DWordArray : public Common::Array<int32>, public CObject {
+ public:
+ virtual bool load(MfcArchive &file);
+};
+
+typedef Common::Array<void *> PtrList;
+
+char *genFileName(int superId, int sceneId, const char *ext);
+byte *transCyrillic(byte *s);
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_UTILS_H */
diff --git a/engines/gob/POTFILES b/engines/gob/POTFILES
new file mode 100644
index 0000000000..9a512469dd
--- /dev/null
+++ b/engines/gob/POTFILES
@@ -0,0 +1,3 @@
+engines/gob/inter_playtoons.cpp
+engines/gob/inter_v2.cpp
+engines/gob/inter_v5.cpp
diff --git a/engines/gob/configure.engine b/engines/gob/configure.engine
new file mode 100644
index 0000000000..8e012f5815
--- /dev/null
+++ b/engines/gob/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine gob "Gobli*ns" yes
diff --git a/engines/gob/iniconfig.cpp b/engines/gob/iniconfig.cpp
index bba531723c..032231bd4d 100644
--- a/engines/gob/iniconfig.cpp
+++ b/engines/gob/iniconfig.cpp
@@ -73,7 +73,7 @@ bool INIConfig::getConfig(const Common::String &file, Config &config) {
}
bool INIConfig::openConfig(const Common::String &file, Config &config) {
- config.config = new Common::ConfigFile();
+ config.config = new Common::INIFile();
config.created = false;
if (!config.config->loadFromFile(file)) {
@@ -89,7 +89,7 @@ bool INIConfig::openConfig(const Common::String &file, Config &config) {
}
bool INIConfig::createConfig(const Common::String &file, Config &config) {
- config.config = new Common::ConfigFile();
+ config.config = new Common::INIFile();
config.created = true;
_configs.setVal(file, config);
diff --git a/engines/gob/iniconfig.h b/engines/gob/iniconfig.h
index bf60f2d125..c1890170dc 100644
--- a/engines/gob/iniconfig.h
+++ b/engines/gob/iniconfig.h
@@ -24,7 +24,7 @@
#define GOB_INICONFIG_H
#include "common/str.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/hashmap.h"
namespace Gob {
@@ -43,7 +43,7 @@ public:
private:
struct Config {
- Common::ConfigFile *config;
+ Common::INIFile *config;
bool created;
};
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 6b65eb6ab9..870b0f15b3 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
@@ -815,7 +821,7 @@ bool Surface::loadIFF(Common::SeekableReadStream &stream) {
return false;
resize(decoder.getSurface()->w, decoder.getSurface()->h);
- memcpy(_vidMem, decoder.getSurface()->pixels, decoder.getSurface()->w * decoder.getSurface()->h);
+ memcpy(_vidMem, decoder.getSurface()->getPixels(), decoder.getSurface()->w * decoder.getSurface()->h);
return true;
}
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index a478492ccc..155989ccee 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -734,7 +734,11 @@ bool VideoPlayer::copyFrame(int slot, Surface &dest,
if (!surface)
return false;
- Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)surface->pixels);
+ // FIXME? This currently casts away const from the pixel data. However, it
+ // is only used read-only in this case (as far as I can tell). Not casting
+ // the const qualifier away will lead to an additional allocation and copy
+ // of the frame data which is undesirable.
+ Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)const_cast<void *>(surface->getPixels()));
dest.blit(src, left, top, left + width - 1, top + height - 1, x, y, transp);
return true;
diff --git a/engines/groovie/POTFILES b/engines/groovie/POTFILES
new file mode 100644
index 0000000000..0bf4528a7d
--- /dev/null
+++ b/engines/groovie/POTFILES
@@ -0,0 +1,2 @@
+engines/groovie/detection.cpp
+engines/groovie/script.cpp
diff --git a/engines/groovie/configure.engine b/engines/groovie/configure.engine
new file mode 100644
index 0000000000..84e95a70df
--- /dev/null
+++ b/engines/groovie/configure.engine
@@ -0,0 +1,4 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine groovie "Groovie" yes "groovie2" "7th Guest"
+add_engine groovie2 "Groovie 2 games" no "" "" "jpeg"
diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp
index d29c22dd02..a55d8fad95 100644
--- a/engines/groovie/font.cpp
+++ b/engines/groovie/font.cpp
@@ -112,7 +112,7 @@ bool T7GFont::load(Common::SeekableReadStream &stream) {
return true;
}
-void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const {
+void T7GFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
// We ignore the color, as the font is already colored
const Glyph *glyph = getGlyph(chr);
const byte *src = glyph->pixels;
@@ -125,7 +125,7 @@ void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 co
}
}
-const T7GFont::Glyph *T7GFont::getGlyph(byte chr) const {
+const T7GFont::Glyph *T7GFont::getGlyph(uint32 chr) const {
assert (chr < 128);
byte numGlyph = _mapChar2Glyph[chr];
diff --git a/engines/groovie/font.h b/engines/groovie/font.h
index 20aaa4cf23..49cf4b7b06 100644
--- a/engines/groovie/font.h
+++ b/engines/groovie/font.h
@@ -37,8 +37,8 @@ public:
int getFontHeight() const { return _maxHeight; }
int getMaxCharWidth() const { return _maxWidth; }
- int getCharWidth(byte chr) const { return getGlyph(chr)->width; }
- void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const;
+ int getCharWidth(uint32 chr) const { return getGlyph(chr)->width; }
+ void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const;
private:
int _maxHeight, _maxWidth;
@@ -55,7 +55,7 @@ private:
byte _mapChar2Glyph[128];
Glyph *_glyphs;
- const Glyph *getGlyph(byte chr) const;
+ const Glyph *getGlyph(uint32 chr) const;
};
} // End of Groovie namespace
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 73eb574dec..a4d8a4330c 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -82,8 +82,8 @@ void GraphicsMan::mergeFgAndBg() {
uint32 i;
byte *countf, *countb;
- countf = (byte *)_foreground.getBasePtr(0, 0);
- countb = (byte *)_background.getBasePtr(0, 0);
+ countf = (byte *)_foreground.getPixels();
+ countb = (byte *)_background.getPixels();
for (i = 640 * 320; i; i--) {
if (255 == *(countf)) {
*(countf) = *(countb);
@@ -94,7 +94,7 @@ void GraphicsMan::mergeFgAndBg() {
}
void GraphicsMan::updateScreen(Graphics::Surface *source) {
- _vm->_system->copyRectToScreen(source->getBasePtr(0, 0), 640, 0, 80, 640, 320);
+ _vm->_system->copyRectToScreen(source->getPixels(), 640, 0, 80, 640, 320);
change();
}
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 72a61fefb2..e1ca7fb945 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -28,6 +28,7 @@
#include "groovie/groovie.h"
#include "common/debug.h"
+#include "common/substream.h"
#include "common/textconsole.h"
#include "graphics/palette.h"
@@ -160,7 +161,7 @@ bool ROQPlayer::playFrameInternal() {
if (_dirty) {
// Update the screen
- _syst->copyRectToScreen(_bg->getBasePtr(0, 0), _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
+ _syst->copyRectToScreen(_bg->getPixels(), _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
_syst->updateScreen();
// Clear the dirty flag
@@ -291,8 +292,8 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
}
// Clear the buffers with black YUV values
- byte *ptr1 = (byte *)_currBuf->getBasePtr(0, 0);
- byte *ptr2 = (byte *)_prevBuf->getBasePtr(0, 0);
+ byte *ptr1 = (byte *)_currBuf->getPixels();
+ byte *ptr2 = (byte *)_prevBuf->getPixels();
for (int i = 0; i < width * height; i++) {
*ptr1++ = 0;
*ptr1++ = 128;
@@ -435,19 +436,20 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {
warning("Groovie::ROQ: JPEG frame (unfinished)");
Graphics::JPEGDecoder *jpg = new Graphics::JPEGDecoder();
- jpg->loadStream(*_file);
- const byte *y = (const byte *)jpg->getComponent(1)->getBasePtr(0, 0);
- const byte *u = (const byte *)jpg->getComponent(2)->getBasePtr(0, 0);
- const byte *v = (const byte *)jpg->getComponent(3)->getBasePtr(0, 0);
+ jpg->setOutputColorSpace(Graphics::JPEGDecoder::kColorSpaceYUV);
- byte *ptr = (byte *)_currBuf->getBasePtr(0, 0);
- for (int i = 0; i < _currBuf->w * _currBuf->h; i++) {
- *ptr++ = *y++;
- *ptr++ = *u++;
- *ptr++ = *v++;
- }
+ uint32 startPos = _file->pos();
+ Common::SeekableSubReadStream subStream(_file, startPos, startPos + blockHeader.size, DisposeAfterUse::NO);
+ jpg->loadStream(subStream);
+
+ const Graphics::Surface *srcSurf = jpg->getSurface();
+ const byte *src = (const byte *)srcSurf->getPixels();
+ byte *ptr = (byte *)_currBuf->getPixels();
+ memcpy(ptr, src, _currBuf->w * _currBuf->h * srcSurf->format.bytesPerPixel);
delete jpg;
+
+ _file->seek(startPos + blockHeader.size);
return true;
}
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index cbbdecc3e7..8e3bef9945 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -373,7 +373,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) {
rect.translate(0, -80);
_vm->_graphicsMan->_foreground.frameRect(rect, 250);
- _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getBasePtr(0, 0), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320);
+ _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320);
_vm->_system->updateScreen();
}
@@ -983,7 +983,7 @@ void Script::o_strcmpnejmp_var() { // 0x21
void Script::o_copybgtofg() { // 0x22
debugScript(1, true, "COPY_BG_TO_FG");
- memcpy(_vm->_graphicsMan->_foreground.getBasePtr(0, 0), _vm->_graphicsMan->_background.getBasePtr(0, 0), 640 * 320);
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * 320);
}
void Script::o_strcmpeqjmp() { // 0x23
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/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index 8786e75488..59d966a22f 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -358,7 +358,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
byte *buf;
if (_flagOne) {
// Paint to the foreground
- buf = (byte *)_fg->getBasePtr(0, 0);
+ buf = (byte *)_fg->getPixels();
if (_flag2Byte) {
mask = 0xff;
} else {
@@ -370,7 +370,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
_flagFirstFrame = true;
} else {
// Paint to the background
- buf = (byte *)_bg->getBasePtr(0, 0);
+ buf = (byte *)_bg->getPixels();
}
// Read the palette
@@ -486,9 +486,9 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth)
// TODO: Verify just the else block is required
//if (_flagOne) {
// Paint to the foreground
- //dest = (byte *)_fg->getBasePtr(0, 0) + offset;
+ //dest = (byte *)_fg->getPixels() + offset;
//} else {
- dest = (byte *)_bg->getBasePtr(0, 0) + offset;
+ dest = (byte *)_bg->getPixels() + offset;
//}
// Move the pointers to the beginning of the current block
@@ -496,8 +496,8 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth)
dest += blockOff;
byte *fgBuf = 0;
if (_flagSeven) {
- fgBuf = (byte *)_fg->getBasePtr(0, 0) + offset + blockOff;
- //byte *bgBuf = (byte *)_bg->getBasePtr(0, 0) + offset + blockOff;
+ fgBuf = (byte *)_fg->getPixels() + offset + blockOff;
+ //byte *bgBuf = (byte *)_bg->getPixels() + offset + blockOff;
}
for (int y = TILE_SIZE; y; y--) {
@@ -550,7 +550,7 @@ void VDXPlayer::fadeIn(uint8 *targetpal) {
// TODO: Is it required? If so, move to an appropiate place
// Copy the foreground to the background
- memcpy((byte *)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), (byte *)_vm->_graphicsMan->_background.getBasePtr(0, 0), 640 * 320);
+ memcpy((byte *)_vm->_graphicsMan->_foreground.getPixels(), (byte *)_vm->_graphicsMan->_background.getPixels(), 640 * 320);
// Start a fadein
_vm->_graphicsMan->fadeIn(targetpal);
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index f7b923badf..f9e3ecafcd 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;
}
/**
@@ -349,15 +349,21 @@ void ComputerManager::loadMenu() {
char *ptr;
if (_vm->_fileIO->fileExists("COMPUTAN.TXT")) {
ptr = (char *)_vm->_fileIO->loadFile("COMPUTAN.TXT");
- } else if (_vm->_globals->_language == LANG_FR) {
- ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText));
- strcpy(ptr, _frenchText);
- } else if (_vm->_globals->_language == LANG_SP) {
- ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText));
- strcpy(ptr, _spanishText);
} else {
- ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText));
- strcpy(ptr, _englishText);
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
+ ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText));
+ strcpy(ptr, _frenchText);
+ break;
+ case LANG_SP:
+ ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText));
+ strcpy(ptr, _spanishText);
+ break;
+ default:
+ ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText));
+ strcpy(ptr, _englishText);
+ break;
+ }
}
char *tmpPtr = ptr;
@@ -479,12 +485,17 @@ void ComputerManager::readText(int idx) {
_vm->_events->_escKeyFl = false;
Common::String filename;
- if (_vm->_globals->_language == LANG_EN)
+ switch (_vm->_globals->_language) {
+ case LANG_EN:
filename = "THOPKAN.TXT";
- else if (_vm->_globals->_language == LANG_FR)
+ break;
+ case LANG_FR:
filename = "THOPK.TXT";
- else if (_vm->_globals->_language == LANG_SP)
+ break;
+ case LANG_SP:
filename = "THOPKES.TXT";
+ break;
+ }
byte *ptr = _vm->_fileIO->loadFile(filename);
uint16 fileSize = _vm->_fileIO->fileSize(filename);
@@ -579,26 +590,32 @@ void ComputerManager::displayGamesSubMenu() {
*/
void ComputerManager::loadHiscore() {
byte *ptr = _vm->_globals->allocMemory(100);
- _vm->_saveLoad->load("HISCORE.DAT", ptr);
+ memset(ptr, 0, 100);
+
+ if (_vm->_saveLoad->saveExists(_vm->getTargetName() + "-highscore.dat"))
+ _vm->_saveLoad->load(_vm->getTargetName() + "-highscore.dat", ptr);
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);
}
}
+ _lowestHiScore = atol(_score[5]._score.c_str());
_vm->_globals->freeMemory(ptr);
- _breakoutHiscore = atol(_score[5]._score.c_str());
}
/**
@@ -779,7 +796,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 +840,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 +881,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 +903,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 +920,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);
@@ -970,10 +1002,10 @@ void ComputerManager::saveScore() {
}
byte *ptr = _vm->_globals->allocMemory(100);
- memset(ptr, 0, 99);
+ memset(ptr, 0, 100);
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 = ' ';
@@ -991,7 +1023,7 @@ void ComputerManager::saveScore() {
ptr[curBufPtr + 15] = 0;
}
- _vm->_saveLoad->saveFile("HISCORE.DAT", ptr, 100);
+ _vm->_saveLoad->saveFile(_vm->getTargetName() + "-highscore.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/configure.engine b/engines/hopkins/configure.engine
new file mode 100644
index 0000000000..c38ecd4cd2
--- /dev/null
+++ b/engines/hopkins/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine hopkins "Hopkins FBI" yes "" "" "16bit"
diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp
index a42597415b..c617a5aacf 100644
--- a/engines/hopkins/detection.cpp
+++ b/engines/hopkins/detection.cpp
@@ -56,6 +56,10 @@ bool HopkinsEngine::getIsDemo() const {
return _gameDescription->desc.flags & ADGF_DEMO;
}
+const Common::String &HopkinsEngine::getTargetName() const {
+ return _targetName;
+}
+
} // End of namespace Hopkins
static const PlainGameDescriptor hopkinsGames[] = {
@@ -67,6 +71,7 @@ static const PlainGameDescriptor hopkinsGames[] = {
const static char *directoryGlobs[] = {
"voice",
+ "link",
0
};
diff --git a/engines/hopkins/detection_tables.h b/engines/hopkins/detection_tables.h
index 3e04375fe9..c3ff563f6f 100644
--- a/engines/hopkins/detection_tables.h
+++ b/engines/hopkins/detection_tables.h
@@ -24,12 +24,11 @@ namespace Hopkins {
static const HopkinsGameDescription gameDescriptions[] = {
{
- // Hopkins FBI Linux Demo 1.00
+ // Hopkins FBI Linux Demo UK 1.00 and 1.02
{
"hopkins",
- "Linux Demo v1.00",
+ "Linux Demo",
{
- {"Hopkins-PDemo.bin", 0, "88b4d6e14b9b1407083cb3d1213c0fa7", 272027},
{"RES_VAN.RES", 0, "29414c05be8f9fe794c61572a65def12", 16060544},
AD_LISTEND
},
@@ -39,32 +38,14 @@ static const HopkinsGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
},
-
- {
- // Hopkins FBI Linux Demo 1.02
- {
- "hopkins",
- "Linux Demo v1.02",
- {
- {"Hopkins-PDemo.bin", 0, "f82f4e698f3a189419351be0de2b2f8e", 273760},
- {"RES_VAN.RES", 0, "29414c05be8f9fe794c61572a65def12", 16060544},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformLinux,
- ADGF_DEMO,
- GUIO1(GUIO_NONE)
- },
- },
-
{
// Hopkins FBI OS/2, provided by Strangerke
{
"hopkins",
0,
{
- {"Hopkins.exe", 0, "63d45f882278e5a9fa1027066223e5d9", 292864},
{"ENG_VOI.RES", 0, "fa5789d1d8c19d160bce44a33e742fdf", 66860711},
+ {"CREAN.TXT", 0, "e13aa69d9e043f066776e1d0ef98fdf5", 1871},
AD_LISTEND
},
Common::EN_ANY,
@@ -74,93 +55,41 @@ static const HopkinsGameDescription gameDescriptions[] = {
},
},
{
- // Hopkins FBI Win95 Demo, provided by Strangerke
- // CHECKME: No voice! a second file is required though... Also, it has multi-language support
- {
- "hopkins",
- "Win95 Demo",
- {
- {"Hopkins.exe", 0, "0c9ebfe371f4dcf84a49f333f04839a0", 376897},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- GUIO1(GUIO_NONE)
- },
- },
- {
- // Hopkins FBI Win95 Polish Demo, provided by Strangerke
- {
- "hopkins",
- "Win95 Demo",
- {
- {"Hopkins.exe", 0, "7595c0b9374739b212ee9f8f412ac716", 307200},
- {"RES_VAN.RES", 0, "8262cfba261c200af4451902689dffe0", 12233202},
- AD_LISTEND
- },
- Common::PL_POL,
- Common::kPlatformWindows,
- ADGF_DEMO,
- GUIO1(GUIO_NONE)
- },
- },
- {
- // Hopkins FBI Win95 Spanish
- {
- "hopkins",
- 0,
- {
- {"Hopkins.exe", 0, "31c837378bb2e0b2573befea44956d3f", 421386},
- {"RES_VES.RES", 0, "77ee08896466ae88cc1af3bf1a0bf78c", 32882302},
- AD_LISTEND
- },
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
- },
- },
- {
- // Hopkins FBI Win95, provided by Strangerke
+ // Hopkins FBI BeOS, provided by Strangerke & Eriktorbjorn
{
"hopkins",
0,
{
- {"Hopkins.exe", 0, "277a5c144bf9ec7d8450ae37afb85090", 419281},
- {"RES_VAN.RES", 0, "f1693ac0b0859c8ecd8cb30ff43cf55f", 38296346},
+ {"ENG_VOI.RES", 0, "fa5789d1d8c19d160bce44a33e742fdf", 66860711},
AD_LISTEND
},
Common::EN_ANY,
- Common::kPlatformWindows,
+ Common::kPlatformBeOS,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
},
{
- // Hopkins FBI Win95, provided by alexbevi
- // Dec 15 1998 hopkins.exe
+ // Hopkins FBI Win95 Spanish
{
"hopkins",
0,
{
- {"Hopkins.exe", 0, "a587762dd50d5933e1c89f9975180764", 378694},
- {"RES_VAN.RES", 0, "f1693ac0b0859c8ecd8cb30ff43cf55f", 38296346},
+ {"RES_VES.RES", 0, "77ee08896466ae88cc1af3bf1a0bf78c", 32882302},
AD_LISTEND
},
- Common::EN_ANY,
+ Common::ES_ESP,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
},
{
- // Hopkins FBI Win95 EN, provided by greencis in bug #3612406
+ // Hopkins FBI Win95 UK, provided by Strangerke, alexbevi, greencis
{
"hopkins",
0,
{
- {"hopkins.exe", 0, "020690049fa1dfcd63a18fdafb139a0e", 421386},
{"RES_VAN.RES", 0, "f1693ac0b0859c8ecd8cb30ff43cf55f", 38296346},
AD_LISTEND
},
@@ -176,7 +105,6 @@ static const HopkinsGameDescription gameDescriptions[] = {
"hopkins",
0,
{
- {"hopkins.exe", 0, "3043fef0bd3bfeba8252647cd090ce09", 419281},
{"res_van.res", 0, "bf17c710e184a25a6c8e9d1d9503c38e", 32197685},
AD_LISTEND
},
@@ -192,7 +120,6 @@ static const HopkinsGameDescription gameDescriptions[] = {
"hopkins",
0,
{
- {"Hopkins.bin", 0, "71611380cb31744bf909b8319a65e6e6", 275844},
{"RES_VFR.RES", 0, "0490d4d1aa71075ebf71cc79e5dc7894", 39817945},
AD_LISTEND
},
@@ -208,7 +135,6 @@ static const HopkinsGameDescription gameDescriptions[] = {
"hopkins",
0,
{
- {"Hopkins.bin", 0, "71611380cb31744bf909b8319a65e6e6", 275844},
{"RES_VAN.RES", 0, "29414c05be8f9fe794c61572a65def12", 38832455},
AD_LISTEND
},
@@ -218,61 +144,53 @@ static const HopkinsGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
},
-
{
- // Hopkins FBI BeOS, provided by Strangerke
+ // Hopkins FBI Win95, French, provided by SylvainTV
{
"hopkins",
0,
{
- {"ENG_VOI.RES", 0, "fa5789d1d8c19d160bce44a33e742fdf", 66860711},
- {"Hopkins_ FBI", 0, "8940ce2e618c42691b66aad5d6c223b0", 757936},
+ {"RES_VFR.RES", 0, "b8a3849063c9eeefe80e82cfce1ad3cd", 39269361},
AD_LISTEND
},
- Common::EN_ANY,
- Common::kPlatformBeOS,
+ Common::FR_FRA,
+ Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
- },
+ },
{
- // Hopkins FBI BeOS, uninstalled, provided by eriktorbjorn
+ // Hopkins FBI Win95 Demo, provided by Strangerke
+ // CHECKME: No voice! a second file is required though... Also, it has multi-language support
{
"hopkins",
- 0,
+ "Win95 Demo",
{
- {"ENG_VOI.RES", 0, "fa5789d1d8c19d160bce44a33e742fdf", 66860711},
- {"Hopkins.pkg", 0, "72f97806dd3d5fc0c0eb24196f180618", 285017},
+ {"Hopkins.exe", 0, "0c9ebfe371f4dcf84a49f333f04839a0", 376897},
AD_LISTEND
},
Common::EN_ANY,
- Common::kPlatformBeOS,
- ADGF_NO_FLAGS,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
GUIO1(GUIO_NONE)
},
-
},
-
{
- // Hopkins FBI Win32, French uninstalled, provided by SylvainTV
+ // Hopkins FBI Win95 Polish Demo, provided by Strangerke
{
"hopkins",
- 0,
+ "Win95 Demo",
{
- {"Hopkins.exe", 0, "277a5c144bf9ec7d8450ae37afb85090", 419281},
- {"RES_VFR.RES", 0, "b8a3849063c9eeefe80e82cfce1ad3cd", 39269361},
+ {"RES_VAN.RES", 0, "8262cfba261c200af4451902689dffe0", 12233202},
AD_LISTEND
},
- Common::FR_FRA,
+ Common::PL_POL,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_DEMO,
GUIO1(GUIO_NONE)
},
-
},
-
-
{ AD_TABLE_END_MARKER }
};
diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp
index 6cdfbf47d1..8c944167ae 100644
--- a/engines/hopkins/dialogs.cpp
+++ b/engines/hopkins/dialogs.cpp
@@ -84,12 +84,17 @@ void DialogsManager::showOptionsDialog() {
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
filename = "OPTION.SPR";
else {
- if (_vm->_globals->_language == LANG_FR)
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
filename = "OPTIFR.SPR";
- else if (_vm->_globals->_language == LANG_EN)
+ break;
+ case LANG_EN:
filename = "OPTIAN.SPR";
- else if (_vm->_globals->_language == LANG_SP)
+ break;
+ case LANG_SP:
filename = "OPTIES.SPR";
+ break;
+ }
}
_vm->_globals->_optionDialogSpr = _vm->_fileIO->loadFile(filename);
@@ -505,7 +510,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;
@@ -691,7 +696,7 @@ void DialogsManager::showSaveLoad(SaveLoadMode mode) {
Graphics::Surface thumb8;
_vm->_saveLoad->convertThumb16To8(header._thumbnail, &thumb8);
- byte *thumb = (byte *)thumb8.pixels;
+ byte *thumb = (byte *)thumb8.getPixels();
int16 startPosX_ = _vm->_events->_startPos.x;
switch (slotNumber) {
diff --git a/engines/hopkins/events.cpp b/engines/hopkins/events.cpp
index 51c66c4f92..d0c1dcea4d 100644
--- a/engines/hopkins/events.cpp
+++ b/engines/hopkins/events.cpp
@@ -271,7 +271,7 @@ void EventsManager::pollEvents() {
_mouseButton = 0;
return;
default:
- break;
+ break;
}
}
diff --git a/engines/hopkins/globals.cpp b/engines/hopkins/globals.cpp
index 28f22ed99e..cd66a84b73 100644
--- a/engines/hopkins/globals.cpp
+++ b/engines/hopkins/globals.cpp
@@ -134,7 +134,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:
@@ -148,7 +148,7 @@ void Globals::setConfig() {
_language = LANG_SP;
break;
default:
- warning("Unknown language in internal language mapping");
+ error("Hopkins - SetConfig(): Unknown language in internal language mapping");
break;
}
// End of CHECKME
diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp
index ebc5cfa8da..05b8296b86 100644
--- a/engines/hopkins/graphics.cpp
+++ b/engines/hopkins/graphics.cpp
@@ -325,7 +325,7 @@ void GraphicsManager::loadPCX640(byte *surface, const Common::String &file, byte
// Copy out the dimensions and pixels of the decoded surface
_largeScreenFl = s->w > SCREEN_WIDTH;
- Common::copy((byte *)s->pixels, (byte *)s->pixels + (s->pitch * s->h), surface);
+ Common::copy((const byte *)s->getPixels(), (const byte *)s->getBasePtr(0, s->h), surface);
// Copy out the palette
const byte *palSrc = pcxDecoder.getPalette();
@@ -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);
}
}
@@ -1202,15 +1202,13 @@ void GraphicsManager::displayZones() {
void GraphicsManager::displayLines() {
Graphics::Surface *screenSurface = g_system->lockScreen();
- 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;
int y = _vm->_linesMan->_lineItem[lineIndex]._lineData[i+1];
if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT) {
- pixels[ y * screenSurface->w + x ] = 0xffff;
+ WRITE_UINT16(screenSurface->getBasePtr(x, y), 0xffff);
}
i += 2;
}
@@ -1230,7 +1228,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);
@@ -1361,7 +1359,7 @@ void GraphicsManager::drawCompressedSprite(byte *surface, const byte *srcData, i
_posYClipped = 0;
_clipX1 = 0;
_clipY1 = 0;
- if ((xp300 <= _minX) || (yp300 <= _minY) || (xp300 >= _maxX + 300) || (yp300 >= _maxY + 300))
+ if ((xp300 <= _minX) || (yp300 <= _minY) || (xp300 >= _maxX + 300) || (yp300 >= _maxY + 300))
return;
// Clipped values are greater or equal to zero, thanks to the previous test
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 2997320ba4..adf7580e6b 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -35,12 +35,9 @@
namespace Hopkins {
-HopkinsEngine *g_vm;
-
HopkinsEngine::HopkinsEngine(OSystem *syst, const HopkinsGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Hopkins") {
DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level");
- g_vm = this;
_animMan = new AnimationManager(this);
_computer = new ComputerManager(this);
_dialog = new DialogsManager(this);
@@ -95,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();
}
@@ -114,8 +111,6 @@ Common::Error HopkinsEngine::saveGameState(int slot, const Common::String &desc)
}
Common::Error HopkinsEngine::run() {
- _saveLoad->initSaves();
-
_globals->setConfig();
_fileIO->initCensorship();
initializeSystem();
@@ -156,36 +151,31 @@ bool HopkinsEngine::runWin95Demo() {
_events->_rateCounter = 0;
_globals->_eventMode = EVENTMODE_IGNORE;
_globals->_speed = 1;
-
- for (int i = 1; i < 50; i++) {
- _graphicsMan->copySurface(_graphicsMan->_backBuffer, 0, 0, 640, 440, _graphicsMan->_frontBuffer, 0, 0);
- _events->refreshScreenAndEvents();
- }
-
+ _events->delay(500);
_globals->_eventMode = EVENTMODE_DEFAULT;
if (_events->_rateCounter > 475)
_globals->_speed = 2;
if (_events->_rateCounter > 700)
_globals->_speed = 3;
- if (_startGameSlot == -1) {
- _graphicsMan->fadeOutLong();
- _globals->_eventMode = EVENTMODE_IGNORE;
- _globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
- }
+ if (_startGameSlot == -1)
+ _graphicsMan->fadeOutShort();
+
+ _globals->_eventMode = EVENTMODE_IGNORE;
+ _globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
_globals->_characterType = CHARACTER_HOPKINS;
_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
- memset(_globals->_saveData, 0, 2000);
+ memset(_globals->_saveData, 0, sizeof(Savegame));
_globals->_exitId = 0;
- if (_startGameSlot != -1)
- _saveLoad->loadGame(_startGameSlot);
-
if (getLanguage() != Common::PL_POL)
if (!displayAdultDisclaimer())
return Common::kNoError;
+ if (_startGameSlot != -1)
+ _saveLoad->loadGame(_startGameSlot);
+
for (;;) {
if (_globals->_exitId == 300)
_globals->_exitId = 0;
@@ -206,23 +196,31 @@ bool HopkinsEngine::runWin95Demo() {
switch (_globals->_exitId) {
case 1:
+ // Handles room: Apartment
_linesMan->setMaxLineIdx(40);
_globals->_characterMaxPosY = 435;
_objectsMan->sceneControl2("IM01", "IM01", "ANIM01", "IM01", 2, true);
break;
case 3:
+ // - Displays bank attack when leaving the apartment
+ // - Handles room: bottom of the apartment
if (!_globals->_saveData->_data[svBankAttackAnimPlayedFl]) {
_soundMan->playSound(3);
if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
_graphicsMan->loadImage("fond");
else {
- if (_globals->_language == LANG_FR)
+ switch (_globals->_language) {
+ case LANG_FR:
_graphicsMan->loadImage("fondfr");
- else if (_globals->_language == LANG_EN)
+ break;
+ case LANG_EN:
_graphicsMan->loadImage("fondan");
- else if (_globals->_language == LANG_SP)
+ break;
+ case LANG_SP:
_graphicsMan->loadImage("fondes");
+ break;
+ }
}
_graphicsMan->fadeInLong();
_events->delay(500);
@@ -240,7 +238,7 @@ bool HopkinsEngine::runWin95Demo() {
_soundMan->removeSample(2);
_soundMan->removeSample(3);
_soundMan->removeSample(4);
- _graphicsMan->fadeOutLong();
+ _graphicsMan->fadeOutShort();
_globals->_saveData->_data[svBankAttackAnimPlayedFl] = 1;
}
_linesMan->setMaxLineIdx(5);
@@ -249,12 +247,14 @@ bool HopkinsEngine::runWin95Demo() {
break;
case 4:
+ // Handle room: City map
_globals->_disableInventFl = true;
_objectsMan->handleCityMap();
_globals->_disableInventFl = false;
break;
case 5:
+ // Handle room: Outside the bank
_linesMan->setMaxLineIdx(5);
_globals->_characterMaxPosY = 455;
@@ -402,14 +402,27 @@ bool HopkinsEngine::runWin95Demo() {
break;
case 151:
- _soundMan->playSound(28);
- _globals->_eventMode = EVENTMODE_ALT; // CHECKME!
- _graphicsMan->clearScreen();
- _graphicsMan->clearPalette();
- _graphicsMan->loadImage("njour3a");
- _graphicsMan->fadeInLong();
- _events->delay(5000);
- _graphicsMan->fadeOutLong();
+ if (_fileIO->fileExists("JOUR3A.ANM")) {
+ // The Polish demo uses the animation file than the complete versions
+ _soundMan->playSound(16);
+ _globals->_eventMode = EVENTMODE_IGNORE;
+
+ _graphicsMan->clearScreen();
+ _graphicsMan->clearPalette();
+ _graphicsMan->_fadingFl = true;
+ _animMan->playAnim("JOUR3A.ANM", "JOUR3A.ANM", 12, 12, 2000);
+ } else {
+ // The other demos only display a nag screen
+ _soundMan->playSound(28);
+ _globals->_eventMode = EVENTMODE_ALT; // CHECKME!
+ _graphicsMan->clearScreen();
+ _graphicsMan->clearPalette();
+ _graphicsMan->loadImage("njour3a");
+ _graphicsMan->fadeInLong();
+ _events->delay(5000);
+ _graphicsMan->fadeOutLong();
+ }
+
_globals->_exitId = 300;
_globals->_eventMode = EVENTMODE_DEFAULT;
break;
@@ -457,7 +470,7 @@ bool HopkinsEngine::runLinuxDemo() {
_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
_globals->_characterType = CHARACTER_HOPKINS;
_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
- memset(_globals->_saveData, 0, 2000);
+ memset(_globals->_saveData, 0, sizeof(Savegame));
_globals->_exitId = 0;
if (_startGameSlot != -1)
@@ -513,12 +526,17 @@ bool HopkinsEngine::runLinuxDemo() {
if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
_graphicsMan->loadImage("fond");
else {
- if (_globals->_language == LANG_FR)
+ switch (_globals->_language) {
+ case LANG_FR:
_graphicsMan->loadImage("fondfr");
- else if (_globals->_language == LANG_EN)
+ break;
+ case LANG_EN:
_graphicsMan->loadImage("fondan");
- else if (_globals->_language == LANG_SP)
+ break;
+ case LANG_SP:
_graphicsMan->loadImage("fondes");
+ break;
+ }
}
_graphicsMan->fadeInLong();
_events->delay(500);
@@ -785,14 +803,14 @@ bool HopkinsEngine::runFull() {
if (_startGameSlot == -1) {
if (getPlatform() == Common::kPlatformLinux) {
- _graphicsMan->loadImage("H2");
- _graphicsMan->fadeInLong();
- _events->delay(500);
- _graphicsMan->fadeOutLong();
- _globals->_speed = 2;
- _globals->_eventMode = EVENTMODE_IGNORE;
- _graphicsMan->_fadingFl = true;
- _animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200);
+ _graphicsMan->loadImage("H2");
+ _graphicsMan->fadeInLong();
+ _events->delay(500);
+ _graphicsMan->fadeOutLong();
+ _globals->_speed = 2;
+ _globals->_eventMode = EVENTMODE_IGNORE;
+ _graphicsMan->_fadingFl = true;
+ _animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200);
} else {
_animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200);
_graphicsMan->fadeOutLong();
@@ -818,7 +836,7 @@ bool HopkinsEngine::runFull() {
_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
_globals->_characterType = CHARACTER_HOPKINS;
_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
- memset(_globals->_saveData, 0, 2000);
+ memset(_globals->_saveData, 0, sizeof(Savegame));
_globals->_exitId = 0;
@@ -859,12 +877,17 @@ bool HopkinsEngine::runFull() {
if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
_graphicsMan->loadImage("fond");
else {
- if (_globals->_language == LANG_FR)
+ switch (_globals->_language) {
+ case LANG_FR:
_graphicsMan->loadImage("fondfr");
- else if (_globals->_language == LANG_EN)
+ break;
+ case LANG_EN:
_graphicsMan->loadImage("fondan");
- else if (_globals->_language == LANG_SP)
+ break;
+ case LANG_SP:
_graphicsMan->loadImage("fondes");
+ break;
+ }
}
_graphicsMan->fadeInLong();
_events->delay(500);
@@ -1125,12 +1148,14 @@ bool HopkinsEngine::runFull() {
break;
case 30:
+ // Shooting
_linesMan->setMaxLineIdx(15);
_globals->_characterMaxPosY = 440;
_objectsMan->sceneControl2("IM30", "IM30", "ANIM30", "IM30", 24, false);
break;
case 31:
+ // Shooting target
_objectsMan->sceneControl("IM31", "IM31", "ANIM31", "IM31", 10, true);
break;
@@ -1145,6 +1170,7 @@ bool HopkinsEngine::runFull() {
break;
case 34:
+ // In the airport, before the flight cut-scene
_objectsMan->sceneControl("IM34", "IM34", "ANIM34", "IM34", 2, false);
break;
@@ -1175,6 +1201,7 @@ bool HopkinsEngine::runFull() {
}
case 50:
+ // Flight cut scene
playPlaneCutscene();
_globals->_exitId = 51;
break;
@@ -1634,8 +1661,8 @@ void HopkinsEngine::playIntro() {
_graphicsMan->setColorPercentage(253, 100, 100, 100);
_graphicsMan->setColorPercentage(251, 100, 100, 100);
_graphicsMan->setColorPercentage(254, 0, 0, 0);
- for (int i = 0; i <= 4; i++)
- _events->refreshScreenAndEvents();
+
+ _events->delay(500);
_globals->_eventMode = EVENTMODE_IGNORE;
_graphicsMan->fadeInLong();
@@ -1896,10 +1923,7 @@ void HopkinsEngine::bombExplosion() {
}
void HopkinsEngine::restoreSystem() {
- // If the game isn't alerady trying to quit, flag that quitting is needed
- if (!shouldQuit())
- quitGame();
-
+ quitGame();
_events->refreshEvents();
}
@@ -2224,6 +2248,8 @@ void HopkinsEngine::playPlaneCutscene() {
if (!_events->_escKeyFl) {
_graphicsMan->_fadingFl = true;
_animMan->playAnim("PARA00A.ANM", "PARA00.ANM", 9, 9, 9);
+ } else {
+ _graphicsMan->fadeOutShort();
}
_events->_escKeyFl = false;
diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h
index 777fd1c335..d8c30e5004 100644
--- a/engines/hopkins/hopkins.h
+++ b/engines/hopkins/hopkins.h
@@ -164,6 +164,7 @@ public:
Common::Platform getPlatform() const;
uint16 getVersion() const;
bool getIsDemo() const;
+ const Common::String &getTargetName() const;
int getRandomNumber(int maxNumber);
Common::String generateSaveName(int slotNumber);
@@ -183,9 +184,6 @@ public:
virtual void syncSoundSettings();
};
-// Global reference to the HopkinsEngine object
-extern HopkinsEngine *g_vm;
-
} // End of namespace Hopkins
#endif /* HOPKINS_HOPKINS_H */
diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp
index 767b599d68..aa708fdfb2 100644
--- a/engines/hopkins/lines.cpp
+++ b/engines/hopkins/lines.cpp
@@ -975,7 +975,6 @@ int LinesManager::computeRouteIdx(int lineIdx, int dataIdx, int fromX, int fromY
curX = destX;
int lineIdxLeft = -1;
- loopCond = false;
do {
--curX;
if (checkCollisionLine(curX, destY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx)) {
diff --git a/engines/hopkins/menu.cpp b/engines/hopkins/menu.cpp
index 455f4ad8d4..048d1b2cef 100644
--- a/engines/hopkins/menu.cpp
+++ b/engines/hopkins/menu.cpp
@@ -69,23 +69,37 @@ int MenuManager::menu() {
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
_vm->_graphicsMan->loadImage("MENU");
- else if (_vm->_globals->_language == LANG_EN)
- _vm->_graphicsMan->loadImage("MENUAN");
- else if (_vm->_globals->_language == LANG_FR)
- _vm->_graphicsMan->loadImage("MENUFR");
- else if (_vm->_globals->_language == LANG_SP)
- _vm->_graphicsMan->loadImage("MENUES");
+ else {
+ switch (_vm->_globals->_language) {
+ case LANG_EN:
+ _vm->_graphicsMan->loadImage("MENUAN");
+ break;
+ case LANG_FR:
+ _vm->_graphicsMan->loadImage("MENUFR");
+ break;
+ case LANG_SP:
+ _vm->_graphicsMan->loadImage("MENUES");
+ break;
+ }
+ }
_vm->_graphicsMan->fadeInLong();
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
spriteData = _vm->_objectsMan->loadSprite("MENU.SPR");
- else if (_vm->_globals->_language == LANG_EN)
- spriteData = _vm->_objectsMan->loadSprite("MENUAN.SPR");
- else if (_vm->_globals->_language == LANG_FR)
- spriteData = _vm->_objectsMan->loadSprite("MENUFR.SPR");
- else if (_vm->_globals->_language == LANG_SP)
- spriteData = _vm->_objectsMan->loadSprite("MENUES.SPR");
+ else {
+ switch (_vm->_globals->_language) {
+ case LANG_EN:
+ spriteData = _vm->_objectsMan->loadSprite("MENUAN.SPR");
+ break;
+ case LANG_FR:
+ spriteData = _vm->_objectsMan->loadSprite("MENUFR.SPR");
+ break;
+ case LANG_SP:
+ spriteData = _vm->_objectsMan->loadSprite("MENUES.SPR");
+ break;
+ }
+ }
_vm->_events->mouseOn();
_vm->_events->changeMouseCursor(0);
diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp
index 45b4885c90..b0dea7e6d1 100644
--- a/engines/hopkins/saveload.cpp
+++ b/engines/hopkins/saveload.cpp
@@ -43,39 +43,38 @@ SaveLoadManager::SaveLoadManager(HopkinsEngine *vm) {
}
bool SaveLoadManager::save(const Common::String &file, const void *buf, size_t n) {
- Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(file);
+ Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(file);
- if (f) {
- size_t bytesWritten = f->write(buf, n);
- f->finalize();
- delete f;
+ if (savefile) {
+ size_t bytesWritten = savefile->write(buf, n);
+ savefile->finalize();
+ delete savefile;
return bytesWritten == n;
} else
return false;
}
+bool SaveLoadManager::saveExists(const Common::String &file) {
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
+ bool result = savefile != NULL;
+ delete savefile;
+ return result;
+}
+
// Save File
bool SaveLoadManager::saveFile(const Common::String &file, const void *buf, size_t n) {
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 *f = g_system->getSavefileManager()->openForLoading(file);
- if (f == NULL)
- error("Error openinig file - %s", file.c_str());
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
+ if (savefile == NULL)
+ error("Error opening file - %s", file.c_str());
- int32 filesize = f->size();
- f->read(buf, filesize);
- delete f;
+ int32 filesize = savefile->size();
+ savefile->read(buf, filesize);
+ delete savefile;
}
bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header) {
@@ -215,13 +214,13 @@ Common::Error SaveLoadManager::loadGame(int slot) {
bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header) {
// Try and open the save file for reading
- Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
- g_vm->generateSaveName(slot));
- if (!saveFile)
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(
+ _vm->generateSaveName(slot));
+ if (!savefile)
return false;
- bool result = readSavegameHeader(saveFile, header);
- delete saveFile;
+ bool result = readSavegameHeader(savefile, header);
+ delete savefile;
return result;
}
@@ -234,14 +233,14 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) {
Graphics::Surface thumb8;
thumb8.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
- _vm->_graphicsMan->reduceScreenPart(_vm->_graphicsMan->_frontBuffer, (byte *)thumb8.pixels,
+ _vm->_graphicsMan->reduceScreenPart(_vm->_graphicsMan->_frontBuffer, (byte *)thumb8.getPixels(),
_vm->_events->_startPos.x, 20, SCREEN_WIDTH, SCREEN_HEIGHT - 40, 80);
// Convert the 8-bit pixel to 16 bit surface
s->create(w, h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- const byte *srcP = (const byte *)thumb8.pixels;
- uint16 *destP = (uint16 *)s->pixels;
+ const byte *srcP = (const byte *)thumb8.getPixels();
+ uint16 *destP = (uint16 *)s->getPixels();
for (int yp = 0; yp < h; ++yp) {
// Copy over the line, using the source pixels as lookups into the pixels palette
@@ -259,6 +258,10 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) {
}
void SaveLoadManager::syncSavegameData(Common::Serializer &s, int version) {
+ // The brief version 3 had the highscores embedded. They're in a separate file now, so skip
+ if (version == 3 && s.isLoading())
+ s.skip(100);
+
s.syncBytes(&_vm->_globals->_saveData->_data[0], 2050);
syncCharacterLocation(s, _vm->_globals->_saveData->_cloneHopkins);
syncCharacterLocation(s, _vm->_globals->_saveData->_realHopkins);
@@ -296,8 +299,8 @@ void SaveLoadManager::convertThumb16To8(Graphics::Surface *thumb16, Graphics::Su
pixelFormat16.colorToRGB(p, paletteR[palIndex], paletteG[palIndex], paletteB[palIndex]);
}
- const uint16 *srcP = (const uint16 *)thumb16->pixels;
- byte *destP = (byte *)thumb8->pixels;
+ const uint16 *srcP = (const uint16 *)thumb16->getPixels();
+ byte *destP = (byte *)thumb8->getPixels();
for (int yp = 0; yp < thumb16->h; ++yp) {
const uint16 *lineSrcP = srcP;
diff --git a/engines/hopkins/saveload.h b/engines/hopkins/saveload.h
index 221a445fd2..5b77c11f12 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 4
struct hopkinsSavegameHeader {
uint8 _version;
@@ -56,14 +56,14 @@ private:
public:
SaveLoadManager(HopkinsEngine *vm);
- void initSaves();
+ bool saveExists(const Common::String &file);
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);
static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header);
void writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header);
- static bool readSavegameHeader(int slot, hopkinsSavegameHeader &header);
+ bool readSavegameHeader(int slot, hopkinsSavegameHeader &header);
Common::Error saveGame(int slot, const Common::String &saveName);
Common::Error loadGame(int slot);
diff --git a/engines/hopkins/script.cpp b/engines/hopkins/script.cpp
index c39273203d..09b0641a12 100644
--- a/engines/hopkins/script.cpp
+++ b/engines/hopkins/script.cpp
@@ -148,12 +148,18 @@ int ScriptManager::handleOpcode(const byte *dataP) {
_vm->_soundMan->mixVoice(635, 4, displayedTxtFl);
} else {
int textPosX = READ_LE_INT16(dataP + 9);
- if (_vm->_globals->_language == LANG_FR && !_vm->_soundMan->_textOffFl)
- _vm->_fontMan->initTextBuffers(9, mesgId, "OBJET1.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
- else if (_vm->_globals->_language == LANG_EN && !_vm->_soundMan->_textOffFl)
- _vm->_fontMan->initTextBuffers(9, mesgId, "OBJETAN.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
- else if (_vm->_globals->_language == LANG_SP && !_vm->_soundMan->_textOffFl) {
- _vm->_fontMan->initTextBuffers(9, mesgId, "OBJETES.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
+ if (!_vm->_soundMan->_textOffFl) {
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
+ _vm->_fontMan->initTextBuffers(9, mesgId, "OBJET1.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
+ break;
+ case LANG_EN:
+ _vm->_fontMan->initTextBuffers(9, mesgId, "OBJETAN.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
+ break;
+ case LANG_SP:
+ _vm->_fontMan->initTextBuffers(9, mesgId, "OBJETES.TXT", 2 * textPosX, 60, 6, dataP[7], 253);
+ break;
+ }
}
bool displayedTxtFl = false;
@@ -536,6 +542,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 12:
+ // Bank - negotiations between Hopkins and one of the killers
_vm->_fontMan->hideText(9);
_vm->_events->refreshScreenAndEvents();
_vm->_events->refreshScreenAndEvents();
@@ -543,6 +550,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 13:
+ // Bank - after negotiations, Hopkins enters the bank
_vm->_events->_mouseButton = _vm->_events->_curMouseButton;
_vm->_globals->_disableInventFl = true;
_vm->_graphicsMan->fadeOutLong();
@@ -553,9 +561,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
_vm->_graphicsMan->endDisplayBob();
_vm->_objectsMan->clearScreen();
- if ((_vm->getPlatform() == Common::kPlatformWindows) && _vm->getIsDemo()) {
- _vm->_graphicsMan->fadeOutLong();
- } else {
+ if ((_vm->getPlatform() != Common::kPlatformWindows) || !_vm->getIsDemo()) {
_vm->_soundMan->playSoundFile("SOUND17.WAV");
_vm->_graphicsMan->_fadingFl = true;
_vm->_animMan->playSequence2("HELICO.SEQ", 10, 4, 10);
@@ -615,10 +621,6 @@ int ScriptManager::handleOpcode(const byte *dataP) {
_vm->_graphicsMan->_fadingFl = true;
_vm->_animMan->playSequence2("ASSOM.SEQ", 10, 4, 500);
_vm->_soundMan->_specialSoundNum = 0;
-
- if ((_vm->getPlatform() == Common::kPlatformWindows) && _vm->getIsDemo())
- _vm->_graphicsMan->fadeOutLong();
-
_vm->_globals->_disableInventFl = false;
_vm->_objectsMan->_helicopterFl = true;
break;
@@ -1221,6 +1223,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 88:
+ // Shooting target - Shooting at target
if (_vm->_globals->_saveData->_data[svField183] == 1) {
_vm->_objectsMan->setBobAnimDataIdx(1, 0);
_vm->_objectsMan->setBobAnimDataIdx(2, 0);
@@ -1298,6 +1301,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 90:
+ // Shooting target - Using the level
_vm->_soundMan->playSoundFile("SOUND52.WAV");
if (!_vm->_globals->_saveData->_data[svField186]) {
_vm->_animMan->playSequence("CIB5A.SEQ", 1, 12, 1, false, false);
@@ -1984,6 +1988,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 216:
+ // Discuss with pilot just before Flight cutscene
_vm->_globals->_introSpeechOffFl = true;
_vm->_talkMan->startAnimatedCharacterDialogue("aviat1.pe2");
_vm->_globals->_introSpeechOffFl = false;
diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp
index bf816c08a4..92c5f51462 100644
--- a/engines/hopkins/sound.cpp
+++ b/engines/hopkins/sound.cpp
@@ -520,12 +520,19 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
filename = "ENG_VOI.RES";
// Win95 and Linux versions uses another set of names
- else if (_vm->_globals->_language == LANG_FR)
- filename = "RES_VFR.RES";
- else if (_vm->_globals->_language == LANG_EN)
- filename = "RES_VAN.RES";
- else if (_vm->_globals->_language == LANG_SP)
- filename = "RES_VES.RES";
+ else {
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
+ filename = "RES_VFR.RES";
+ break;
+ case LANG_EN:
+ filename = "RES_VAN.RES";
+ break;
+ case LANG_SP:
+ filename = "RES_VES.RES";
+ break;
+ }
+ }
catPos = _vm->_fileIO->_catalogPos;
catLen = _vm->_fileIO->_catalogSize;
@@ -535,12 +542,19 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
filename = "ENG_VOI.RES";
// Win95 and Linux versions uses another set of names
- else if (_vm->_globals->_language == LANG_FR)
- filename = "RES_VFR.RES";
- else if (_vm->_globals->_language == LANG_EN)
- filename = "RES_VAN.RES";
- else if (_vm->_globals->_language == LANG_SP)
- filename = "RES_VES.RES";
+ else {
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
+ filename = "RES_VFR.RES";
+ break;
+ case LANG_EN:
+ filename = "RES_VAN.RES";
+ break;
+ case LANG_SP:
+ filename = "RES_VES.RES";
+ break;
+ }
+ }
catPos = _vm->_fileIO->_catalogPos;
catLen = _vm->_fileIO->_catalogSize;
@@ -550,12 +564,19 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
filename = "ENG_VOI.RES";
// Win95 and Linux versions uses another set of names
- else if (_vm->_globals->_language == LANG_FR)
- filename = "RES_VFR.RES";
- else if (_vm->_globals->_language == LANG_EN)
- filename = "RES_VAN.RES";
- else if (_vm->_globals->_language == LANG_SP)
- filename = "RES_VES.RES";
+ else {
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
+ filename = "RES_VFR.RES";
+ break;
+ case LANG_EN:
+ filename = "RES_VAN.RES";
+ break;
+ case LANG_SP:
+ filename = "RES_VES.RES";
+ break;
+ }
+ }
catPos = _vm->_fileIO->_catalogPos;
catLen = _vm->_fileIO->_catalogSize;
diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp
index 736ec9865c..d218dd27b5 100644
--- a/engines/hopkins/talk.cpp
+++ b/engines/hopkins/talk.cpp
@@ -68,12 +68,17 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename)
getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer);
getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer);
getStringFromBuffer(20, _answersFilename, (const char *)_characterBuffer);
- if (_vm->_globals->_language == LANG_FR) {
+
+ switch (_vm->_globals->_language) {
+ case LANG_FR:
_answersFilename = _questionsFilename = "RUE.TXT";
- } else if (_vm->_globals->_language == LANG_EN) {
+ break;
+ case LANG_EN:
_answersFilename = _questionsFilename = "RUEAN.TXT";
- } else if (_vm->_globals->_language == LANG_SP) {
+ break;
+ case LANG_SP:
_answersFilename = _questionsFilename = "RUEES.TXT";
+ break;
}
_dialogueMesgId1 = READ_LE_INT16((uint16 *)_characterBuffer + 40);
_paletteBufferIdx = 20 * READ_LE_INT16((uint16 *)_characterBuffer + 42) + 110;
@@ -261,7 +266,7 @@ int TalkManager::dialogQuestion(bool animatedFl) {
int retVal = -1;
bool loopCond = false;
- do {
+ do {
int mousePosY = _vm->_events->getMouseY();
if (sentence1PosY < mousePosY && mousePosY < (sentence2PosY - 1)) {
_vm->_fontMan->setOptimalColor(6, 7, 8, 5);
diff --git a/engines/hugo/configure.engine b/engines/hugo/configure.engine
new file mode 100644
index 0000000000..9ab5c54e1e
--- /dev/null
+++ b/engines/hugo/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine hugo "Hugo Trilogy" yes
diff --git a/engines/hugo/dialogs.cpp b/engines/hugo/dialogs.cpp
index 0f07d52aee..23e04dc479 100644
--- a/engines/hugo/dialogs.cpp
+++ b/engines/hugo/dialogs.cpp
@@ -34,8 +34,10 @@
namespace Hugo {
-TopMenu::TopMenu(HugoEngine *vm) : Dialog(0, 0, kMenuWidth, kMenuHeight), _arrayBmp(0), _arraySize(0),
- _vm(vm) {
+TopMenu::TopMenu(HugoEngine *vm) : Dialog(0, 0, kMenuWidth, kMenuHeight), _vm(vm) {
+ _arrayBmp = nullptr;
+ _arraySize = 0;
+
init();
}
@@ -140,12 +142,10 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
_arrayBmp[i * 2] = bitmapSrc->convertTo(g_system->getOverlayFormat());
_arrayBmp[i * 2 + 1] = new Graphics::Surface();
_arrayBmp[i * 2 + 1]->create(_arrayBmp[i * 2]->w * 2, _arrayBmp[i * 2]->h * 2, g_system->getOverlayFormat());
- byte *src = (byte *)_arrayBmp[i * 2]->pixels;
- byte *dst = (byte *)_arrayBmp[i * 2 + 1]->pixels;
for (int j = 0; j < _arrayBmp[i * 2]->h; j++) {
- src = (byte *)_arrayBmp[i * 2]->getBasePtr(0, j);
- dst = (byte *)_arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2);
+ byte *src = (byte *)_arrayBmp[i * 2]->getBasePtr(0, j);
+ byte *dst = (byte *)_arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2);
for (int k = _arrayBmp[i * 2]->w; k > 0; k--) {
for (int m = _arrayBmp[i * 2]->format.bytesPerPixel; m > 0; m--) {
*dst++ = *src++;
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index fbe39b3a0c..3dc9c9a1c3 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -75,13 +75,13 @@ static const byte stdMouseCursor[] = {
Screen::Screen(HugoEngine *vm) : _vm(vm) {
- _mainPalette = 0;
- _curPalette = 0;
+ _mainPalette = nullptr;
+ _curPalette = nullptr;
_dlAddIndex = 0;
_dlRestoreIndex = 0;
for (int i = 0; i < kNumFonts; i++) {
- _arrayFont[i] = 0;
+ _arrayFont[i] = nullptr;
fontLoadedFl[i] = false;
}
for (int i = 0; i < kBlitListSize; i++) {
@@ -100,6 +100,8 @@ Screen::Screen(HugoEngine *vm) : _vm(vm) {
_dlRestoreList[i]._dx = 0;
_dlRestoreList[i]._dy = 0;
}
+ _fnt = 0;
+ _paletteSize = 0;
}
Screen::~Screen() {
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index e58c2e57d6..aa128048af 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -246,13 +246,13 @@ SoundPtr FileManager::getSound(const int16 sound, uint16 *size) {
// No more to do if SILENCE (called for cleanup purposes)
if (sound == _vm->_soundSilence)
- return 0;
+ return nullptr;
// Open sounds file
Common::File fp; // Handle to SOUND_FILE
if (!fp.open(getSoundFilename())) {
warning("Hugo Error: File not found %s", getSoundFilename());
- return 0;
+ return nullptr;
}
if (!_hasReadHeader) {
@@ -519,6 +519,7 @@ void FileManager::readBootFile() {
ofp.read(_vm->_boot._pbswitch, sizeof(_vm->_boot._pbswitch));
ofp.read(_vm->_boot._distrib, sizeof(_vm->_boot._distrib));
_vm->_boot._exitLen = ofp.readUint16LE();
+ ofp.close();
byte *p = (byte *)&_vm->_boot;
@@ -527,7 +528,6 @@ void FileManager::readBootFile() {
checksum ^= p[i];
p[i] ^= s_bootCypher[i % s_bootCypherLen];
}
- ofp.close();
if (checksum) {
Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index bcf06055f8..88e2e4372b 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -46,11 +46,11 @@
namespace Hugo {
-HugoEngine *HugoEngine::s_Engine = 0;
+HugoEngine *HugoEngine::s_Engine = nullptr;
HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(syst), _gameDescription(gd),
- _hero(0), _heroImage(0), _defltTunes(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0),
- _screenStates(0), _numStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0), _episode(0)
+ _hero(nullptr), _heroImage(0), _defltTunes(nullptr), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0),
+ _screenStates(nullptr), _numStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0), _episode(nullptr)
{
_system = syst;
DebugMan.addDebugChannel(kDebugSchedule, "Schedule", "Script Schedule debug level");
@@ -66,17 +66,17 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy
_console = new HugoConsole(this);
_rnd = 0;
-
- _screen = NULL;
- _mouse = NULL;
- _inventory = NULL;
- _parser = NULL;
- _route = NULL;
- _sound = NULL;
- _intro = NULL;
- _object = NULL;
- _text = NULL;
- _topMenu = NULL;
+
+ _screen = nullptr;
+ _mouse = nullptr;
+ _inventory = nullptr;
+ _parser = nullptr;
+ _route = nullptr;
+ _sound = nullptr;
+ _intro = nullptr;
+ _object = nullptr;
+ _text = nullptr;
+ _topMenu = nullptr;
_status._storyModeFl = false;
_status._gameOverFl = false;
_status._lookFl = false;
@@ -93,6 +93,26 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy
_gameType = kGameTypeNone;
_platform = Common::kPlatformUnknown;
_packedFl = false;
+
+ _numVariant = 0;
+ _gameVariant = kGameVariantNone;
+ _normalTPS = 0;
+ _screenPtr = nullptr;
+ _config._musicFl = true;
+ _config._soundFl = true;
+ _config._turboFl = false;
+ _look = 0;
+ _take = 0;
+ _drop = 0;
+ _maze._enabledFl = false;
+ _maze._size = 0;
+ _maze._x1 = _maze._y1 = _maze._x2 = _maze._y2 = _maze._x3 = _maze._x4 = 0;
+ _maze._firstScreenIndex = 0;
+ _boot._checksum = 0;
+ _boot._registered = kRegShareware;
+ _boot._exitLen = 0;
+ _file = nullptr;
+ _scheduler = nullptr;
}
HugoEngine::~HugoEngine() {
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index 9f495a9037..6adb5f95d0 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -106,7 +106,8 @@ enum GameVariant {
kGameVariantH3Win,
kGameVariantH1Dos,
kGameVariantH2Dos,
- kGameVariantH3Dos
+ kGameVariantH3Dos,
+ kGameVariantNone
};
enum HugoDebugChannels {
@@ -259,7 +260,7 @@ public:
// Used by the qsort function
static HugoEngine &get() {
- assert(s_Engine != 0);
+ assert(s_Engine != nullptr);
return *s_Engine;
}
diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp
index 505e356049..5db6c39078 100644
--- a/engines/hugo/intro.cpp
+++ b/engines/hugo/intro.cpp
@@ -39,9 +39,10 @@
namespace Hugo {
-IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm), _introX(0), _introY(0) {
+IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm) {
_introXSize = 0;
_introTicks = 0;
+ _introX = _introY = nullptr;
}
IntroHandler::~IntroHandler() {
@@ -74,6 +75,7 @@ void IntroHandler::loadIntroData(Common::SeekableReadStream &in) {
void IntroHandler::freeIntroData() {
free(_introX);
free(_introY);
+ _introX = _introY = nullptr;
}
intro_v1d::intro_v1d(HugoEngine *vm) : IntroHandler(vm) {
@@ -89,11 +91,7 @@ void intro_v1d::preNewGame() {
void intro_v1d::introInit() {
_introState = 0;
_introTicks = 0;
- _surf.w = 320;
- _surf.h = 200;
- _surf.pixels = _vm->_screen->getFrontBuffer();
- _surf.pitch = 320;
- _surf.format = Graphics::PixelFormat::createFormatCLUT8();
+ _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8());
_vm->_screen->displayList(kDisplayInit);
}
@@ -243,11 +241,7 @@ void intro_v2d::preNewGame() {
void intro_v2d::introInit() {
_vm->_screen->displayList(kDisplayInit);
_vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen
- _surf.w = 320;
- _surf.h = 200;
- _surf.pixels = _vm->_screen->getFrontBuffer();
- _surf.pitch = 320;
- _surf.format = Graphics::PixelFormat::createFormatCLUT8();
+ _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8());
char buffer[128];
@@ -289,11 +283,7 @@ void intro_v3d::preNewGame() {
void intro_v3d::introInit() {
_vm->_screen->displayList(kDisplayInit);
_vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen
- _surf.w = 320;
- _surf.h = 200;
- _surf.pixels = _vm->_screen->getFrontBuffer();
- _surf.pitch = 320;
- _surf.format = Graphics::PixelFormat::createFormatCLUT8();
+ _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8());
char buffer[128];
if (_vm->_boot._registered)
diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp
index c2495beadb..03df997866 100644
--- a/engines/hugo/inventory.cpp
+++ b/engines/hugo/inventory.cpp
@@ -44,7 +44,8 @@ namespace Hugo {
static const int kMaxDisp = (kXPix / kInvDx); // Max icons displayable
-InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm), _invent(0) {
+InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm) {
+ _invent = nullptr;
_firstIconId = 0;
_inventoryState = kInventoryOff; // Inventory icon bar state
_inventoryHeight = 0; // Inventory icon bar pos
@@ -62,6 +63,7 @@ void InventoryHandler::setInventoryState(Istate state) {
void InventoryHandler::freeInvent() {
free(_invent);
+ _invent = nullptr;
}
int16 InventoryHandler::getInventoryObjId() const {
diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp
index ae286c8afb..4ef3db3e2b 100644
--- a/engines/hugo/mouse.cpp
+++ b/engines/hugo/mouse.cpp
@@ -45,7 +45,8 @@
namespace Hugo {
-MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm), _hotspots(0) {
+MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm) {
+ _hotspots = nullptr;
_leftButtonFl = false;
_rightButtonFl = false;
_jumpExitFl = false; // Can't jump to a screen exit
@@ -83,6 +84,7 @@ void MouseHandler::setMouseY(int y) {
void MouseHandler::freeHotspots() {
free(_hotspots);
+ _hotspots = nullptr;
}
bool MouseHandler::getJumpExitFl() const {
@@ -169,7 +171,7 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in
_vm->_object->useObject(objId); // Use status.objid on object
} else { // Clicked over viewport object
Object *obj = &_vm->_object->_objects[objId];
- int16 x = 0, y = 0;
+ int16 x, y;
switch (obj->_viewx) { // Where to walk to
case -1: // Walk to object position
if (_vm->_object->findObjectSpace(obj, &x, &y))
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index 7b4783e4d8..44f46d2d79 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -44,7 +44,9 @@
namespace Hugo {
-ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0), _uses(0) {
+ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm) {
+ _uses = nullptr;
+ _objects = nullptr;
_numObj = 0;
_objCount = 0;
_usesSize = 0;
@@ -249,47 +251,49 @@ void ObjectHandler::lookObject(Object *obj) {
void ObjectHandler::freeObjects() {
debugC(1, kDebugObject, "freeObjects");
- if (_vm->_hero != 0 && _vm->_hero->_seqList[0]._seqPtr != 0) {
+ if (_vm->_hero != nullptr && _vm->_hero->_seqList[0]._seqPtr != nullptr) {
// Free all sequence lists and image data
for (int16 i = 0; i < _numObj; i++) {
Object *obj = &_objects[i];
for (int16 j = 0; j < obj->_seqNumb; j++) {
Seq *seq = obj->_seqList[j]._seqPtr;
Seq *next;
- if (seq == 0) // Failure during database load
+ if (seq == nullptr) // Failure during database load
break;
- if (seq->_imagePtr != 0) {
+ if (seq->_imagePtr != nullptr) {
free(seq->_imagePtr);
- seq->_imagePtr = 0;
+ seq->_imagePtr = nullptr;
}
seq = seq->_nextSeqPtr;
while (seq != obj->_seqList[j]._seqPtr) {
- if (seq->_imagePtr != 0) {
+ if (seq->_imagePtr != nullptr) {
free(seq->_imagePtr);
- seq->_imagePtr = 0;
+ seq->_imagePtr = nullptr;
}
next = seq->_nextSeqPtr;
free(seq);
seq = next;
}
free(seq);
+ seq = nullptr;
}
}
}
- if (_uses) {
+ if (_uses != nullptr) {
for (int16 i = 0; i < _usesSize; i++)
free(_uses[i]._targets);
free(_uses);
+ _uses = nullptr;
}
for (int16 i = 0; i < _objCount; i++) {
free(_objects[i]._stateDataIndex);
- _objects[i]._stateDataIndex = 0;
+ _objects[i]._stateDataIndex = nullptr;
}
free(_objects);
- _objects = 0;
+ _objects = nullptr;
}
/**
@@ -358,7 +362,7 @@ void ObjectHandler::showTakeables() {
* Find a clear space around supplied object that hero can walk to
*/
bool ObjectHandler::findObjectSpace(Object *obj, int16 *destx, int16 *desty) {
- debugC(1, kDebugObject, "findObjectSpace(obj, %d, %d)", *destx, *desty);
+ debugC(1, kDebugObject, "findObjectSpace(...)");
Seq *curImage = obj->_currImagePtr;
int16 y = obj->_y + curImage->_y2 - 1;
@@ -414,7 +418,7 @@ void ObjectHandler::readUse(Common::ReadStream &in, Uses &curUse) {
*/
void ObjectHandler::loadObjectUses(Common::ReadStream &in) {
Uses tmpUse;
- tmpUse._targets = 0;
+ tmpUse._targets = nullptr;
//Read _uses
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
@@ -430,7 +434,7 @@ void ObjectHandler::loadObjectUses(Common::ReadStream &in) {
else {
readUse(in, tmpUse);
free(tmpUse._targets);
- tmpUse._targets = 0;
+ tmpUse._targets = nullptr;
}
}
}
@@ -442,7 +446,7 @@ void ObjectHandler::readObject(Common::ReadStream &in, Object &curObject) {
uint16 numSubElem = in.readUint16BE();
if (numSubElem == 0)
- curObject._stateDataIndex = 0;
+ curObject._stateDataIndex = nullptr;
else
curObject._stateDataIndex = (uint16 *)malloc(sizeof(uint16) * numSubElem);
for (int j = 0; j < numSubElem; j++)
@@ -453,16 +457,16 @@ void ObjectHandler::readObject(Common::ReadStream &in, Object &curObject) {
curObject._vyPath = in.readSint16BE();
curObject._actIndex = in.readUint16BE();
curObject._seqNumb = in.readByte();
- curObject._currImagePtr = 0;
+ curObject._currImagePtr = nullptr;
if (curObject._seqNumb == 0) {
curObject._seqList[0]._imageNbr = 0;
- curObject._seqList[0]._seqPtr = 0;
+ curObject._seqList[0]._seqPtr = nullptr;
}
for (int j = 0; j < curObject._seqNumb; j++) {
curObject._seqList[j]._imageNbr = in.readUint16BE();
- curObject._seqList[j]._seqPtr = 0;
+ curObject._seqList[j]._seqPtr = nullptr;
}
curObject._cycling = (Cycle)in.readByte();
@@ -498,7 +502,7 @@ void ObjectHandler::readObject(Common::ReadStream &in, Object &curObject) {
void ObjectHandler::loadObjectArr(Common::ReadStream &in) {
debugC(6, kDebugObject, "loadObject(&in)");
Object tmpObject;
- tmpObject._stateDataIndex = 0;
+ tmpObject._stateDataIndex = nullptr;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
@@ -515,7 +519,7 @@ void ObjectHandler::loadObjectArr(Common::ReadStream &in) {
// Skip over uneeded objects.
readObject(in, tmpObject);
free(tmpObject._stateDataIndex);
- tmpObject._stateDataIndex = 0;
+ tmpObject._stateDataIndex = nullptr;
}
}
}
diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp
index 2585c64fd8..57938ec371 100644
--- a/engines/hugo/parser.cpp
+++ b/engines/hugo/parser.cpp
@@ -44,14 +44,20 @@
namespace Hugo {
-Parser::Parser(HugoEngine *vm) : _vm(vm), _putIndex(0), _getIndex(0), _arrayReqs(0), _catchallList(0), _backgroundObjects(0), _cmdList(0) {
+Parser::Parser(HugoEngine *vm) : _vm(vm), _putIndex(0), _getIndex(0) {
+ _catchallList = nullptr;
+ _arrayReqs = nullptr;
+
+ _backgroundObjects = nullptr;
+ _backgroundObjectsSize = 0;
+ _cmdList = nullptr;
+ _cmdListSize = 0;
+
_cmdLineIndex = 0;
_cmdLineTick = 0;
_cmdLineCursor = '_';
_cmdLine[0] = '\0';
- _cmdListSize = 0;
_checkDoubleF1Fl = false;
- _backgroundObjectsSize = 0;
}
Parser::~Parser() {
@@ -172,7 +178,7 @@ const char *Parser::useBG(const char *name) {
return _vm->_text->getVerb(p[i]._verbIndex, 0);
}
- return 0;
+ return nullptr;
}
void Parser::freeParser() {
@@ -180,20 +186,24 @@ void Parser::freeParser() {
for (int i = 0; _arrayReqs[i] != 0; i++)
free(_arrayReqs[i]);
free(_arrayReqs);
+ _arrayReqs = nullptr;
}
free(_catchallList);
+ _catchallList = nullptr;
if (_backgroundObjects) {
for (int i = 0; i < _backgroundObjectsSize; i++)
free(_backgroundObjects[i]);
free(_backgroundObjects);
+ _backgroundObjects = nullptr;
}
if (_cmdList) {
for (int i = 0; i < _cmdListSize; i++)
free(_cmdList[i]);
free(_cmdList);
+ _cmdList = nullptr;
}
}
@@ -398,9 +408,9 @@ void Parser::command(const char *format, ...) {
* Locate any member of object name list appearing in command line
*/
bool Parser::isWordPresent(char **wordArr) const {
- debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]);
-
if (wordArr != 0) {
+ debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]);
+
for (int i = 0; strlen(wordArr[i]); i++) {
if (strstr(_vm->_line, wordArr[i]))
return true;
@@ -421,7 +431,7 @@ const char *Parser::findNoun() const {
return _vm->_text->getNoun(i, 0);
}
}
- return 0;
+ return nullptr;
}
/**
@@ -436,7 +446,7 @@ const char *Parser::findVerb() const {
return _vm->_text->getVerb(i, 0);
}
}
- return 0;
+ return nullptr;
}
/**
diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp
index 54dae88c28..dc3c41de9c 100644
--- a/engines/hugo/route.cpp
+++ b/engines/hugo/route.cpp
@@ -45,6 +45,17 @@ Route::Route(HugoEngine *vm) : _vm(vm) {
_routeIndex = -1; // Hero not following a route
_routeType = kRouteSpace; // Hero walking to space
_routeObjId = -1; // Hero not walking to anything
+
+ for (int i = 0; i < kMaxSeg; i++)
+ _segment[i]._y = _segment[i]._x1 = _segment[i]._x2 = 0;
+
+ _segmentNumb = 0;
+ _routeListIndex = 0;
+ _destX = _destY = 0;
+ _heroWidth = 0;
+ _routeFoundFl = false;
+ _fullStackFl = false;
+ _fullSegmentFl = false;
}
void Route::resetRoute() {
@@ -303,7 +314,7 @@ Common::Point *Route::newNode() {
_routeListIndex++;
if (_routeListIndex >= kMaxNodes) // Too many nodes
- return 0; // Incomplete route - failure
+ return nullptr; // Incomplete route - failure
_route[_routeListIndex] = _route[_routeListIndex - 1]; // Initialize with previous node
return &_route[_routeListIndex];
diff --git a/engines/hugo/route.h b/engines/hugo/route.h
index 716829a201..71db1e2583 100644
--- a/engines/hugo/route.h
+++ b/engines/hugo/route.h
@@ -79,9 +79,11 @@ private:
int16 _destY;
int16 _heroWidth; // Hero width
bool _routeFoundFl; // TRUE when path found
- bool _fullStackFl; // TRUE if stack exhausted
bool _fullSegmentFl; // Segments exhausted
+ // CHECKME: Never set to true, could be removed
+ bool _fullStackFl; // TRUE if stack exhausted
+
void segment(int16 x, int16 y);
bool findRoute(const int16 cx, const int16 cy);
Common::Point *newNode();
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index 32b8a47df7..17ffa9d391 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -47,10 +47,23 @@
namespace Hugo {
-Scheduler::Scheduler(HugoEngine *vm) : _vm(vm), _actListArr(0), _curTick(0), _oldTime(0), _refreshTimeout(0), _points(0), _screenActs(0) {
+Scheduler::Scheduler(HugoEngine *vm) : _vm(vm) {
+ _actListArr = nullptr;
+ _curTick = 0;
+ _oldTime = 0;
+ _refreshTimeout = 0;
+ _points = nullptr;
+ _screenActs = nullptr;
+
memset(_events, 0, sizeof(_events));
_numBonuses = 0;
_screenActsSize = 0;
+
+ _actListArrSize = 0;
+ _alNewscrIndex = 0;
+ _freeEvent = nullptr;
+ _headEvent = nullptr;
+ _tailEvent = nullptr;
}
Scheduler::~Scheduler() {
@@ -69,14 +82,14 @@ void Scheduler::initEventQueue() {
// Chain nextEvent from first to last
for (int i = kMaxEvents; --i;)
_events[i - 1]._nextEvent = &_events[i];
- _events[kMaxEvents - 1]._nextEvent = 0;
+ _events[kMaxEvents - 1]._nextEvent = nullptr;
// Chain prevEvent from last to first
for (int i = 1; i < kMaxEvents; i++)
_events[i]._prevEvent = &_events[i - 1];
- _events[0]._prevEvent = 0;
+ _events[0]._prevEvent = nullptr;
- _headEvent = _tailEvent = 0; // Event list is empty
+ _headEvent = _tailEvent = nullptr; // Event list is empty
_freeEvent = _events; // Free list is full
}
@@ -90,7 +103,7 @@ Event *Scheduler::getQueue() {
error("An error has occurred: %s", "getQueue");
Event *resEvent = _freeEvent;
_freeEvent = _freeEvent->_nextEvent;
- resEvent->_nextEvent = 0;
+ resEvent->_nextEvent = nullptr;
return resEvent;
}
@@ -597,7 +610,7 @@ void Scheduler::loadScreenAct(Common::SeekableReadStream &in) {
for (int i = 0; i < numElem; i++) {
uint16 numSubElem = in.readUint16BE();
if (numSubElem == 0) {
- _screenActs[i] = 0;
+ _screenActs[i] = nullptr;
} else {
_screenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem);
for (int j = 0; j < numSubElem; j++)
@@ -617,11 +630,14 @@ void Scheduler::freeScheduler() {
debugC(6, kDebugSchedule, "freeActListArr()");
free(_points);
+ _points = nullptr;
if (_screenActs) {
for (int i = 0; i < _screenActsSize; i++)
free(_screenActs[i]);
free(_screenActs);
+ _screenActs = nullptr;
+ _screenActsSize = 0;
}
if (_actListArr) {
@@ -633,6 +649,8 @@ void Scheduler::freeScheduler() {
free(_actListArr[i]);
}
free(_actListArr);
+ _actListArr = nullptr;
+ _actListArrSize = 0;
}
}
@@ -698,9 +716,9 @@ void Scheduler::saveEvents(Common::WriteStream *f) {
f->writeUint32BE(getTicks());
- int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events;
- int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events;
- int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events;
+ int16 freeIndex = (_freeEvent == nullptr) ? -1 : _freeEvent - _events;
+ int16 headIndex = (_headEvent == nullptr) ? -1 : _headEvent - _events;
+ int16 tailIndex = (_tailEvent == nullptr) ? -1 : _tailEvent - _events;
f->writeSint16BE(freeIndex);
f->writeSint16BE(headIndex);
@@ -717,8 +735,8 @@ void Scheduler::saveEvents(Common::WriteStream *f) {
f->writeSint16BE(subElem);
f->writeByte((wrkEvent->_localActionFl) ? 1 : 0);
f->writeUint32BE(wrkEvent->_time);
- f->writeSint16BE((wrkEvent->_prevEvent == 0) ? -1 : (wrkEvent->_prevEvent - _events));
- f->writeSint16BE((wrkEvent->_nextEvent == 0) ? -1 : (wrkEvent->_nextEvent - _events));
+ f->writeSint16BE((wrkEvent->_prevEvent == nullptr) ? -1 : (wrkEvent->_prevEvent - _events));
+ f->writeSint16BE((wrkEvent->_nextEvent == nullptr) ? -1 : (wrkEvent->_nextEvent - _events));
}
}
@@ -1102,7 +1120,7 @@ void Scheduler::restoreEvents(Common::ReadStream *f) {
// fix up action pointer (to do better)
if ((index == -1) && (subElem == -1))
- _events[i]._action = 0;
+ _events[i]._action = nullptr;
else
_events[i]._action = (Act *)&_actListArr[index][subElem];
@@ -1112,12 +1130,12 @@ void Scheduler::restoreEvents(Common::ReadStream *f) {
int16 prevIndex = f->readSint16BE();
int16 nextIndex = f->readSint16BE();
- _events[i]._prevEvent = (prevIndex == -1) ? (Event *)0 : &_events[prevIndex];
- _events[i]._nextEvent = (nextIndex == -1) ? (Event *)0 : &_events[nextIndex];
+ _events[i]._prevEvent = (prevIndex == -1) ? nullptr : &_events[prevIndex];
+ _events[i]._nextEvent = (nextIndex == -1) ? nullptr : &_events[nextIndex];
}
- _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
- _headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
- _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex];
+ _freeEvent = (freeIndex == -1) ? nullptr : &_events[freeIndex];
+ _headEvent = (headIndex == -1) ? nullptr : &_events[headIndex];
+ _tailEvent = (tailIndex == -1) ? nullptr : &_events[tailIndex];
// Adjust times to fit our time
uint32 curTime = getTicks();
@@ -1156,7 +1174,7 @@ void Scheduler::insertAction(Act *action) {
// Now find the place to insert the event
if (!_tailEvent) { // Empty queue
_tailEvent = _headEvent = curEvent;
- curEvent->_nextEvent = curEvent->_prevEvent = 0;
+ curEvent->_nextEvent = curEvent->_prevEvent = nullptr;
} else {
Event *wrkEvent = _tailEvent; // Search from latest time back
bool found = false;
@@ -1178,7 +1196,7 @@ void Scheduler::insertAction(Act *action) {
if (!found) { // Must be earliest in list
_headEvent->_prevEvent = curEvent; // So insert as new head
curEvent->_nextEvent = _headEvent;
- curEvent->_prevEvent = 0;
+ curEvent->_prevEvent = nullptr;
_headEvent = curEvent;
}
}
@@ -1424,7 +1442,7 @@ Event *Scheduler::doAction(Event *curEvent) {
}
if (action->_a0._actType == NEW_SCREEN) { // New_screen() deletes entire list
- return 0; // nextEvent = 0 since list now empty
+ return nullptr; // nextEvent = nullptr since list now empty
} else {
wrkEvent = curEvent->_nextEvent;
delQueue(curEvent); // Return event to free list
@@ -1455,9 +1473,9 @@ void Scheduler::delQueue(Event *curEvent) {
}
if (_headEvent)
- _headEvent->_prevEvent = 0; // Mark end of list
+ _headEvent->_prevEvent = nullptr; // Mark end of list
else
- _tailEvent = 0; // Empty queue
+ _tailEvent = nullptr; // Empty queue
curEvent->_nextEvent = _freeEvent; // Return p to free list
if (_freeEvent) // Special case, if free list was empty
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index aefa03cd5e..28dcdc83d6 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -123,11 +123,12 @@ SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- _DOSSongPtr = 0;
+ _DOSSongPtr = nullptr;
_curPriority = 0;
_pcspkrTimer = 0;
_pcspkrOctave = 3;
_pcspkrNoteDuration = 2;
+ _DOSIntroSong = nullptr;
}
SoundHandler::~SoundHandler() {
@@ -210,7 +211,7 @@ void SoundHandler::playSound(int16 sound, const byte priority) {
_curPriority = priority;
// Get sound data
- if ((soundPtr = _vm->_file->getSound(sound, &size)) == 0)
+ if ((soundPtr = _vm->_file->getSound(sound, &size)) == nullptr)
return;
Audio::AudioStream *stream = Audio::makeRawStream(soundPtr, size, 11025, Audio::FLAG_UNSIGNED);
diff --git a/engines/hugo/text.cpp b/engines/hugo/text.cpp
index f8b02bdf68..538a0341e2 100644
--- a/engines/hugo/text.cpp
+++ b/engines/hugo/text.cpp
@@ -26,9 +26,17 @@
namespace Hugo {
-TextHandler::TextHandler(HugoEngine *vm) : _vm(vm), _textData(0), _stringtData(0),
- _textEngine(0), _textIntro(0), _textMouse(0), _textParser(0), _textUtil(0),
- _screenNames(0), _arrayNouns(0), _arrayVerbs(0) {
+TextHandler::TextHandler(HugoEngine *vm) : _vm(vm) {
+ _textData = nullptr;
+ _stringtData = nullptr;
+ _textEngine = nullptr;
+ _textIntro = nullptr;
+ _textMouse = nullptr;
+ _textParser = nullptr;
+ _textUtil = nullptr;
+ _screenNames = nullptr;
+ _arrayNouns = nullptr;
+ _arrayVerbs = nullptr;
}
TextHandler::~TextHandler() {
@@ -86,9 +94,9 @@ char **TextHandler::loadTextsVariante(Common::ReadStream &in, uint16 *arraySize)
int numTexts;
int entryLen;
int len;
- char **res = 0;
- char *pos = 0;
- char *posBck = 0;
+ char **res = nullptr;
+ char *pos = nullptr;
+ char *posBck = nullptr;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
numTexts = in.readUint16BE();
@@ -126,21 +134,21 @@ char **TextHandler::loadTextsVariante(Common::ReadStream &in, uint16 *arraySize)
}
char ***TextHandler::loadTextsArray(Common::ReadStream &in) {
- char ***resArray = 0;
+ char ***resArray = nullptr;
uint16 arraySize;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
arraySize = in.readUint16BE();
if (varnt == _vm->_gameVariant) {
resArray = (char ***)malloc(sizeof(char **) * (arraySize + 1));
- resArray[arraySize] = 0;
+ resArray[arraySize] = nullptr;
}
for (int i = 0; i < arraySize; i++) {
int numTexts = in.readUint16BE();
int entryLen = in.readUint16BE();
char *pos = (char *)malloc(entryLen);
- char *posBck = 0;
- char **res = 0;
+ char *posBck = nullptr;
+ char **res = nullptr;
if (varnt == _vm->_gameVariant) {
res = (char **)malloc(sizeof(char *) * numTexts);
res[0] = pos;
@@ -232,6 +240,7 @@ void TextHandler::freeTexts(char **ptr) {
free(*ptr - DATAALIGNMENT);
free(ptr);
+ ptr = nullptr;
}
void TextHandler::freeAllTexts() {
@@ -242,12 +251,14 @@ void TextHandler::freeAllTexts() {
for (int i = 0; _arrayNouns[i]; i++)
freeTexts(_arrayNouns[i]);
free(_arrayNouns);
+ _arrayNouns = nullptr;
}
if (_arrayVerbs) {
for (int i = 0; _arrayVerbs[i]; i++)
freeTexts(_arrayVerbs[i]);
free(_arrayVerbs);
+ _arrayVerbs = nullptr;
}
freeTexts(_screenNames);
diff --git a/engines/kyra/POTFILES b/engines/kyra/POTFILES
new file mode 100644
index 0000000000..16888e2c5a
--- /dev/null
+++ b/engines/kyra/POTFILES
@@ -0,0 +1,3 @@
+engines/kyra/detection.cpp
+engines/kyra/lol.cpp
+engines/kyra/sound_midi.cpp
diff --git a/engines/kyra/animator_lok.cpp b/engines/kyra/animator_lok.cpp
index c246eebd46..945a51a4ec 100644
--- a/engines/kyra/animator_lok.cpp
+++ b/engines/kyra/animator_lok.cpp
@@ -491,7 +491,7 @@ Animator_LoK::AnimObject *Animator_LoK::objectAddHead(AnimObject *queue, AnimObj
}
Animator_LoK::AnimObject *Animator_LoK::objectQueue(AnimObject *queue, AnimObject *add) {
- if (add->drawY <= queue->drawY || !queue) {
+ if (!queue || add->drawY <= queue->drawY) {
add->nextAnimObject = queue;
return add;
}
diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp
index 80a95da047..80ff42e2c5 100644
--- a/engines/kyra/chargen.cpp
+++ b/engines/kyra/chargen.cpp
@@ -155,8 +155,10 @@ CharacterGenerator::~CharacterGenerator() {
}
bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
- if (!characters && !faceShapes)
+ if (!characters || !faceShapes) {
+ warning("CharacterGenerator::start: Called without character data");
return true;
+ }
_characters = characters;
_faceShapes = *faceShapes;
diff --git a/engines/kyra/configure.engine b/engines/kyra/configure.engine
new file mode 100644
index 0000000000..b7d6334fcc
--- /dev/null
+++ b/engines/kyra/configure.engine
@@ -0,0 +1,5 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine kyra "Kyra" yes "lol eob" "Legend of Kyrandia 1-3"
+add_engine lol "Lands of Lore" yes
+add_engine eob "Eye of the Beholder" yes
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index bcbfe27b69..ee0303c8c3 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -737,7 +737,7 @@ void KyraEngine_MR::loadAlbumPageWSA() {
if (_album.curPage != 14) {
filename = Common::String::format("PAGE%x.WSA", _album.curPage+1);
_album.rightPage.wsa->open(filename.c_str(), 1, 0);
- _album.rightPage.maxFrame = _album.leftPage.wsa->frames()-1;
+ _album.rightPage.maxFrame = _album.rightPage.wsa->frames()-1;
}
}
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/resource.cpp b/engines/kyra/resource.cpp
index c350c81742..7a1abe8dd9 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -74,10 +74,14 @@ bool Resource::reset() {
loadProtectedFiles(list);
} else {
+ // We only search in the game path to avoid any invalid PAK or
+ // APK files from being picked up. This might happen, for example,
+ // when the user has an Android package file in the CWD.
+ Common::FSDirectory gameDir(dir);
Common::ArchiveMemberList files;
- _files.listMatchingMembers(files, "*.PAK");
- _files.listMatchingMembers(files, "*.APK");
+ gameDir.listMatchingMembers(files, "*.PAK");
+ gameDir.listMatchingMembers(files, "*.APK");
for (Common::ArchiveMemberList::const_iterator i = files.begin(); i != files.end(); ++i) {
Common::String name = (*i)->getName();
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index c9486d9c45..d2b4907b6a 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -577,6 +577,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) {
}
updateCharPal(0);
+ _screen->updateScreen();
if (!_menuDirectlyToLoad) {
_emc->start(&_sceneScriptState, 3);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 419b630714..8c97e46a8f 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -718,6 +718,13 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF
_vm->delay((delayAcc >> 8) * 1000 / 60);
delayAcc &= 0xFF;
}
+
+ // In case we should quit we setup the final palette here. This avoids
+ // ugly palette glitches when quitting while fading. This can for example
+ // be noticed when quitting while viewing the family album in Kyra3.
+ if (_vm->shouldQuit()) {
+ setScreenPalette(pal);
+ }
}
void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) {
@@ -1256,7 +1263,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 +1303,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/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index cc7d526ffe..23eb94cb53 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -280,7 +280,7 @@ void Screen_v2::setTextColorMap(const uint8 *cmap) {
void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2,
int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim) {
- if (!(w1 || h1 || w2 || h2))
+ if (!w1 || !h1 || !w2 || !h2)
return;
ScreenDim cdm = *getScreenDim(dim);
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 2a2f9a5493..51f1ea51cf 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -1722,9 +1722,10 @@ int KyraEngine_LoK::handleBeadState() {
_screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
++_beadState1.tableIndex;
- if (_beadState1.tableIndex > 24)
+ if (_beadState1.tableIndex > 24) {
_beadState1.tableIndex = 0;
_unkEndSeqVar4 = 1;
+ }
if (_system->getMillis() > _beadStateTimer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
snd_playSoundEffect(0x0B);
if (_currentCharacter->x1 > 233 && _currentCharacter->x1 < 305 && _currentCharacter->y1 > 85 && _currentCharacter->y1 < 105 &&
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index af741a1ebe..e4752f33de 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -225,6 +225,7 @@ void SoundTowns::playSoundEffect(uint8 track, uint8) {
_driver->chanPanPos(_sfxChannel, 0x40);
_driver->chanPitch(_sfxChannel, 0);
_driver->playSoundEffect(_sfxChannel, note, 127, sfxPlaybackBuffer);
+ delete[] sfxPlaybackBuffer;
}
void SoundTowns::updateVolumeSettings() {
diff --git a/engines/kyra/text_rpg.cpp b/engines/kyra/text_rpg.cpp
index a19d678e35..24c523c856 100644
--- a/engines/kyra/text_rpg.cpp
+++ b/engines/kyra/text_rpg.cpp
@@ -129,7 +129,7 @@ void TextDisplayer_rpg::displayText(char *str, ...) {
uint16 charsPerLine = (sd->w << 3) / (_screen->getFontWidth() + _screen->_charWidth);
while (c) {
- char a = tolower(_ctrl[1]);
+ char a = tolower((unsigned char)_ctrl[1]);
if (!_tempString2 && c == '%') {
if (a == 'd') {
diff --git a/engines/lastexpress/configure.engine b/engines/lastexpress/configure.engine
new file mode 100644
index 0000000000..807b1a088b
--- /dev/null
+++ b/engines/lastexpress/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine lastexpress "The Last Express" no "" "" "16bit"
diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp
index 7618259e69..832bcc2e26 100644
--- a/engines/lastexpress/data/animation.cpp
+++ b/engines/lastexpress/data/animation.cpp
@@ -270,7 +270,7 @@ void Animation::play() {
draw(s);
// XXX: Update the screen
- g_system->copyRectToScreen(s->pixels, s->pitch, 0, 0, s->w, s->h);
+ g_system->copyRectToScreen(s->getPixels(), s->pitch, 0, 0, s->w, s->h);
// Free the temporary surface
s->free();
diff --git a/engines/lastexpress/data/scene.h b/engines/lastexpress/data/scene.h
index 69a1417459..b99e56a74c 100644
--- a/engines/lastexpress/data/scene.h
+++ b/engines/lastexpress/data/scene.h
@@ -83,6 +83,7 @@ class Scene;
class SceneHotspot {
public:
enum Action {
+ kActionNone = 0,
kActionInventory = 1,
kActionSavePoint = 2,
kActionPlaySound = 3,
@@ -152,8 +153,19 @@ public:
byte cursor;
uint32 next;
- SceneHotspot() {}
+ SceneHotspot() {
+ coordsOffset = 0;
+ scene = kSceneNone;
+ location = 0;
+ action = kActionNone;
+ param1 = 0;
+ param2 = 0;
+ param3 = 0;
+ cursor = 0;
+ next = 0;
+ }
~SceneHotspot();
+
static SceneHotspot *load(Common::SeekableReadStream *stream);
bool isInside(const Common::Point &point);
diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp
index a5bcba84cd..c7073b560c 100644
--- a/engines/lastexpress/data/sequence.cpp
+++ b/engines/lastexpress/data/sequence.cpp
@@ -128,8 +128,8 @@ AnimFrame::~AnimFrame() {
}
Common::Rect AnimFrame::draw(Graphics::Surface *s) {
- byte *inp = (byte *)_image.pixels;
- uint16 *outp = (uint16 *)s->pixels;
+ byte *inp = (byte *)_image.getPixels();
+ uint16 *outp = (uint16 *)s->getPixels();
for (int i = 0; i < 640 * 480; i++, inp++, outp++) {
if (*inp)
*outp = _palette[*inp];
@@ -155,7 +155,7 @@ void AnimFrame::decomp4(Common::SeekableReadStream *in, const FrameInfo &f) {
}
void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift) {
- byte *p = (byte *)_image.getBasePtr(0, 0);
+ byte *p = (byte *)_image.getPixels();
uint32 skip = f.initialSkip / 2;
uint32 size = f.decompressedEndOffset / 2;
@@ -200,7 +200,7 @@ void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byt
}
void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) {
- byte *p = (byte *)_image.getBasePtr(0, 0);
+ byte *p = (byte *)_image.getPixels();
uint32 skip = f.initialSkip / 2;
uint32 size = f.decompressedEndOffset / 2;
@@ -235,7 +235,7 @@ void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) {
}
void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) {
- byte *p = (byte *)_image.getBasePtr(0, 0);
+ byte *p = (byte *)_image.getPixels();
uint32 skip = f.initialSkip / 2;
uint32 size = f.decompressedEndOffset / 2;
@@ -288,7 +288,7 @@ void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) {
}
void AnimFrame::decompFF(Common::SeekableReadStream *in, const FrameInfo &f) {
- byte *p = (byte *)_image.getBasePtr(0, 0);
+ byte *p = (byte *)_image.getPixels();
uint32 skip = f.initialSkip / 2;
uint32 size = f.decompressedEndOffset / 2;
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index db3a3e3962..7c83aff93d 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -487,7 +487,9 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
// Handle right-click to interrupt sequence
Common::Event ev;
- _engine->getEventManager()->pollEvent(ev);
+ if (!_engine->getEventManager()->pollEvent(ev))
+ break;
+
if (ev.type == Common::EVENT_RBUTTONUP)
break;
@@ -596,7 +598,9 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
// Handle right-click to interrupt sequence
Common::Event ev;
- _engine->getEventManager()->pollEvent(ev);
+ if (!_engine->getEventManager()->pollEvent(ev))
+ break;
+
if (ev.type == Common::EVENT_RBUTTONUP)
break;
diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h
index c67d13db9e..f3b57e7464 100644
--- a/engines/lastexpress/entities/entity.h
+++ b/engines/lastexpress/entities/entity.h
@@ -330,7 +330,7 @@ public:
};
struct EntityParametersSIII : EntityParameters {
- char seq[12];
+ char seq[13];
uint param4;
uint param5;
uint param6;
@@ -338,7 +338,7 @@ public:
uint param8;
EntityParametersSIII() {
- memset(&seq, 0, 12);
+ memset(&seq, 0, 13);
param4 = 0;
param5 = 0;
param6 = 0;
@@ -374,16 +374,16 @@ public:
};
struct EntityParametersSIIS : EntityParameters {
- char seq1[12];
+ char seq1[13];
uint param4;
uint param5;
- char seq2[12];
+ char seq2[13];
EntityParametersSIIS() {
- memset(&seq1, 0, 12);
+ memset(&seq1, 0, 13);
param4 = 0;
param5 = 0;
- memset(&seq2, 0, 12);
+ memset(&seq2, 0, 13);
}
Common::String toString() {
@@ -410,14 +410,14 @@ public:
struct EntityParametersISSI : EntityParameters {
uint param1;
- char seq1[12];
- char seq2[12];
+ char seq1[13];
+ char seq2[13];
uint param8;
EntityParametersISSI() {
param1 = 0;
- memset(&seq1, 0, 12);
- memset(&seq2, 0, 12);
+ memset(&seq1, 0, 13);
+ memset(&seq2, 0, 13);
param8 = 0;
}
@@ -445,7 +445,7 @@ public:
struct EntityParametersISII : EntityParameters {
uint param1;
- char seq[12];
+ char seq[13];
uint param5;
uint param6;
uint param7;
@@ -453,7 +453,7 @@ public:
EntityParametersISII() {
param1 = 0;
- memset(&seq, 0, 12);
+ memset(&seq, 0, 13);
param5 = 0;
param6 = 0;
param7 = 0;
@@ -488,14 +488,14 @@ public:
};
struct EntityParametersSSII : EntityParameters {
- char seq1[12];
- char seq2[12];
+ char seq1[13];
+ char seq2[13];
uint param7;
uint param8;
EntityParametersSSII() {
- memset(&seq1, 0, 12);
- memset(&seq2, 0, 12);
+ memset(&seq1, 0, 13);
+ memset(&seq2, 0, 13);
param7 = 0;
param8 = 0;
}
@@ -523,14 +523,14 @@ public:
};
struct EntityParametersSSS : EntityParameters {
- char seq1[12];
- char seq2[12];
- char seq3[8];
+ char seq1[13];
+ char seq2[13];
+ char seq3[9];
EntityParametersSSS() {
- memset(&seq1, 0, 12);
- memset(&seq2, 0, 12);
- memset(&seq3, 0, 8);
+ memset(&seq1, 0, 13);
+ memset(&seq2, 0, 13);
+ memset(&seq3, 0, 9);
}
Common::String toString() {
@@ -551,14 +551,14 @@ public:
struct EntityParametersIISS : EntityParameters {
uint param1;
uint param2;
- char seq1[12];
- char seq2[12];
+ char seq1[13];
+ char seq2[13];
EntityParametersIISS() {
param1 = 0;
param2 = 0;
- memset(&seq1, 0, 12);
- memset(&seq2, 0, 12);
+ memset(&seq1, 0, 13);
+ memset(&seq2, 0, 13);
}
Common::String toString() {
@@ -586,7 +586,7 @@ public:
struct EntityParametersIISI : EntityParameters {
uint param1;
uint param2;
- char seq[12];
+ char seq[13];
uint param6;
uint param7;
uint param8;
@@ -594,7 +594,7 @@ public:
EntityParametersIISI() {
param1 = 0;
param2 = 0;
- memset(&seq, 0, 12);
+ memset(&seq, 0, 13);
param6 = 0;
param7 = 0;
param8 = 0;
@@ -631,7 +631,7 @@ public:
uint param1;
uint param2;
uint param3;
- char seq[12];
+ char seq[13];
uint param7;
uint param8;
@@ -639,7 +639,7 @@ public:
param1 = 0;
param2 = 0;
param3 = 0;
- memset(&seq, 0, 12);
+ memset(&seq, 0, 13);
param7 = 0;
param8 = 0;
}
@@ -677,7 +677,7 @@ public:
uint param3;
uint param4;
uint param5;
- char seq[12];
+ char seq[13];
EntityParametersI5S() {
param1 = 0;
@@ -685,7 +685,7 @@ public:
param3 = 0;
param4 = 0;
param5 = 0;
- memset(&seq, 0, 12);
+ memset(&seq, 0, 13);
}
void saveLoadWithSerializer(Common::Serializer &s) {
@@ -818,9 +818,9 @@ public:
/**
* Synchronizes a string.
*
- * @param s The Common::Serializer to use.
- * @param string The string.
- * @param length Length of the string.
+ * @param s The Common::Serializer to use.
+ * @param string The string.
+ * @param length Length of the string.
*/
void syncString(Common::Serializer &s, Common::String &string, uint length) const;
@@ -921,7 +921,7 @@ protected:
/**
* Play sound
*
- * @param savepoint The savepoint
+ * @param savepoint The savepoint
* - Sound filename
* @param resetItem true to reset item.
* @param flag sound flag
@@ -931,9 +931,9 @@ protected:
/**
* Draws the entity
*
- * @param savepoint The savepoint
- * - Sequence
- * - ExcuseMe flag
+ * @param savepoint The savepoint
+ * - Sequence
+ * - ExcuseMe flag
* @param handleExcuseMe true to handle excuseMeCath action
*/
void draw(const SavePoint &savepoint, bool handleExcuseMe = false);
@@ -941,7 +941,7 @@ protected:
/**
* Draws the entity along with another one
*
- * @param savepoint The savepoint.
+ * @param savepoint The savepoint.
* - Sequence 1
* - Sequence 2
* - EntityIndex
@@ -976,23 +976,23 @@ protected:
/**
* Process callback action when the entity direction is not kDirectionRight
*
- * @param savepoint The savepoint.
+ * @param savepoint The savepoint.
*/
void callbackActionOnDirection(const SavePoint &savepoint);
/**
* Process callback action when somebody is standing in the restaurant or salon.
*
- * @param savepoint The savepoint.
+ * @param savepoint The savepoint.
*/
void callbackActionRestaurantOrSalon(const SavePoint &savepoint);
/**
* Updates the entity
*
- * @param savepoint The savepoint.
- * - CarIndex
- * - EntityPosition
+ * @param savepoint The savepoint.
+ * - CarIndex
+ * - EntityPosition
* @param handleExcuseMe true to handle the kActionExcuseMe/kActionExcuseMeCath actions.
*/
void updateEntity(const SavePoint &savepoint, bool handleExcuseMe = false);
@@ -1000,11 +1000,11 @@ protected:
/**
* Call a specific savepoint (or draw sequence in default case)
*
- * @param savepoint The savepoint.
- * - Sequence to draw in default case
- * - EntityIndex
- * - ActionIndex
- * - Sequence for the savepoint
+ * @param savepoint The savepoint.
+ * - Sequence to draw in default case
+ * - EntityIndex
+ * - ActionIndex
+ * - Sequence for the savepoint
* @param handleExcuseMe true to handle excuse me.
*/
void callSavepoint(const SavePoint &savepoint, bool handleExcuseMe = false);
@@ -1012,36 +1012,36 @@ protected:
/**
* Handles entering/exiting a compartment.
*
- * @param savepoint The savepoint.
- * @param position1 The first position.
- * @param position2 The second position.
- * @param car The car.
- * @param compartment The compartment.
- * @param alternate true to use the alternate version of SceneManager::loadSceneFromObject()
+ * @param savepoint The savepoint.
+ * @param position1 The first position.
+ * @param position2 The second position.
+ * @param car The car.
+ * @param compartment The compartment.
+ * @param alternate true to use the alternate version of SceneManager::loadSceneFromObject()
*/
void enterExitCompartment(const SavePoint &savepoint, EntityPosition position1 = kPositionNone, EntityPosition position2 = kPositionNone, CarIndex car = kCarNone, ObjectIndex compartment = kObjectNone, bool alternate = false, bool updateLocation = false);
/**
* Go to compartment.
*
- * @param savepoint The savepoint.
- * @param compartmentFrom The compartment from.
- * @param positionFrom The position from.
- * @param sequenceFrom The sequence from.
- * @param sequenceTo The sequence to.
+ * @param savepoint The savepoint.
+ * @param compartmentFrom The compartment from.
+ * @param positionFrom The position from.
+ * @param sequenceFrom The sequence from.
+ * @param sequenceTo The sequence to.
*/
void goToCompartment(const SavePoint &savepoint, ObjectIndex compartmentFrom, EntityPosition positionFrom, Common::String sequenceFrom, Common::String sequenceTo);
/**
* Go to compartment from compartment.
*
- * @param savepoint The savepoint.
- * @param compartmentFrom The compartment from.
- * @param positionFrom The position from.
- * @param sequenceFrom The sequence from.
- * @param compartmentTo The compartment to.
- * @param positionTo The position to.
- * @param sequenceTo The sequence to.
+ * @param savepoint The savepoint.
+ * @param compartmentFrom The compartment from.
+ * @param positionFrom The position from.
+ * @param sequenceFrom The sequence from.
+ * @param compartmentTo The compartment to.
+ * @param positionTo The position to.
+ * @param sequenceTo The sequence to.
*/
void goToCompartmentFromCompartment(const SavePoint &savepoint, ObjectIndex compartmentFrom, EntityPosition positionFrom, Common::String sequenceFrom, ObjectIndex compartmentTo, EntityPosition positionTo, Common::String sequenceTo);
diff --git a/engines/lastexpress/entities/servers0.cpp b/engines/lastexpress/entities/servers0.cpp
index 73e0d34722..6323ef0ca8 100644
--- a/engines/lastexpress/entities/servers0.cpp
+++ b/engines/lastexpress/entities/servers0.cpp
@@ -115,7 +115,7 @@ IMPLEMENT_FUNCTION_NOSETUP(5, Servers0, callbackActionOnDirection)
case kActionExitCompartment:
callbackAction();
- break;
+ break;
case kActionExcuseMeCath:
if (!params->param1) {
@@ -445,7 +445,7 @@ IMPLEMENT_FUNCTION(24, Servers0, chapter2Handler)
HANDLE_TABLE(1, 3, 1, setup_function25);
HANDLE_TABLE(1, 4, 2, setup_function26);
- break;
+ break;
case kActionCallback:
if (getCallback() == 1)
diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp
index d9ddb0a4d1..68c0813013 100644
--- a/engines/lastexpress/entities/verges.cpp
+++ b/engines/lastexpress/entities/verges.cpp
@@ -105,7 +105,7 @@ IMPLEMENT_FUNCTION(3, Verges, callbackActionOnDirection)
case kActionExitCompartment:
callbackAction();
- break;
+ break;
case kActionExcuseMeCath:
if (!params->param1) {
diff --git a/engines/lastexpress/game/entities.h b/engines/lastexpress/game/entities.h
index 81aed627aa..cacbc408c9 100644
--- a/engines/lastexpress/game/entities.h
+++ b/engines/lastexpress/game/entities.h
@@ -110,7 +110,7 @@ public:
* Query if 'entity' is inside a compartment
*
* @param entity The entity.
- * @param car The car.
+ * @param car The car.
* @param position The position.
*
* @return true if inside the compartment, false if not.
@@ -247,7 +247,7 @@ public:
/**
* Query if nobody is in a compartment at that position.
*
- * @param car The car.
+ * @param car The car.
* @param position The position.
*
* @return true if nobody is in a compartment, false if not.
@@ -334,8 +334,8 @@ private:
static const int _compartmentsCount = 16;
static const int _positionsCount = 100 * 10; // 100 positions per train car
- LastExpressEngine *_engine;
- EntityData *_header;
+ LastExpressEngine *_engine;
+ EntityData *_header;
Common::Array<Entity *> _entities;
// Compartments & positions
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index 11e7369ee1..2f1b0a8e76 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -52,6 +52,8 @@ Inventory::Inventory(LastExpressEngine *engine) : _engine(engine), _selectedItem
_selectedItemRect = Common::Rect(44, 0, 76, 32);
init();
+
+ debug(9, "_showingHourGlass: %d", _showingHourGlass);
}
Inventory::~Inventory() {
diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp
index 09104d1bf9..d24fb9b598 100644
--- a/engines/lastexpress/game/logic.cpp
+++ b/engines/lastexpress/game/logic.cpp
@@ -413,8 +413,8 @@ void Logic::resetState() {
/**
* Handle game over
*
- * @param type The savegame type.
- * @param value The value (event, time, index, ...)
+ * @param type The savegame type.
+ * @param value The value (event, time, index, ...)
* @param sceneIndex Index of the scene to show.
* @param showScene true to show a scene, false to return to menu directly
*/
diff --git a/engines/lastexpress/game/logic.h b/engines/lastexpress/game/logic.h
index efb8f1e1a3..b2d08cb06f 100644
--- a/engines/lastexpress/game/logic.h
+++ b/engines/lastexpress/game/logic.h
@@ -54,7 +54,7 @@ public:
void playFinalSequence() const;
void updateCursor(bool redraw = true) const;
- Action *getGameAction() { return _action; }
+ Action *getGameAction() { return _action; }
Beetle *getGameBeetle() { return _beetle; }
Entities *getGameEntities() { return _entities; }
Fight *getGameFight() { return _fight; }
diff --git a/engines/lastexpress/game/object.cpp b/engines/lastexpress/game/object.cpp
index 48df91ea6d..2fcdde12b9 100644
--- a/engines/lastexpress/game/object.cpp
+++ b/engines/lastexpress/game/object.cpp
@@ -69,11 +69,12 @@ void Objects::update(ObjectIndex index, EntityIndex entity, ObjectLocation locat
getFlags()->flag_3 = true;
// Compartments
- if (original_location != location && (original_location == kObjectLocation2 || location == kObjectLocation2))
+ if (original_location != location && (original_location == kObjectLocation2 || location == kObjectLocation2)) {
if ((index >= kObjectCompartment1 && index <= kObjectCompartment8)
- || (index >= kObjectCompartmentA && index <= kObjectCompartmentF)) {
- getScenes()->updateDoorsAndClock();
+ || (index >= kObjectCompartmentA && index <= kObjectCompartmentF)) {
+ getScenes()->updateDoorsAndClock();
}
+ }
}
void Objects::updateLocation2(ObjectIndex index, ObjectLocation location2) {
diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h
index 361957227e..257c005e4a 100644
--- a/engines/lastexpress/game/savegame.h
+++ b/engines/lastexpress/game/savegame.h
@@ -167,7 +167,7 @@ public:
bool isGameFinished(uint32 menuIndex, uint32 savegameIndex);
// Accessors
- uint32 getTime(uint32 index) { return getEntry(index)->time; }
+ uint32 getTime(uint32 index) { return getEntry(index)->time; }
ChapterIndex getChapter(uint32 index) { return getEntry(index)->chapter; }
uint32 getValue(uint32 index) { return getEntry(index)->value; }
uint32 getLastSavegameTicks() const { return _gameTicksLastSavegame; }
diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp
index a2c7226b93..82688fff2e 100644
--- a/engines/lastexpress/game/scenes.cpp
+++ b/engines/lastexpress/game/scenes.cpp
@@ -587,8 +587,8 @@ void SceneManager::updateDoorsAndClock() {
Common::String name = Common::String::format("633X%c-%02d.seq", (index - firstIndex) + 65, scene->position);
Sequence *sequence = loadSequence1(name, 255);
- // If the sequence doesn't exists, skip
- if (!sequence || !sequence->isLoaded())
+ // If the sequence doesn't exists or could not be loaded, skip index
+ if (!sequence)
continue;
// Adjust frame data and store in frame list
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index 2c484f6976..83d528d346 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -502,6 +502,7 @@ public:
volume = _defaultVolume;
//Game data
+ field_0 = 0;
time = kTimeCityParis;
timeDelta = _defaultTimeDelta;
timeTicks = 0;
@@ -656,12 +657,12 @@ private:
// Timer
int _timer;
- Flags *_flags; ///< Flags
- Inventory *_inventory; ///< Inventory
- Objects *_objects; ///< Objects
- SavePoints *_savepoints; ///< SavePoints
- GameState *_state; ///< State
- Common::Point _coords; ///< Current coordinates
+ Flags *_flags; ///< Flags
+ Inventory *_inventory; ///< Inventory
+ Objects *_objects; ///< Objects
+ SavePoints *_savepoints; ///< SavePoints
+ GameState *_state; ///< State
+ Common::Point _coords; ///< Current coordinates
};
} // End of namespace LastExpress
diff --git a/engines/lastexpress/graphics.cpp b/engines/lastexpress/graphics.cpp
index 753c3a39e4..9ced38a2e1 100644
--- a/engines/lastexpress/graphics.cpp
+++ b/engines/lastexpress/graphics.cpp
@@ -131,11 +131,11 @@ void GraphicsManager::mergePlanes() {
// Clear screen surface
_screen.fillRect(Common::Rect(640, 480), 0);
- uint16 *screen = (uint16 *)_screen.pixels;
- uint16 *inventory = (uint16 *)_inventory.pixels;
- uint16 *overlay = (uint16 *)_overlay.pixels;
- uint16 *backgroundC = (uint16 *)_backgroundC.pixels;
- uint16 *backgroundA = (uint16 *)_backgroundA.pixels;
+ uint16 *screen = (uint16 *)_screen.getPixels();
+ uint16 *inventory = (uint16 *)_inventory.getPixels();
+ uint16 *overlay = (uint16 *)_overlay.getPixels();
+ uint16 *backgroundC = (uint16 *)_backgroundC.getPixels();
+ uint16 *backgroundA = (uint16 *)_backgroundA.getPixels();
for (int i = 0; i < 640 * 480; i++) {
@@ -160,7 +160,7 @@ void GraphicsManager::mergePlanes() {
void GraphicsManager::updateScreen() {
g_system->fillScreen(0);
- g_system->copyRectToScreen(_screen.getBasePtr(0, 0), 640 * 2, 0, 0, 640, 480);
+ g_system->copyRectToScreen(_screen.getPixels(), 640 * 2, 0, 0, 640, 480);
}
} // End of namespace LastExpress
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 01d2634dec..bc1624d171 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -165,10 +165,10 @@ Common::Error LastExpressEngine::run() {
void LastExpressEngine::pollEvents() {
Common::Event ev;
- _eventMan->pollEvent(ev);
+ if (!_eventMan->pollEvent(ev))
+ return;
switch (ev.type) {
-
case Common::EVENT_LBUTTONUP:
getGameLogic()->getGameState()->getGameFlags()->mouseLeftClick = true;
break;
diff --git a/engines/lure/configure.engine b/engines/lure/configure.engine
new file mode 100644
index 0000000000..e9f92893e3
--- /dev/null
+++ b/engines/lure/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine lure "Lure of the Temptress" yes
diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp
index 3fbbf84469..92f07a566e 100644
--- a/engines/lure/debugger.cpp
+++ b/engines/lure/debugger.cpp
@@ -337,11 +337,11 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
} else if (strcmp(argv[2], "activate") == 0) {
// Activate the hotspot
res.activateHotspot(hs->hotspotId);
- hs->flags &= !HOTSPOTFLAG_MENU_EXCLUSION;
+ hs->flags &= ~HOTSPOTFLAG_MENU_EXCLUSION;
DebugPrintf("Activated\n");
} else if (strcmp(argv[2], "deactivate") == 0) {
- // Activate the hotspot
+ // Deactivate the hotspot
res.deactivateHotspot(hs->hotspotId);
hs->flags |= HOTSPOTFLAG_MENU_EXCLUSION;
DebugPrintf("Deactivated\n");
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index 7fab4521f7..d0b439677d 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -260,8 +260,10 @@ void Hotspot::setAnimation(HotspotAnimData *newRecord) {
_anim = NULL;
_numFrames = 0;
_frameNumber = 0;
- if (!newRecord) return;
- if (!disk.exists(newRecord->animId)) return;
+ if (!newRecord)
+ return;
+ if (!disk.exists(newRecord->animId))
+ return;
// Scan for any size overrides - some animations get their size set after decoding, but
// we want it in advance so we can decode the animation straight to a graphic surface
@@ -516,7 +518,8 @@ void Hotspot::endAction() {
}
void Hotspot::setDirection(Direction dir) {
- if ((_numFrames == 0) || (_direction == dir)) return;
+ if ((_numFrames == 0) || (_direction == dir))
+ return;
uint8 newFrameNumber = 0;
switch (dir) {
@@ -634,7 +637,8 @@ void Hotspot::setOccupied(bool occupiedFlag) {
if (xp < 0) {
xp = -xp;
widthVal -= xp;
- if (widthVal <= 0) return;
+ if (widthVal <= 0)
+ return;
xp = 0;
}
@@ -642,7 +646,8 @@ void Hotspot::setOccupied(bool occupiedFlag) {
int x2 = xp + widthVal - ROOM_PATHS_WIDTH - 1;
if (x2 >= 0) {
widthVal -= (x2 + 1);
- if (widthVal <= 0) return;
+ if (widthVal <= 0)
+ return;
}
RoomPathsData &paths = Resources::getReference().getRoom(_roomNumber)->paths;
@@ -656,14 +661,16 @@ void Hotspot::setOccupied(bool occupiedFlag) {
// walks the character a single step in a sequence defined by the walking list
bool Hotspot::walkingStep() {
- if (_pathFinder.isEmpty()) return true;
+ if (_pathFinder.isEmpty())
+ return true;
// Check to see if the end of the next straight walking slice
if (_pathFinder.stepCtr() >= _pathFinder.top().numSteps()) {
// Move to next slice in walking sequence
_pathFinder.stepCtr() = 0;
_pathFinder.pop();
- if (_pathFinder.isEmpty()) return true;
+ if (_pathFinder.isEmpty())
+ return true;
}
if (_pathFinder.stepCtr() == 0)
@@ -782,13 +789,15 @@ void Hotspot::showMessage(uint16 messageId, uint16 destCharacterId) {
uint16 *v = (uint16 *) (msgData + READ_LE_UINT16(msgData + idx + sizeof(uint16)));
while ((idVal = READ_LE_UINT16(v)) != 0xffff) {
++v;
- if (READ_LE_UINT16(v) == messageId) break;
+ if (READ_LE_UINT16(v) == messageId)
+ break;
++v;
}
// default response if a specific response not found
- if (idVal == 0xffff) idVal = 0x8c4;
+ if (idVal == 0xffff)
+ idVal = 0x8c4;
debugC(ERROR_DETAILED, kLureDebugStrings, "Hotspot::showMessage idVal=%xh", idVal);
if (idVal == 0x76) {
@@ -826,7 +835,8 @@ void Hotspot::handleTalkDialog() {
Room &room = Room::getReference();
// Return if no talk dialog is necessary
- if (_data->talkCountdown == 0) return;
+ if (_data->talkCountdown == 0)
+ return;
debugC(ERROR_DETAILED, kLureDebugAnimations, "Talk countdown = %d", _data->talkCountdown);
if (_data->talkCountdown == CONVERSE_COUNTDOWN_SIZE) {
@@ -933,7 +943,8 @@ static const uint16 validRoomExitHotspots[] = {0x2711, 0x2712, 0x2714, 0x2715, 0
bool Hotspot::isRoomExit(uint16 id) {
for (const uint16 *p = &validRoomExitHotspots[0]; *p != 0; ++p)
- if (*p == id) return true;
+ if (*p == id)
+ return true;
return false;
}
@@ -1043,7 +1054,7 @@ BarPlaceResult Hotspot::getBarPlace() {
index = -1;
while (++index < NUM_SERVE_CUSTOMERS) {
if (barEntry.customers[index].hotspotId == 0)
- break;
+ break;
}
if (index == NUM_SERVE_CUSTOMERS)
@@ -1391,7 +1402,8 @@ void Hotspot::doGet(HotspotData *hotspot) {
Resources &res = Resources::getReference();
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1409,7 +1421,8 @@ void Hotspot::doGet(HotspotData *hotspot) {
if (sequenceOffset != 0) {
uint16 execResult = Script::execute(sequenceOffset);
- if (execResult == 1) return;
+ if (execResult == 1)
+ return;
else if (execResult != 0) {
showMessage(execResult);
return;
@@ -1432,7 +1445,8 @@ void Hotspot::doOperate(HotspotData *hotspot) {
Action action = currentActions().top().supportData().action();
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1467,7 +1481,8 @@ void Hotspot::doOpen(HotspotData *hotspot) {
}
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1487,7 +1502,8 @@ void Hotspot::doOpen(HotspotData *hotspot) {
if (sequenceOffset != 0) {
sequenceOffset = Script::execute(sequenceOffset);
- if (sequenceOffset == 1) return;
+ if (sequenceOffset == 1)
+ return;
if (sequenceOffset != 0) {
if (_exitCtr != 0)
_exitCtr = 4;
@@ -1522,7 +1538,8 @@ void Hotspot::doClose(HotspotData *hotspot) {
}
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1575,7 +1592,8 @@ void Hotspot::doUse(HotspotData *hotspot) {
}
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1616,7 +1634,8 @@ void Hotspot::doGive(HotspotData *hotspot) {
}
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1662,7 +1681,8 @@ void Hotspot::doTalkTo(HotspotData *hotspot) {
(hotspot->hotspotId != BLACKSMITH_ID))) {
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1706,7 +1726,8 @@ void Hotspot::doTell(HotspotData *hotspot) {
assert(character);
HotspotPrecheckResult hsResult = actionPrecheck(hotspot);
- if (hsResult == PC_WAIT) return;
+ if (hsResult == PC_WAIT)
+ return;
else if (hsResult != PC_EXECUTE) {
endAction();
return;
@@ -1800,7 +1821,8 @@ void Hotspot::doAsk(HotspotData *hotspot) {
_data->useHotspotId = usedId;
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1886,14 +1908,17 @@ void Hotspot::doStatus(HotspotData *hotspot) {
HotspotData const &rec = **i;
if (rec.roomNumber == PLAYER_ID) {
- if (numItems++ == 0) strcat(buffer, ": ");
- else strcat(buffer, ", ");
+ if (numItems++ == 0)
+ strcat(buffer, ": ");
+ else
+ strcat(buffer, ", ");
strings.getString(rec.nameId, buffer + strlen(buffer));
}
}
// If there were no items, add in the word 'nothing'
- if (numItems == 0) strcat(buffer, stringList.getString(S_INV_NOTHING));
+ if (numItems == 0)
+ strcat(buffer, stringList.getString(S_INV_NOTHING));
// If the player has money, add it in
uint16 numGroats = res.fieldList().numGroats();
@@ -1943,7 +1968,8 @@ void Hotspot::doBribe(HotspotData *hotspot) {
fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId);
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1968,7 +1994,8 @@ void Hotspot::doBribe(HotspotData *hotspot) {
sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, BRIBE);
if (sequenceOffset != 0) {
sequenceOffset = Script::execute(sequenceOffset);
- if (sequenceOffset != 0) return;
+ if (sequenceOffset != 0)
+ return;
}
uint16 talkIndex = res.fieldList().getField(TALK_INDEX);
@@ -2004,7 +2031,8 @@ void Hotspot::doLockUnlock(HotspotData *hotspot) {
fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId);
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -2156,7 +2184,8 @@ void Hotspot::npcTalkNpcToNpc(HotspotData *hotspot) {
fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId);
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -2594,7 +2623,8 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
if (h.characterMode() == CHARMODE_PLAYER_WAIT) {
h.updateMovement();
- if (bumpedPlayer) return;
+ if (bumpedPlayer)
+ return;
} else {
// All other character modes
if (h.delayCtr() > 0) {
@@ -2691,7 +2721,8 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
res.pausedList().scan(h);
pfResult = pathFinder.process();
- if (pfResult == PF_UNFINISHED) break;
+ if (pfResult == PF_UNFINISHED)
+ break;
debugC(ERROR_DETAILED, kLureDebugAnimations,
"pathFinder done: result = %d", pfResult);
@@ -2863,7 +2894,8 @@ void HotspotTickHandlers::roomExitAnimHandler(Hotspot &h) {
Room &room = Room::getReference();
RoomExitJoinData *rec = res.getExitJoin(h.hotspotId());
- if (!rec) return;
+ if (!rec)
+ return;
RoomExitJoinStruct &rs = (rec->hotspots[0].hotspotId == h.hotspotId()) ?
rec->hotspots[0] : rec->hotspots[1];
@@ -3036,7 +3068,8 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
res.pausedList().scan(h);
pfResult = pathFinder.process();
- if (pfResult == PF_UNFINISHED) break;
+ if (pfResult == PF_UNFINISHED)
+ break;
// Pathfinding is now complete
buffer = pathFinder.getDebugInfo();
@@ -3474,7 +3507,8 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) {
showSelections |= (entry->descId & 0x3fff) != TALK_MAGIC_ID;
}
- if ((entry->preSequenceId & 0x8000) != 0) break;
+ if ((entry->preSequenceId & 0x8000) != 0)
+ break;
}
if (showSelections && (numLines > 1)) {
@@ -3584,7 +3618,8 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) {
debugC(ERROR_DETAILED, kLureDebugAnimations, "Character response pre id = %xh",
_talkResponse->preSequenceId);
- if (!_talkResponse->preSequenceId) break;
+ if (!_talkResponse->preSequenceId)
+ break;
responseNumber = Script::execute(_talkResponse->preSequenceId);
debugC(ERROR_DETAILED, kLureDebugAnimations, "Character response new response = %d",
responseNumber);
@@ -3680,9 +3715,12 @@ void HotspotTickHandlers::grubAnimHandler(Hotspot &h) {
character = ratpouch;
}
- if (character->x() < 72) frameNumber = 0;
- else if (character->x() < 172) frameNumber = 1;
- else frameNumber = 2;
+ if (character->x() < 72)
+ frameNumber = 0;
+ else if (character->x() < 172)
+ frameNumber = 1;
+ else
+ frameNumber = 2;
h.setActionCtr(frameNumber);
h.setFrameNumber(frameNumber);
@@ -3782,7 +3820,8 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) {
// Moving right
h.setPosition(h.x() + 2, h.y());
h.setActionCtr(h.actionCtr() + 1);
- if (h.actionCtr() >= 6) h.setActionCtr(0);
+ if (h.actionCtr() >= 6)
+ h.setActionCtr(0);
}
} else {
// Stop the barman moving
@@ -4006,6 +4045,7 @@ void HotspotTickHandlers::rackSerfAnimHandler(Hotspot &h) {
h.setActionCtr(4);
h.setLayer(2);
+ // Deliberate fall-through
case 4:
if (HotspotScript::execute(&h)) {
h.setLayer(255);
@@ -4230,7 +4270,8 @@ PathFinderResult PathFinder::process() {
while (1) {
// Loop through to process cells in the given area
- if (!returnFlag) _yCtr = 0;
+ if (!returnFlag)
+ _yCtr = 0;
while (returnFlag || (_yCtr < ROOM_PATHS_HEIGHT)) {
if (!returnFlag) _xCtr = 0;
@@ -4238,7 +4279,8 @@ PathFinderResult PathFinder::process() {
if (!returnFlag) {
processCell(&_layer[(_yChangeStart + _yCtr * _yChangeInc) * DECODED_PATHS_WIDTH +
(_xChangeStart + _xCtr * _xChangeInc)]);
- if (breakFlag && (_countdownCtr <= 0)) return PF_UNFINISHED;
+ if (breakFlag && (_countdownCtr <= 0))
+ return PF_UNFINISHED;
} else {
returnFlag = false;
}
@@ -4248,7 +4290,8 @@ PathFinderResult PathFinder::process() {
}
// If the destination cell has been filled in, then break out of loop
- if (*_pDest != 0) break;
+ if (*_pDest != 0)
+ break;
if (_cellPopulated) {
// At least one cell populated, so go repeat loop
@@ -4306,27 +4349,37 @@ PathFinderResult PathFinder::process() {
currDirection = NO_DIRECTION;
while (1) {
v = *pCurrent - 1;
- if (v == 0) break;
+ if (v == 0)
+ break;
newDirection = NO_DIRECTION;
if (!altFlag && (currDirection != LEFT) && (currDirection != RIGHT)) {
// Standard order direction checking
- if (*(pCurrent - DECODED_PATHS_WIDTH) == v) newDirection = DOWN;
- else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) newDirection = UP;
- else if (*(pCurrent + 1) == v) newDirection = LEFT;
- else if (*(pCurrent - 1) == v) newDirection = RIGHT;
+ if (*(pCurrent - DECODED_PATHS_WIDTH) == v)
+ newDirection = DOWN;
+ else if (*(pCurrent + DECODED_PATHS_WIDTH) == v)
+ newDirection = UP;
+ else if (*(pCurrent + 1) == v)
+ newDirection = LEFT;
+ else if (*(pCurrent - 1) == v)
+ newDirection = RIGHT;
} else {
// Alternate order direction checking
- if (*(pCurrent + 1) == v) newDirection = LEFT;
- else if (*(pCurrent - 1) == v) newDirection = RIGHT;
- else if (*(pCurrent - DECODED_PATHS_WIDTH) == v) newDirection = DOWN;
- else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) newDirection = UP;
+ if (*(pCurrent + 1) == v)
+ newDirection = LEFT;
+ else if (*(pCurrent - 1) == v)
+ newDirection = RIGHT;
+ else if (*(pCurrent - DECODED_PATHS_WIDTH) == v)
+ newDirection = DOWN;
+ else if (*(pCurrent + DECODED_PATHS_WIDTH) == v)
+ newDirection = UP;
}
if (newDirection == NO_DIRECTION)
error("Path finding process failed");
// Process for the specified direction
- if (newDirection != currDirection) add(newDirection, 0);
+ if (newDirection != currDirection)
+ add(newDirection, 0);
switch (newDirection) {
case UP:
@@ -4373,8 +4426,10 @@ PathFinderResult PathFinder::process() {
}
// Final Step
- if (_xPos < 0) add(RIGHT, -_xPos);
- else if (_xPos > 0) add(LEFT, _xPos);
+ if (_xPos < 0)
+ add(RIGHT, -_xPos);
+ else if (_xPos > 0)
+ add(LEFT, _xPos);
return result;
}
@@ -4401,16 +4456,20 @@ void PathFinder::processCell(uint16 *p) {
// Check the surrounding cells (up,down,left,right) for values
// Up
vTemp = *(p - DECODED_PATHS_WIDTH);
- if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp;
+ if ((vTemp != 0) && (vTemp < vMax))
+ vMax = vTemp;
// Down
vTemp = *(p + DECODED_PATHS_WIDTH);
- if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp;
+ if ((vTemp != 0) && (vTemp < vMax))
+ vMax = vTemp;
// Left
vTemp = *(p - 1);
- if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp;
+ if ((vTemp != 0) && (vTemp < vMax))
+ vMax = vTemp;
// Right
vTemp = *(p + 1);
- if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp;
+ if ((vTemp != 0) && (vTemp < vMax))
+ vMax = vTemp;
if (vMax != 0xffff) {
// A surrounding cell with a value was found
@@ -4432,7 +4491,8 @@ void PathFinder::scanLine(int numScans, int changeAmount, uint16 *&pEnd, int &v)
for (int ctr = 1; ctr <= numScans; ++ctr) {
pTemp += changeAmount;
if ((*pTemp != 0) && (*pTemp != 0xffff)) {
- if ((v < ctr) || ((v == ctr) && (*pTemp >= *pEnd))) return;
+ if ((v < ctr) || ((v == ctr) && (*pTemp >= *pEnd)))
+ return;
pEnd = pTemp;
v = ctr;
break;
@@ -4447,11 +4507,15 @@ void PathFinder::initVars() {
_destX = _hotspot->destX();
_destY = _hotspot->destY();
- if (_destX < 10) _destX -= 50;
- if (_destX >= FULL_SCREEN_WIDTH-10) _destX += 50;
+ if (_destX < 10)
+ _destX -= 50;
+ if (_destX >= FULL_SCREEN_WIDTH-10)
+ _destX += 50;
- _xPos = 0; _yPos = 0;
- _xDestPos = 0; _yDestPos = 0;
+ _xPos = 0;
+ _yPos = 0;
+ _xDestPos = 0;
+ _yDestPos = 0;
_xCurrent = _hotspot->x();
if (_xCurrent < 0) {
@@ -4621,7 +4685,8 @@ void Support::characterChangeRoom(Hotspot &h, uint16 roomNumber,
if (h.hotspotId() == PLAYER_ID) {
// Room change code for the player
- if (room.cursorState() != CS_NONE) return;
+ if (room.cursorState() != CS_NONE)
+ return;
PlayerNewPosition &p = fields.playerNewPos();
if (checkForIntersectingCharacter(h, newX, newY - 48, roomNumber)) {
@@ -4678,7 +4743,8 @@ bool Support::charactersIntersecting(HotspotData *hotspot1, HotspotData *hotspot
bool Support::isCharacterInList(uint16 *lst, int numEntries, uint16 charId) {
while (numEntries-- > 0)
- if (*lst++ == charId) return true;
+ if (*lst++ == charId)
+ return true;
return false;
}
diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp
index 93deecdcd6..7564ce91a0 100644
--- a/engines/lure/menu.cpp
+++ b/engines/lure/menu.cpp
@@ -47,6 +47,7 @@ MenuRecord::MenuRecord(const MenuRecordBounds *bounds, int numParams, ...) {
va_start(params, numParams);
for (int index = 0; index < _numEntries; ++index)
_entries[index] = va_arg(params, const char *);
+ va_end(params);
// Store position data
_hsxstart = bounds->left; _hsxend = bounds->right;
@@ -458,7 +459,7 @@ Action PopupMenu::Show(int numEntries, Action *actions) {
strList[index] = stringList.getString(*actionPtr++);
uint16 result = Show(numEntries, strList);
- delete strList;
+ Memory::dealloc(strList);
if (result == 0xffff) return NONE;
else return actions[result];
}
diff --git a/engines/made/configure.engine b/engines/made/configure.engine
new file mode 100644
index 0000000000..2266712338
--- /dev/null
+++ b/engines/made/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine made "MADE" yes
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index e8b755cb40..c2c866ff34 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -211,77 +211,77 @@ static const MadeGameDescription gameDescriptions[] = {
3,
},
- {
- // Return to Zork - Italian CD version 1.2 3/31/95 (installed)
+ {
+ // Return to Zork - Italian CD version 1.2 3/31/95 (installed)
// Patch #2685032 submitted by goodoldgeorg
- {
- "rtz",
- "V1.2, 3/31/95, installed, CD",
- AD_ENTRY1s("rtzcd.dat", "5b86035aed0277f96e3d173542b5364a", 523776),
- Common::IT_ITA,
- Common::kPlatformDOS,
+ {
+ "rtz",
+ "V1.2, 3/31/95, installed, CD",
+ AD_ENTRY1s("rtzcd.dat", "5b86035aed0277f96e3d173542b5364a", 523776),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
ADGF_CD,
GUIO0()
- },
- GID_RTZ,
- 0,
- GF_CD,
- 3,
- },
+ },
+ GID_RTZ,
+ 0,
+ GF_CD,
+ 3,
+ },
{
- // Return to Zork - Italian CD version 1.2 3/31/95
+ // Return to Zork - Italian CD version 1.2 3/31/95
// Patch #2685032 submitted by goodoldgeorg
- {
- "rtz",
- "V1.2, 3/31/95, CD",
- AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354971),
- Common::IT_ITA,
- Common::kPlatformDOS,
+ {
+ "rtz",
+ "V1.2, 3/31/95, CD",
+ AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354971),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
ADGF_CD,
GUIO0()
- },
- GID_RTZ,
- 0,
- GF_CD_COMPRESSED,
- 3,
- },
-
- {
- // Return to Zork - French CD version 1.2 5/13/95 (installed)
+ },
+ GID_RTZ,
+ 0,
+ GF_CD_COMPRESSED,
+ 3,
+ },
+
+ {
+ // Return to Zork - French CD version 1.2 5/13/95 (installed)
// Patch #2685032 submitted by goodoldgeorg
- {
- "rtz",
- "V1.2, 5/13/95, installed, CD",
- AD_ENTRY1s("rtzcd.dat", "bde8251a8e34e87c54e3f93147d56c9e", 523776),
- Common::FR_FRA,
- Common::kPlatformDOS,
+ {
+ "rtz",
+ "V1.2, 5/13/95, installed, CD",
+ AD_ENTRY1s("rtzcd.dat", "bde8251a8e34e87c54e3f93147d56c9e", 523776),
+ Common::FR_FRA,
+ Common::kPlatformDOS,
ADGF_CD,
GUIO0()
- },
- GID_RTZ,
- 0,
- GF_CD,
- 3,
- },
-
- {
- // Return to Zork - French CD version 1.2 5/13/95
+ },
+ GID_RTZ,
+ 0,
+ GF_CD,
+ 3,
+ },
+
+ {
+ // Return to Zork - French CD version 1.2 5/13/95
// Patch #2685032 submitted by goodoldgeorg
- {
- "rtz",
- "V1.2, 3/31/95, CD",
- AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354614),
- Common::FR_FRA,
- Common::kPlatformDOS,
+ {
+ "rtz",
+ "V1.2, 3/31/95, CD",
+ AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354614),
+ Common::FR_FRA,
+ Common::kPlatformDOS,
ADGF_CD,
GUIO0()
- },
- GID_RTZ,
- 0,
- GF_CD_COMPRESSED,
- 3,
- },
+ },
+ GID_RTZ,
+ 0,
+ GF_CD_COMPRESSED,
+ 3,
+ },
{
// Return to Zork - English floppy version
diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp
index 4d3fc7116a..a8e33774f6 100644
--- a/engines/made/graphics.cpp
+++ b/engines/made/graphics.cpp
@@ -83,7 +83,7 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u
if ((maskFlags != 0) && (maskFlags != 2) && (pixelFlags != 0) && (pixelFlags != 2) && (cmdFlags != 0))
error("decompressImage() Unsupported flags: cmdFlags = %02X; maskFlags = %02X, pixelFlags = %02X", cmdFlags, maskFlags, pixelFlags);
- byte *destPtr = (byte *)surface.getBasePtr(0, 0);
+ byte *destPtr = (byte *)surface.getPixels();
byte lineBuf[640 * 4];
byte bitBuf[40];
@@ -196,7 +196,7 @@ void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOf
byte *maskBuffer = source + maskOffs;
byte *pixelBuffer = source + pixelOffs;
- byte *destPtr = (byte *)surface.getBasePtr(0, 0);
+ byte *destPtr = (byte *)surface.getPixels();
byte bitBuf[40];
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 3843040961..3e192cb04c 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -85,7 +85,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_script = new ScriptInterpreter(this);
- _music = new MusicPlayer();
+ _music = nullptr;
// Set default sound frequency
switch (getGameID()) {
@@ -102,8 +102,6 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
// Return to Zork sets it itself via a script funtion
break;
}
-
- syncSoundSettings();
}
MadeEngine::~MadeEngine() {
@@ -277,6 +275,8 @@ void MadeEngine::handleEvents() {
}
Common::Error MadeEngine::run() {
+ _music = new MusicPlayer();
+ syncSoundSettings();
// Initialize backend
initGraphics(320, 200, false);
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index cf450f7e25..573ff7faf1 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -248,7 +248,7 @@ void PmvPlayer::handleEvents() {
}
void PmvPlayer::updateScreen() {
- _vm->_system->copyRectToScreen(_surface->pixels, _surface->pitch,
+ _vm->_system->copyRectToScreen(_surface->getPixels(), _surface->pitch,
(320 - _surface->w) / 2, (200 - _surface->h) / 2, _surface->w, _surface->h);
_vm->_system->updateScreen();
}
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp
index ea7d57f82d..30848e8ec1 100644
--- a/engines/made/screen.cpp
+++ b/engines/made/screen.cpp
@@ -344,12 +344,12 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask
void Screen::updateSprites() {
// TODO: This needs some more work, dirty rectangles are currently not used
- memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000);
+ memcpy(_workScreen->getPixels(), _backgroundScreen->getPixels(), 64000);
drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0);
drawSpriteChannels(_workScreenDrawCtx, 1, 2);
- _vm->_system->copyRectToScreen(_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h);
+ _vm->_system->copyRectToScreen(_workScreen->getPixels(), _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h);
_vm->_screen->updateScreenAndWait(10);
}
@@ -593,7 +593,7 @@ void Screen::show() {
return;
drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0);
- memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000);
+ memcpy(_workScreen->getPixels(), _backgroundScreen->getPixels(), 64000);
drawSpriteChannels(_workScreenDrawCtx, 1, 2);
_fx->run(_visualEffectNum, _workScreen, _palette, _newPalette, _paletteColorCount);
@@ -775,7 +775,7 @@ void Screen::unlockScreen() {
}
void Screen::showWorkScreen() {
- _vm->_system->copyRectToScreen(_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h);
+ _vm->_system->copyRectToScreen(_workScreen->getPixels(), _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h);
}
void Screen::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp
index ad71f1fb49..b89b3af802 100644
--- a/engines/made/screenfx.cpp
+++ b/engines/made/screenfx.cpp
@@ -165,7 +165,7 @@ void ScreenEffects::flash(int flashCount, byte *palette, int colorCount) {
_screen->setRGBPalette(_fxPalette, 0, colorCount);
_screen->updateScreenAndWait(20);
_screen->setRGBPalette(palette, 0, colorCount);
- _screen->updateScreenAndWait(20);
+ _screen->updateScreenAndWait(20);
}
}
@@ -368,7 +368,7 @@ void ScreenEffects::vfx07(Graphics::Surface *surface, byte *palette, byte *newPa
// "Screen slide in" right to left
void ScreenEffects::vfx08(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) {
for (int x = 8; x <= 320; x += 8) {
- _screen->copyRectToScreen(surface->getBasePtr(0, 0), surface->pitch, 320 - x, 0, x, 200);
+ _screen->copyRectToScreen(surface->getPixels(), surface->pitch, 320 - x, 0, x, 200);
_screen->updateScreenAndWait(25);
}
setPalette(palette);
@@ -529,7 +529,7 @@ void ScreenEffects::vfx19(Graphics::Surface *surface, byte *palette, byte *newPa
// "Screen slide in" bottom to top
void ScreenEffects::vfx20(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) {
for (int y = 4; y <= 200; y += 4) {
- _screen->copyRectToScreen(surface->getBasePtr(0, 0), surface->pitch, 0, 200 - y, 320, y);
+ _screen->copyRectToScreen(surface->getPixels(), surface->pitch, 0, 200 - y, 320, y);
_screen->updateScreenAndWait(25);
}
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index c57778fb71..0e3b50aa98 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -574,7 +574,7 @@ int16 ScriptFunctions::sfLoadMouseCursor(int16 argc, int16 *argv) {
PictureResource *flex = _vm->_res->getPicture(argv[2]);
if (flex) {
Graphics::Surface *surf = flex->getPicture();
- CursorMan.replaceCursor(surf->pixels, surf->w, surf->h, argv[1], argv[0], 0);
+ CursorMan.replaceCursor(surf->getPixels(), surf->w, surf->h, argv[1], argv[0], 0);
_vm->_res->freeResource(flex);
}
return 0;
diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp
index f73c580560..176f8688bd 100644
--- a/engines/made/sound.cpp
+++ b/engines/made/sound.cpp
@@ -228,7 +228,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou
break;
default:
- return;
+ return;
}
diff --git a/engines/mohawk/POTFILES b/engines/mohawk/POTFILES
new file mode 100644
index 0000000000..54d9dcaa3a
--- /dev/null
+++ b/engines/mohawk/POTFILES
@@ -0,0 +1,3 @@
+engines/mohawk/dialogs.cpp
+engines/mohawk/myst.cpp
+engines/mohawk/riven.cpp
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index bc19fe2d3e..b321e043d9 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -580,7 +580,7 @@ void MohawkBitmap::drawRaw(Graphics::Surface *surface) {
_data->skip(_header.bytesPerRow - _header.width * 3);
} else {
- _data->read((byte *)surface->pixels + y * _header.width, _header.width);
+ _data->read((byte *)surface->getBasePtr(0, y), _header.width);
_data->skip(_header.bytesPerRow - _header.width);
}
}
@@ -599,7 +599,7 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
for (uint16 i = 0; i < _header.height; i++) {
uint16 rowByteCount = isLE ? _data->readUint16LE() : _data->readUint16BE();
int32 startPos = _data->pos();
- byte *dst = (byte *)surface->pixels + i * _header.width;
+ byte *dst = (byte *)surface->getBasePtr(0, i);
int16 remaining = _header.width;
while (remaining > 0) {
@@ -779,7 +779,7 @@ MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) {
}
Graphics::Surface *surface = createSurface(_header.width, _header.height);
- memset(surface->pixels, 0, _header.width * _header.height);
+ memset(surface->getPixels(), 0, _header.width * _header.height);
// Expand the <8bpp data to one byte per pixel
switch (getBitsPerPixel()) {
@@ -801,7 +801,7 @@ MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) {
void DOSBitmap::expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) {
assert(surface->format.bytesPerPixel == 1);
- byte *dst = (byte *)surface->pixels;
+ byte *dst = (byte *)surface->getPixels();
// Expand the 8 pixels in a byte into a full byte per pixel
@@ -830,7 +830,7 @@ void DOSBitmap::expandEGAPlanes(Graphics::Surface *surface, Common::SeekableRead
// Note that the image is in EGA planar form and not just standard 4bpp
// This seems to contradict the PoP specs which seem to do something else
- byte *dst = (byte *)surface->pixels;
+ byte *dst = (byte *)surface->getPixels();
for (uint32 i = 0; i < surface->h; i++) {
uint x = 0;
diff --git a/engines/mohawk/configure.engine b/engines/mohawk/configure.engine
new file mode 100644
index 0000000000..fa9d15cffc
--- /dev/null
+++ b/engines/mohawk/configure.engine
@@ -0,0 +1,6 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books"
+add_engine 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/mohawk/cstime.cpp b/engines/mohawk/cstime.cpp
index 3f9827581b..0f69d50a22 100644
--- a/engines/mohawk/cstime.cpp
+++ b/engines/mohawk/cstime.cpp
@@ -51,6 +51,15 @@ MohawkEngine_CSTime::MohawkEngine_CSTime(OSystem *syst, const MohawkGameDescript
_state = kCSTStateStartup;
reset();
+
+ _console = 0;
+ _gfx = 0;
+ _cursor = 0;
+ _interface = 0;
+ _view = 0;
+ _needsUpdate = false;
+ _case = 0;
+ _nextSceneId = 1;
}
MohawkEngine_CSTime::~MohawkEngine_CSTime() {
diff --git a/engines/mohawk/cstime_game.cpp b/engines/mohawk/cstime_game.cpp
index 2e21111025..91d2f895c0 100644
--- a/engines/mohawk/cstime_game.cpp
+++ b/engines/mohawk/cstime_game.cpp
@@ -1094,7 +1094,7 @@ void CSTimeScene::idleAmbientAnims() {
bool CSTimeScene::eventIsActive() {
return _vm->NISIsRunning() /* TODO || _vm->soundIsPlaying()*/ || _vm->getCurrentEventType() == kCSTimeEventWaitForClick
- || _activeChar->_flappingState != 0xffff || _vm->getInterface()->getState() == 4;
+ || _activeChar->_flappingState != 0xffff || _vm->getInterface()->getState() == kCSTimeInterfaceDroppedInventory;
}
void CSTimeScene::cursorOverHotspot(uint id) {
diff --git a/engines/mohawk/cstime_ui.cpp b/engines/mohawk/cstime_ui.cpp
index de7d5bde80..6d5e5dd3ef 100644
--- a/engines/mohawk/cstime_ui.cpp
+++ b/engines/mohawk/cstime_ui.cpp
@@ -854,7 +854,7 @@ void CSTimeInterface::dropItemInInventory(uint16 id) {
clearDialogArea();
_inventoryDisplay->show();
_inventoryDisplay->draw();
- _inventoryDisplay->setState(4);
+ _inventoryDisplay->setState(kCSTimeInterfaceDroppedInventory);
}
CSTimeHelp::CSTimeHelp(MohawkEngine_CSTime *vm) : _vm(vm) {
diff --git a/engines/mohawk/cstime_ui.h b/engines/mohawk/cstime_ui.h
index 27df7cac3e..3154d4b2ef 100644
--- a/engines/mohawk/cstime_ui.h
+++ b/engines/mohawk/cstime_ui.h
@@ -167,7 +167,8 @@ protected:
enum CSTimeInterfaceState {
kCSTimeInterfaceStateNormal = 1,
kCSTimeInterfaceStateDragStart = 2,
- kCSTimeInterfaceStateDragging = 3
+ kCSTimeInterfaceStateDragging = 3,
+ kCSTimeInterfaceDroppedInventory = 4
};
class CSTimeInterface {
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index c7bd03678f..f70efde5fb 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -121,11 +121,11 @@ void MystCursorManager::setCursor(uint16 id) {
// Myst ME stores some cursors as 24bpp images instead of 8bpp
if (surface->format.bytesPerPixel == 1) {
- CursorMan.replaceCursor(surface->pixels, surface->w, surface->h, hotspotX, hotspotY, 0);
+ CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, 0);
CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256);
} else {
Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
- CursorMan.replaceCursor(surface->pixels, surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat);
+ CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat);
}
_vm->_needsUpdate = true;
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index f80dbfacbd..634ff441b6 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -148,16 +148,10 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa
const Common::FSNode gameDataDir(ConfMan.get("path"));
// Rugrats
- const Common::FSNode ProgPath = gameDataDir.getChild("program");
- if (ProgPath.exists())
- SearchMan.addDirectory(ProgPath.getPath(), ProgPath, 0, 2);
- const Common::FSNode RugPath = gameDataDir.getChild("Rugrats Adventure Game");
- if (RugPath.exists())
- SearchMan.addDirectory(RugPath.getPath(), RugPath, 0, 2);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "program", 0, 2);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Rugrats Adventure Game", 0, 2);
// CarmenTQ
- const Common::FSNode CTQPath = gameDataDir.getChild("95instal");
- if (CTQPath.exists())
- SearchMan.addDirectory(CTQPath.getPath(), CTQPath, 0, 4);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "95instal", 0, 4);
}
MohawkEngine_LivingBooks::~MohawkEngine_LivingBooks() {
@@ -317,8 +311,8 @@ void MohawkEngine_LivingBooks::loadBookInfo(const Common::String &filename) {
// - fDebugWindow (always 0?)
if (_bookInfoFile.hasSection("Globals")) {
- const Common::ConfigFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals");
- for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
+ const Common::INIFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals");
+ for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str());
LBCode tempCode(this, 0);
uint offset = tempCode.parseCode(command);
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 76da7d8219..615fcd0e16 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -28,7 +28,7 @@
#include "mohawk/livingbooks_graphics.h"
#include "mohawk/sound.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/rect.h"
#include "common/queue.h"
#include "common/random.h"
@@ -759,7 +759,7 @@ public:
private:
LivingBooksConsole *_console;
- Common::ConfigFile _bookInfoFile;
+ Common::INIFile _bookInfoFile;
Common::String getBookInfoFileName() const;
void loadBookInfo(const Common::String &filename);
diff --git a/engines/mohawk/livingbooks_lbx.cpp b/engines/mohawk/livingbooks_lbx.cpp
index 2b8b22ec81..dcf8caa4a5 100644
--- a/engines/mohawk/livingbooks_lbx.cpp
+++ b/engines/mohawk/livingbooks_lbx.cpp
@@ -33,7 +33,7 @@ public:
bool call(uint callId, const Common::Array<LBValue> &params, LBValue &result);
protected:
- Common::ConfigFile _dataFile;
+ Common::INIFile _dataFile;
Common::String _curSection;
void open(const Common::String &filename);
@@ -77,8 +77,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> &params, LBValu
case kLBXDataFileGetSectionList:
{
Common::SharedPtr<LBList> list = Common::SharedPtr<LBList>(new LBList);
- Common::ConfigFile::SectionList sections = _dataFile.getSections();
- for (Common::List<Common::ConfigFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i)
+ Common::INIFile::SectionList sections = _dataFile.getSections();
+ for (Common::List<Common::INIFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i)
list->array.push_back(LBValue(i->name));
result = LBValue(list);
}
@@ -103,8 +103,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> &params, LBValu
error("incorrect number of parameters (%d) to LBXDataFile::loadCurSectionVars", params.size());
{
- const Common::ConfigFile::SectionKeyList globals = _dataFile.getKeys(_curSection);
- for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
+ const Common::INIFile::SectionKeyList globals = _dataFile.getKeys(_curSection);
+ for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str());
LBCode tempCode(_vm, 0);
uint offset = tempCode.parseCode(command);
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 8140817eb3..975c6c2a21 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -418,6 +418,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
_sound->stopSound();
_sound->stopBackgroundMyst();
+ _video->stopVideos();
if (linkSrcSound)
_sound->playSoundBlocking(linkSrcSound);
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index f17d765c99..dc5f433ce7 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -691,6 +691,7 @@ void Myst::toggleVar(uint16 var) {
else
_state.courtyardImageBoxes |= mask;
}
+ break;
case 41: // Vault white page
if (_globals.ending != 4) {
if (_dockVaultState == 1) {
diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp
index 05e66a3924..cd15960b85 100644
--- a/engines/mohawk/riven_graphics.cpp
+++ b/engines/mohawk/riven_graphics.cpp
@@ -255,7 +255,7 @@ void RivenGraphics::runScheduledTransition() {
}
// For now, just copy the image to screen without doing any transition.
- _vm->_system->copyRectToScreen(_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
+ _vm->_system->copyRectToScreen(_mainScreen->getPixels(), _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
_vm->_system->updateScreen();
_scheduledTransition = -1; // Clear scheduled transition
@@ -345,7 +345,7 @@ void RivenGraphics::drawInventoryImage(uint16 id, const Common::Rect *rect) {
mhkSurface->convertToTrueColor();
Graphics::Surface *surface = mhkSurface->getSurface();
- _vm->_system->copyRectToScreen(surface->pixels, surface->pitch, rect->left, rect->top, surface->w, surface->h);
+ _vm->_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect->left, rect->top, surface->w, surface->h);
delete mhkSurface;
}
@@ -420,7 +420,7 @@ void RivenGraphics::updateCredits() {
} else {
// Otheriwse, we're scrolling
// Move the screen up one row
- memmove(_mainScreen->pixels, _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1));
+ memmove(_mainScreen->getPixels(), _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1));
// Only update as long as we're not before the last frame
// Otherwise, we're just moving up a row (which we already did)
@@ -437,7 +437,7 @@ void RivenGraphics::updateCredits() {
}
// Now flush the new screen
- _vm->_system->copyRectToScreen(_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
+ _vm->_system->copyRectToScreen(_mainScreen->getPixels(), _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
_vm->_system->updateScreen();
}
}
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 8b0130d711..b7e06a2b9f 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -245,7 +245,7 @@ bool VideoManager::updateMovies() {
// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
- _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
+ _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
// We've drawn something to the screen, make sure we update it
updateScreen = true;
diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp
new file mode 100644
index 0000000000..b68dd48b0f
--- /dev/null
+++ b/engines/mortevielle/actions.cpp
@@ -0,0 +1,1674 @@
+/* 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 "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;
+ }
+
+ switch (_coreVar._currPlace) {
+ case MOUNTAIN:
+ if (menuChoice == 1)
+ gotoManorFront();
+ else if (menuChoice == 2)
+ checkManorDistance();
+ _menu.setDestinationText(_coreVar._currPlace);
+ return;
+ case INSIDE_WELL:
+ if (menuChoice == 1)
+ floodedInWell();
+ else if (menuChoice == 2)
+ gotoManorBack();
+ _menu.setDestinationText(_coreVar._currPlace);
+ return;
+ case BUREAU:
+ if (menuChoice == 1)
+ menuChoice = 6;
+ break;
+ case KITCHEN:
+ if (menuChoice == 2)
+ menuChoice = 6;
+ else if (menuChoice == 5)
+ menuChoice = 16;
+ break;
+ case CELLAR:
+ if (menuChoice == 3)
+ menuChoice = 6;
+ break;
+ case LANDING:
+ case ROOM26:
+ if (menuChoice == 4)
+ menuChoice = 6;
+ break;
+ }
+
+ 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;
+
+ switch (menuChoice) {
+ case 1:
+ _coreVar._currPlace = BUREAU;
+ break;
+ case 2:
+ _coreVar._currPlace = KITCHEN;
+ break;
+ case 3:
+ _coreVar._currPlace = CELLAR;
+ break;
+ case 4:
+ _coreVar._currPlace = LANDING;
+ break;
+ case 5:
+ case 12:
+ gotoManorFront();
+ break;
+ case 6:
+ case 11:
+ gotoDiningRoom();
+ break;
+ case 13:
+ _coreVar._currPlace = CHAPEL;
+ break;
+ case 14:
+ _coreVar._currPlace = WELL;
+ break;
+ case 15:
+ checkManorDistance();
+ break;
+ case 16:
+ gotoManorBack();
+ break;
+ case 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();
+ }
+ break;
+ }
+
+ 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 + ((_curSearchObjId - 1) * 10) + _searchCount - 1] = 0;
+ prepareNextObject();
+ ++_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 == JULIA_ROOM) && (_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))
+ displayLookScreen(_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)
+ displayLookScreen(_coreVar._atticRodHoleObjectId);
+ else if (_coreVar._atticBallHoleObjectId != 0)
+ displayLookScreen(_coreVar._atticBallHoleObjectId);
+ } else {
+ _crep = 193;
+ if (_coreVar._atticRodHoleObjectId != 0)
+ displayLookScreen(_coreVar._atticRodHoleObjectId);
+ }
+ }
+ if (_coreVar._currPlace == CELLAR) {
+ _crep = 164;
+ if (_coreVar._cellarObjectId != 0)
+ displayLookScreen(_coreVar._cellarObjectId);
+ }
+ if (_coreVar._currPlace == SECRET_PASSAGE) {
+ _crep = 174;
+ if (_coreVar._secretPassageObjectId != 0)
+ displayLookScreen(_coreVar._secretPassageObjectId);
+ }
+ if (_coreVar._currPlace == WELL) {
+ _crep = 131;
+ if (_coreVar._wellObjectId != 0)
+ displayLookScreen(_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))
+ displayLookScreen(144);
+ if ((_coreVar._currPlace == BLUE_ROOM) && (_num == 3))
+ displayLookScreen(147);
+ if ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 3))
+ displayLookScreen(149);
+ if ((_coreVar._currPlace == JULIA_ROOM) && (_num == 2))
+ displayLookScreen(30);
+ if ((_coreVar._currPlace == DINING_ROOM) && (_num == 3))
+ displayLookScreen(31);
+}
+
+/**
+ * Engine function - Self / Look
+ * @remarks Originally called 'tsregarder'
+ */
+void MortevielleEngine::fctSelftLook() {
+ if (_coreVar._selectedObjectId != 0)
+ displayLookScreen(_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 i;
+ for (i = 1; i <= 6; i++) {
+ if (_num == _openObjects[i])
+ break;
+ }
+
+ if (i <= 6) {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+
+ _curSearchObjId = getFirstObject();
+ if (_curSearchObjId != 0) {
+ _searchCount = 0;
+ _heroSearching = true;
+ _menu.setSearchMenu();
+ prepareNextObject();
+ } else
+ _crep = 997;
+ } else
+ _crep = 187;
+ } 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)
+ displayLookScreen(_coreVar._purpleRoomObjectId);
+ }
+ if (_coreVar._currPlace == CRYPT) {
+ _crep = 123;
+ if (_coreVar._cryptObjectId != 0)
+ displayLookScreen(_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 = _menu._opcodeEnter;
+ _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 i;
+ for (i = 1; (i <= 6); i++) {
+ if ((_openObjects[i] == 0) || (_openObjects[i] == _num))
+ break;
+ }
+
+ if (i > 6) {
+ warning("Unexpected action: Too many open objects");
+ return;
+ }
+
+ if (_openObjects[i] == _num)
+ // display "Already Opened"
+ _crep = 18;
+ else {
+ if (!( ((_num == 3) && ((_coreVar._currPlace == OWN_ROOM)
+ || (_coreVar._currPlace == JULIA_ROOM)
+ || (_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)
+ _soundManager.startSpeech(7, 9, 1);
+ }
+ _openObjects[i] = _num;
+ displayAnimFrame(1, _num);
+ _soundManager.waitSpeech();
+ }
+ int tmpPlace = _coreVar._currPlace;
+ if (_coreVar._currPlace == CRYPT)
+ tmpPlace = CELLAR;
+ _crep = _tabdon[kAouvr + (tmpPlace * 7) + _num - 1];
+ if (_crep == 254)
+ _crep = 999;
+ }
+ }
+}
+
+/**
+ * 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();
+ _soundManager.startSpeech(6, -9, 1);
+
+ // Do you want to enter the hidden passage?
+ int answer = _dialogManager.show(getEngineString(S_YES_NO));
+ if (answer == 1) {
+ Common::String alertTxt = getString(582);
+ _dialogManager.show(alertTxt);
+
+ bool enterPassageFl = _dialogManager.showKnowledgeCheck();
+ _mouse.hideMouse();
+ clearScreen();
+ 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);
+ 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);
+ _soundManager.startSpeech(7, 9, 1);
+ int answer = _dialogManager.show(getEngineString(S_YES_NO));
+ if (answer == 1)
+ _endGame = true;
+ else
+ _crep = 168;
+ }
+ if ((_coreVar._currPlace == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId == 143)) {
+ handleDescriptionText(2, 175);
+ clearVerbBar();
+ _soundManager.startSpeech(6, -9, 1);
+ int answer = _dialogManager.show(getEngineString(S_YES_NO));
+ 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 i;
+ for (i = 1; i <= 6; ++i) {
+ if (_num == _openObjects[i])
+ break;
+ }
+
+ if (i <= 6) {
+ displayAnimFrame(2, _num);
+ _crep = 998;
+ _openObjects[i] = 0;
+ --_openObjCount;
+ if (_openObjCount < 0)
+ _openObjCount = 0;
+ int objId = getFirstObject();
+ if (_curSearchObjId == objId)
+ _curSearchObjId = 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));
+ 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;
+ _soundManager.startSpeech(11, rand, 1);
+ int pres = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId);
+ if (_roomDoorId != OWN_ROOM) {
+ if (pres != -500) {
+ if (rand > pres)
+ _crep = 190;
+ else {
+ setPresenceFlags(_roomDoorId);
+ 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;
+ putObject();
+ if (_crep != 192)
+ displayEmptyHand();
+ return;
+ }
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(7);
+ _crep = 124;
+ if (_num != 0) {
+ int objId = getFirstObject();
+ if (objId == 0)
+ _crep = 997;
+ else {
+ int i;
+ for (i = 1; i <= 6; i++) {
+ if (_num == _openObjects[i])
+ break;
+ }
+
+ if (i <= 6) {
+ _curSearchObjId = objId;
+ _crep = 999;
+ } else
+ _crep = 187;
+ }
+ } 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;
+ displayAnimFrame(1, 7);
+ }
+ } else if (_coreVar._atticRodHoleObjectId != 0) {
+ _crep = 188;
+ } else {
+ _coreVar._atticRodHoleObjectId = _coreVar._selectedObjectId;
+ displayAnimFrame(1, 6);
+ }
+ }
+
+ 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)
+ putObject();
+ 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 pres = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId);
+ if (_roomDoorId != OWN_ROOM) {
+ if (pres != -500) {
+ if (rand > pres)
+ _crep = 101;
+ else {
+ setPresenceFlags(_roomDoorId);
+ int day, hour, minute;
+ updateHour(day, hour, minute);
+ rand = getRandomNumber(1, 100);
+ if ((hour >= 0) && (hour < 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 day, hour, minute;
+ updateHour(day, hour, minute);
+ if ((hour == 12) || (hour == 13) || (hour == 19)) {
+ _coreVar._faithScore -= (_coreVar._faithScore / 7);
+ if (hour == 12) {
+ if (minute == 0)
+ hour = 4;
+ else
+ hour = 3;
+ }
+
+ if ((hour == 13) || (hour == 19)) {
+ if (minute == 0)
+ hour = 2;
+ else
+ hour = 1;
+ }
+
+ _currentHourCount += hour;
+ _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 == JULIA_ROOM) && (_coreVar._selectedObjectId != 136)) {
+ _crep = 189;
+ _coreVar._availableQuestion[8] = '*';
+ } else {
+ int pres = 0;
+ if (!_blo)
+ pres = getPresence(_roomDoorId);
+ if (pres != 0) {
+ if ((_roomDoorId == TOILETS) || (_roomDoorId == BATHROOM))
+ _crep = 179;
+ else {
+ int randVal = (getRandomNumber(0, 10)) - 5;
+ _soundManager.startSpeech(7, randVal, 1);
+ displayAnimFrame(1, 1);
+ _soundManager.waitSpeech();
+
+ int charIndex = convertBitIndexToCharacterIndex(pres);
+ ++_coreVar._faithScore;
+ _coreVar._currPlace = LANDING;
+ _currMenu = MENU_DISCUSS;
+ _currAction = (_menu._discussMenu[charIndex]._menuId << 8) | _menu._discussMenu[charIndex]._actionId;
+ _syn = true;
+ if (_roomDoorId == JULIA_ROOM) {
+ _col = true;
+ _caff = 70;
+ drawPictureWithText();
+ handleDescriptionText(2, _caff);
+ } else
+ _col = false;
+ resetRoomVariables(_roomDoorId);
+ _roomDoorId = OWN_ROOM;
+ }
+ } else {
+ int randVal = (getRandomNumber(0, 10)) - 5;
+ _soundManager.startSpeech(7, randVal, 1);
+ displayAnimFrame(1, 1);
+ _soundManager.waitSpeech();
+
+ _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() {
+ 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();
+ displayTextBlock(getEngineString(S_WANT_TO_WAKE_UP));
+ int day, hour, minute;
+ updateHour(day, hour, minute);
+
+ int answer;
+ do {
+ if (hour < 8) {
+ _coreVar._faithScore -= (_coreVar._faithScore / 20);
+ int z = (7 - hour) * 2;
+ if (minute == 30)
+ --z;
+ _currentHourCount += z;
+ hour = 7;
+ }
+ _currentHourCount += 2;
+ ++hour;
+ if (hour > 23)
+ hour = 0;
+ prepareRoom();
+ answer = _dialogManager.show(getEngineString(S_YES_NO));
+ _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));
+ } 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);
+ menuUp();
+ _mouse.hideMouse();
+ clearScreen();
+ drawDiscussionBox();
+ startDialog(displId);
+ clearScreen();
+ 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 - kResolutionScaler);
+ 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 ((ix == 46) || (_coreVar._availableQuestion[ix] == '*')) {
+ 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();
+ clearScreen();
+ drawDiscussionBox();
+ 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();
+ clearScreen();
+ _mouse.showMouse();
+ }
+ } while ((choice != 46) && (displId != 138));
+ if (_col) {
+ _coreVar._faithScore += (3 * (_coreVar._faithScore / 10));
+ _mouse.hideMouse();
+ clearScreen();
+ drawDiscussionBox();
+ startDialog(138);
+ _mouse.showMouse();
+ _col = false;
+ _coreVar._currPlace = LANDING;
+ }
+ _controlMenu = 0;
+ _mouse.hideMouse();
+ clearScreen();
+ 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;
+ displayNarrativePicture(13, 152);
+ displayEmptyHand();
+ clearUpperLeftPart();
+ clearDescriptionBar();
+ clearVerbBar();
+ handleDescriptionText(9, 1509);
+ testKey(false);
+ _mouse.hideMouse();
+ _caff = 70;
+ _text.taffich();
+ clearScreen();
+ drawDiscussionBox();
+ 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));
+ _quitGame = (answer != 1);
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/configure.engine b/engines/mortevielle/configure.engine
new file mode 100644
index 0000000000..14d6479e7a
--- /dev/null
+++ b/engines/mortevielle/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine mortevielle "Mortevielle" no
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..ee9cb40c99
--- /dev/null
+++ b/engines/mortevielle/detection.cpp
@@ -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.
+ *
+ */
+
+#include "base/plugins.h"
+#include "engines/advancedDetector.h"
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/saveload.h"
+
+namespace Mortevielle {
+struct MortevielleGameDescription {
+ ADGameDescription desc;
+ Common::Language originalLanguage;
+ uint8 dataFeature;
+};
+
+uint32 MortevielleEngine::getGameFlags() const { return _gameDescription->desc.flags; }
+
+Common::Language MortevielleEngine::getLanguage() const { return _gameDescription->desc.language; }
+
+Common::Language MortevielleEngine::getOriginalLanguage() const { return _gameDescription->originalLanguage; }
+
+bool MortevielleEngine::useOriginalData() const { return _gameDescription->dataFeature == kUseOriginalData; }
+
+}
+
+static const PlainGameDescriptor MortevielleGame[] = {
+ {"mortevielle", "Mortville Manor"},
+ {0, 0}
+};
+
+#include "mortevielle/detection_tables.h"
+
+class MortevielleMetaEngine : public AdvancedMetaEngine {
+public:
+ MortevielleMetaEngine() : AdvancedMetaEngine(Mortevielle::MortevielleGameDescriptions, sizeof(Mortevielle::MortevielleGameDescription),
+ MortevielleGame) {
+ _md5Bytes = 512;
+ _singleid = "mortevielle";
+ // Use kADFlagUseExtraAsHint to distinguish between original and improved versions
+ // (i.e. use or not of the game data file).
+ _flags = kADFlagUseExtraAsHint;
+ }
+ 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, (const Mortevielle::MortevielleGameDescription *)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..8d0cd5630c
--- /dev/null
+++ b/engines/mortevielle/detection_tables.h
@@ -0,0 +1,116 @@
+/* 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 MortevielleGameDescription MortevielleGameDescriptions[] = {
+ // French
+ {
+ {
+ "mortevielle",
+ "",
+ {
+ {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ }, Common::FR_FRA, kUseOriginalData
+ },
+ // German
+ {
+ {
+ "mortevielle",
+ "",
+ {
+ {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ }, Common::DE_DEU, kUseOriginalData
+ },
+
+ // German, improved translation
+ {
+ {
+ "mortevielle",
+ "Improved Translation",
+ {
+ {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ }, Common::DE_DEU, kUseEngineDataFile
+ },
+
+ // DOS English version doesn't exist. Technically, they are French or German versions,
+ // using English strings stored mort.dat
+
+ // English on top of French version
+ {
+ {
+ "mortevielle",
+ "",
+ {
+ {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ }, Common::FR_FRA, kUseEngineDataFile
+ },
+
+ // English on top of German version
+ {
+ {
+ "mortevielle",
+ "",
+ {
+ {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ }, Common::DE_DEU, kUseEngineDataFile
+ },
+
+ { AD_TABLE_END_MARKER , Common::EN_ANY, kUseEngineDataFile}
+};
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp
new file mode 100644
index 0000000000..9a2ade60ab
--- /dev/null
+++ b/engines/mortevielle/dialogs.cpp
@@ -0,0 +1,472 @@
+/* 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 "common/str.h"
+
+namespace Mortevielle {
+
+/**
+ * Alert function - Show
+ * @remarks Originally called 'do_alert'
+ */
+int DialogManager::show(const Common::String &msg) {
+ // 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);
+
+ Common::Point curPos;
+ if (alertStr == "") {
+ drawAlertBox(10, 5, colNumb);
+ } else {
+ drawAlertBox(8, 7, colNumb);
+ int 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];
+ curPos.x -= 3;
+ }
+ _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) * kResolutionScaler;
+ 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) * kResolutionScaler;
+ 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 = 1;
+ setPosition(1, coldep, esp);
+ Common::String tmp4(" ");
+ tmp4 += buttonStr[1];
+ 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);
+ col *= 6;
+}
+
+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 firstLine, int lineNum, int width) {
+ if (width > 640)
+ width = 640;
+ int x = 320 - ((uint)width / 2);
+ int y = (firstLine - 1) * 8;
+ int xx = x + width;
+ int yy = y + (lineNum * 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->clearScreen();
+ _vm->_mouse.showMouse();
+ int 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 * kResolutionScaler, 27 + j * 8, (maxLength * 3 + 55) * kResolutionScaler, 34 + j * 8);
+ coor[j]._enabled = true;
+
+ while ((int)choiceArray[j].size() < maxLength) {
+ choiceArray[j] += ' ';
+ }
+ }
+ coor[lastOption - firstOption + 2]._enabled = false;
+ int 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->_soundManager.startSpeech(SpeechNum, 0, 0);
+ _vm->_key = waitForF3F8();
+ if (_vm->shouldQuit())
+ return;
+ } 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 = false;
+ _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..3f30851960
--- /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 firstLine, int lineNum, int width);
+ 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);
+ 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..daf7926438
--- /dev/null
+++ b/engines/mortevielle/graphics.cpp
@@ -0,0 +1,1167 @@
+/* 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.init(bounds.width(), bounds.height(), pitch, getBasePtr(bounds.left, bounds.top), format);
+ 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) {
+ 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.getPixels();
+ *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 = 6;
+
+ 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 = 6;
+
+ 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) {
+ _vm->_screenSurface.fillRect(11, 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..641a527c98
--- /dev/null
+++ b/engines/mortevielle/menu.cpp
@@ -0,0 +1,792 @@
+/* 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}
+};
+
+Menu::Menu() {
+ _opcodeAttach = _opcodeWait = _opcodeForce = _opcodeSleep = OPCODE_NONE;
+ _opcodeListen = _opcodeEnter = _opcodeClose = _opcodeSearch = OPCODE_NONE;
+ _opcodeKnock = _opcodeScratch = _opcodeRead = _opcodeEat = OPCODE_NONE;
+ _opcodePlace = _opcodeOpen = _opcodeTake = _opcodeLook = OPCODE_NONE;
+ _opcodeSmell = _opcodeSound = _opcodeLeave = _opcodeLift = OPCODE_NONE;
+ _opcodeTurn = _opcodeSHide = _opcodeSSearch = _opcodeSRead = OPCODE_NONE;
+ _opcodeSPut = _opcodeSLook = OPCODE_NONE;
+}
+
+void Menu::readVerbNums(Common::File &f, int dataSize) {
+ // Figure out what language Id is needed
+ byte desiredLanguageId;
+ switch(_vm->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;
+ }
+
+ assert(dataSize == 52);
+ _opcodeAttach = f.readUint16LE();
+ _opcodeWait = f.readUint16LE();
+ _opcodeForce = f.readUint16LE();
+ _opcodeSleep = f.readUint16LE();
+ _opcodeListen = f.readUint16LE();
+ _opcodeEnter = f.readUint16LE();
+ _opcodeClose = f.readUint16LE();
+ _opcodeSearch = f.readUint16LE();
+ _opcodeKnock = f.readUint16LE();
+ _opcodeScratch = f.readUint16LE();
+ _opcodeRead = f.readUint16LE();
+ _opcodeEat = f.readUint16LE();
+ _opcodePlace = f.readUint16LE();
+ _opcodeOpen = f.readUint16LE();
+ _opcodeTake = f.readUint16LE();
+ _opcodeLook = f.readUint16LE();
+ _opcodeSmell = f.readUint16LE();
+ _opcodeSound = f.readUint16LE();
+ _opcodeLeave = f.readUint16LE();
+ _opcodeLift = f.readUint16LE();
+ _opcodeTurn = f.readUint16LE();
+ _opcodeSHide = f.readUint16LE();
+ _opcodeSSearch = f.readUint16LE();
+ _opcodeSRead = f.readUint16LE();
+ _opcodeSPut = f.readUint16LE();
+ _opcodeSLook = f.readUint16LE();
+
+ _actionMenu[0]._menuId = OPCODE_NONE >> 8;
+ _actionMenu[0]._actionId = OPCODE_NONE & 0xFF;
+
+ _actionMenu[1]._menuId = _opcodeSHide >> 8;
+ _actionMenu[1]._actionId = _opcodeSHide & 0xFF;
+
+ _actionMenu[2]._menuId = _opcodeAttach >> 8;
+ _actionMenu[2]._actionId = _opcodeAttach & 0xFF;
+
+ _actionMenu[3]._menuId = _opcodeForce >> 8;
+ _actionMenu[3]._actionId = _opcodeForce & 0xFF;
+
+ _actionMenu[4]._menuId = _opcodeSleep >> 8;
+ _actionMenu[4]._actionId = _opcodeSleep & 0xFF;
+
+ _actionMenu[5]._menuId = _opcodeEnter >> 8;
+ _actionMenu[5]._actionId = _opcodeEnter & 0xFF;
+
+ _actionMenu[6]._menuId = _opcodeClose >> 8;
+ _actionMenu[6]._actionId = _opcodeClose & 0xFF;
+
+ _actionMenu[7]._menuId = _opcodeKnock >> 8;
+ _actionMenu[7]._actionId = _opcodeKnock & 0xFF;
+
+ _actionMenu[8]._menuId = _opcodeEat >> 8;
+ _actionMenu[8]._actionId = _opcodeEat & 0xFF;
+
+ _actionMenu[9]._menuId = _opcodePlace >> 8;
+ _actionMenu[9]._actionId = _opcodePlace & 0xFF;
+
+ _actionMenu[10]._menuId = _opcodeOpen >> 8;
+ _actionMenu[10]._actionId = _opcodeOpen & 0xFF;
+
+ _actionMenu[11]._menuId = _opcodeLeave >> 8;
+ _actionMenu[11]._actionId = _opcodeLeave & 0xFF;
+}
+
+/**
+ * Setup a menu's contents
+ * @remarks Originally called 'menut'
+ */
+void Menu::setText(MenuItem item, Common::String name) {
+ Common::String s = name;
+
+ switch (item._menuId) {
+ case MENU_INVENTORY:
+ if (item._actionId != 7) {
+ while (s.size() < 22)
+ s += ' ';
+
+ _inventoryStringArray[item._actionId] = s;
+ _inventoryStringArray[item._actionId].insertChar(' ', 0);
+ }
+ break;
+ case MENU_MOVE: {
+ // If the first character isn't '*' or ' ' then it's missing a heading space
+ char c = s[0];
+ if (c != '*' && c != ' ')
+ s.insertChar(' ', 0);
+
+ while (s.size() < 22)
+ s += ' ';
+
+ _moveStringArray[item._actionId] = s;
+ }
+ break;
+ case MENU_ACTION: {
+ // If the first character isn't '*' or ' ' then it's missing a heading space
+ char c = s[0];
+ if (c != '*' && c != ' ')
+ s.insertChar(' ', 0);
+
+ while (s.size() < 10)
+ s += ' ';
+
+ _actionStringArray[item._actionId] = s;
+ }
+ break;
+ case MENU_SELF: {
+ // If the first character isn't '*' or ' ' then it's missing a heading space
+ char c = s[0];
+ if (c != '*' && c != ' ')
+ s.insertChar(' ', 0);
+
+ while (s.size() < 10)
+ s += ' ';
+
+ _selfStringArray[item._actionId] = s;
+ }
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[item._actionId] = s;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Init destination menu
+ * @remarks Originally called 'tmlieu'
+ */
+void Menu::setDestinationText(int roomId) {
+ Common::String nomp;
+
+ if (roomId == ROOM26)
+ 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], nomp);
+ }
+ nomp = "* ";
+ for (int i = 7; i >= destinationId + 1; --i)
+ setText(_moveMenu[i], nomp);
+}
+
+/**
+ * _disable a menu item
+ * @param menuId Menu number
+ * @param actionId Item index
+ */
+void Menu::disableMenuItem(MenuItem item) {
+ switch (item._menuId) {
+ case MENU_INVENTORY:
+ if (item._actionId > 6) {
+ _inventoryStringArray[item._actionId].setChar('<', 0);
+ _inventoryStringArray[item._actionId].setChar('>', 21);
+ } else
+ _inventoryStringArray[item._actionId].setChar('*', 0);
+ break;
+ case MENU_MOVE:
+ _moveStringArray[item._actionId].setChar('*', 0);
+ break;
+ case MENU_ACTION:
+ _actionStringArray[item._actionId].setChar('*', 0);
+ break;
+ case MENU_SELF:
+ _selfStringArray[item._actionId].setChar('*', 0);
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[item._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(MenuItem item) {
+ switch (item._menuId) {
+ case MENU_INVENTORY:
+ _inventoryStringArray[item._actionId].setChar(' ', 0);
+ _inventoryStringArray[item._actionId].setChar(' ', 21);
+ break;
+ case MENU_MOVE:
+ _moveStringArray[item._actionId].setChar(' ', 0);
+ break;
+ case MENU_ACTION:
+ _actionStringArray[item._actionId].setChar(' ', 0);
+ break;
+ case MENU_SELF:
+ _selfStringArray[item._actionId].setChar(' ', 0);
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[item._actionId].setChar(' ', 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void Menu::displayMenu() {
+ _vm->_mouse.hideMouse();
+ _vm->_screenSurface.fillRect(7, Common::Rect(0, 0, 639, 10));
+
+ int col = 28 * kResolutionScaler;
+ for (int charNum = 0; charNum < 6; charNum++) {
+ // One character after the other
+ int idx = 0;
+ for (int y = 1; y < 9; ++y) {
+ // One column after the other
+ int x = col;
+ for (int k = 0; k < 3; ++k) {
+ // One line after the other
+ uint msk = 0x80;
+ for (int pt = 0; pt <= 7; ++pt) {
+ if ((_charArr[charNum][idx] & 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), 9);
+ }
+ msk >>= 1;
+ ++x;
+ }
+ ++idx;
+ }
+ }
+ col += 48 * kResolutionScaler;
+ }
+ _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) * kResolutionScaler;
+
+ int charWidth = 6;
+ int xmx = dxcar * charWidth + xmn + 2;
+ if ((pos.x > xmn) && (pos.x < xmx) && (pos.y < ymx) && (pos.y > 15)) {
+ int 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) {
+ // Make a copy of the current screen surface for later restore
+ _vm->_backgroundSurface.copyFrom(_vm->_screenSurface);
+
+ // Draw the menu
+ int minX = menuConstants[ii - 1][0] << 3;
+ int lineNum = menuConstants[ii - 1][3];
+ _vm->_mouse.hideMouse();
+ int deltaX = 6;
+ int maxX = minX + (menuConstants[ii - 1][2] * deltaX) + 6;
+ if ((ii == 4) && (_vm->getLanguage() == Common::EN_ANY))
+ // Extra width needed for Self menu in English version
+ maxX = 435;
+
+ _vm->_screenSurface.fillRect(15, Common::Rect(minX, 12, maxX, 10 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.fillRect(0, Common::Rect(maxX, 12, maxX + 4, 10 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.fillRect(0, Common::Rect(minX, 8 + (menuConstants[ii - 1][1] << 1), maxX + 4, 12 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.putxy(minX, 16);
+ for (int i = 1; i <= lineNum; i++) {
+ switch (ii) {
+ case 1:
+ if (_inventoryStringArray[i][0] != '*')
+ _vm->_screenSurface.drawString(_inventoryStringArray[i], 4);
+ break;
+ case 2:
+ if (_moveStringArray[i][0] != '*')
+ _vm->_screenSurface.drawString(_moveStringArray[i], 4);
+ break;
+ case 3:
+ if (_actionStringArray[i][0] != '*')
+ _vm->_screenSurface.drawString(_actionStringArray[i], 4);
+ break;
+ case 4:
+ if (_selfStringArray[i][0] != '*')
+ _vm->_screenSurface.drawString(_selfStringArray[i], 4);
+ break;
+ case 5:
+ if (_discussStringArray[i][0] != '*')
+ _vm->_screenSurface.drawString(_discussStringArray[i], 4);
+ break;
+ case 6:
+ _vm->_screenSurface.drawString(_vm->getEngineString(S_SAVE_LOAD + i), 4);
+ break;
+ case 7: {
+ Common::String s = _vm->getEngineString(S_SAVE_LOAD + 1);
+ s += ' ';
+ s += (char)(48 + i);
+ _vm->_screenSurface.drawString(s, 4);
+ }
+ break;
+ case 8:
+ if (i == 1)
+ _vm->_screenSurface.drawString(_vm->getEngineString(S_RESTART), 4);
+ else {
+ Common::String s = _vm->getEngineString(S_SAVE_LOAD + 2);
+ s += ' ';
+ s += (char)(47 + i);
+ _vm->_screenSurface.drawString(s, 4);
+ }
+ break;
+ default:
+ break;
+ }
+ _vm->_screenSurface.putxy(minX, _vm->_screenSurface._textPos.y + 8);
+ }
+ _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.getPixels();
+
+ // 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 * kResolutionScaler) && curPos.x <= (28 * kResolutionScaler + 24))
+ || (curPos.x >= (76 * kResolutionScaler) && curPos.x <= (76 * kResolutionScaler + 24))
+ || ((curPos.x > 124 * kResolutionScaler) && (curPos.x < 124 * kResolutionScaler + 24))
+ || ((curPos.x > 172 * kResolutionScaler) && (curPos.x < 172 * kResolutionScaler + 24))
+ || ((curPos.x > 220 * kResolutionScaler) && (curPos.x < 220 * kResolutionScaler + 24))
+ || ((curPos.x > 268 * kResolutionScaler) && (curPos.x < 268 * kResolutionScaler + 24)));
+ if (tes) {
+ int ix;
+
+ if (curPos.x < 76 * kResolutionScaler)
+ ix = MENU_INVENTORY;
+ else if (curPos.x < 124 * kResolutionScaler)
+ ix = MENU_MOVE;
+ else if (curPos.x < 172 * kResolutionScaler)
+ ix = MENU_ACTION;
+ else if (curPos.x < 220 * kResolutionScaler)
+ ix = MENU_SELF;
+ else if (curPos.x < 268 * kResolutionScaler)
+ 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::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+void Menu::initMenu() {
+ Common::File f;
+
+ bool menuLoaded = false;
+ // First try to read it from mort.dat if useOriginalData() is false
+ if (!_vm->useOriginalData()) {
+ if (!f.open(MORT_DAT))
+ warning("File %s not found. Using default menu from game data", MORT_DAT);
+ else {
+ // Figure out what language Id is needed
+ byte desiredLanguageId;
+ switch(_vm->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;
+ }
+
+ // Validate the data file header
+ char fileId[4];
+ f.read(fileId, 4);
+ // Do not display warnings here. They would already have been displayed in MortevielleEngine::loadMortDat().
+ if (strncmp(fileId, "MORT", 4) == 0 && f.readByte() >= MORT_DAT_REQUIRED_VERSION) {
+ 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, "MENU", 4)) {
+ // 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);
+ continue;
+ }
+ if (dataSize == 6 * 24) {
+ f.read(_charArr, dataSize);
+ menuLoaded = true;
+ } else
+ warning("Wrong size %d for menu data. Expected %d or less", dataSize, 6 * 24);
+ break;
+ } else {
+ // Other sections
+ f.skip(dataSize);
+ }
+ }
+ }
+ // Close the file
+ f.close();
+ if (!menuLoaded)
+ warning("Failed to load menu from mort.dat. Will use default menu from game data instead.");
+ }
+ }
+
+ if (!menuLoaded) {
+ // Load menu from game data using the original language
+ if (_vm->getOriginalLanguage() == Common::FR_FRA) {
+ if (!f.open("menufr.mor"))
+ error("Missing file - menufr.mor");
+ } else { // Common::DE_DEU
+ if (!f.open("menual.mor"))
+ error("Missing file - menual.mor");
+ }
+ f.read(_charArr, 6 * 24);
+ f.close();
+ }
+
+ // Skipped: dialog asking to swap floppy
+
+ for (int i = 1; i <= 8; ++i)
+ _inventoryStringArray[i] = "* ";
+ _inventoryStringArray[7] = "< -*-*-*-*-*-*-*-*-*- ";
+ for (int i = 1; i <= 7; ++i)
+ _moveStringArray[i] = "* ";
+ for (int i = 1; i < 22; i++) {
+ _actionStringArray[i] = _vm->getString(i + kMenuActionStringIndex);
+ if ((_actionStringArray[i][0] != '*') && (_actionStringArray[i][0] != ' '))
+ _actionStringArray[i].insertChar(' ', 0);
+ while (_actionStringArray[i].size() < 10)
+ _actionStringArray[i] += ' ';
+
+ if (i < 9) {
+ if (i < 6) {
+ _selfStringArray[i] = _vm->getString(i + kMenuSelfStringIndex);
+ if ((_selfStringArray[i][0] != '*') && (_selfStringArray[i][0] != ' '))
+ _selfStringArray[i].insertChar(' ', 0);
+ while (_selfStringArray[i].size() < 10)
+ _selfStringArray[i] += ' ';
+ }
+ _discussStringArray[i] = _vm->getString(i + kMenuSayStringIndex) + ' ';
+ }
+ }
+ for (int 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]);
+ }
+ _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(_moveMenu[i]);
+
+ for (int i = 1; i <= 11; ++i)
+ disableMenuItem(_actionMenu[i]);
+
+ MenuItem miSound;
+ miSound._menuId = _opcodeSound >> 8;
+ miSound._actionId = _opcodeSound & 0xFF;
+
+ MenuItem miLift;
+ miLift._menuId = _opcodeLift >> 8;
+ miLift._actionId = _opcodeLift & 0xFF;
+
+ setText(miSound, _vm->getEngineString(S_SUITE));
+ setText(miLift, _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]);
+
+ MenuItem miSound;
+ miSound._menuId = _opcodeSound >> 8;
+ miSound._actionId = _opcodeSound & 0xFF;
+
+ MenuItem miLift;
+ miLift._menuId = _opcodeLift >> 8;
+ miLift._actionId = _opcodeLift & 0xFF;
+
+ setText(miSound, _vm->getEngineString(S_PROBE));
+ setText(miLift, _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], nomp);
+ enableMenuItem(_inventoryMenu[i]);
+ }
+ }
+
+ if (cy < 6) {
+ for (int i = cy + 1; i <= 6; ++i) {
+ setText(_inventoryMenu[i], " ");
+ disableMenuItem(_inventoryMenu[i]);
+ }
+ }
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/menu.h b/engines/mortevielle/menu.h
new file mode 100644
index 0000000000..debf5b09b6
--- /dev/null
+++ b/engines/mortevielle/menu.h
@@ -0,0 +1,125 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * 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
+};
+
+const int OPCODE_NONE = 0;
+
+struct MenuItem {
+ int _menuId;
+ int _actionId;
+};
+
+class Menu {
+private:
+ MortevielleEngine *_vm;
+
+ byte _charArr[6][24];
+ int _msg3;
+ int _msg4;
+
+ void util(Common::Point pos);
+ void invert(int indx);
+ void menuDown(int ii);
+
+public:
+ Menu();
+
+ 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];
+
+ int _opcodeAttach;
+ int _opcodeWait;
+ int _opcodeForce;
+ int _opcodeSleep;
+ int _opcodeListen;
+ int _opcodeEnter;
+ int _opcodeClose;
+ int _opcodeSearch;
+ int _opcodeKnock;
+ int _opcodeScratch;
+ int _opcodeRead;
+ int _opcodeEat;
+ int _opcodePlace;
+ int _opcodeOpen;
+ int _opcodeTake;
+ int _opcodeLook;
+ int _opcodeSmell;
+ int _opcodeSound;
+ int _opcodeLeave;
+ int _opcodeLift;
+ int _opcodeTurn;
+ int _opcodeSHide;
+ int _opcodeSSearch;
+ int _opcodeSRead;
+ int _opcodeSPut;
+ int _opcodeSLook;
+ MenuItem _actionMenu[12];
+
+ void setParent(MortevielleEngine *vm);
+ void readVerbNums(Common::File &f, int dataSize);
+ void setText(MenuItem item, Common::String name);
+ void setDestinationText(int roomId);
+ void setInventoryText();
+ void disableMenuItem(MenuItem item);
+ void enableMenuItem(MenuItem item);
+ void displayMenu();
+ void drawMenu();
+ void menuUp(int msgId);
+ void eraseMenu();
+ void updateMenu();
+ void initMenu();
+
+ 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..a9f02c2a67
--- /dev/null
+++ b/engines/mortevielle/module.mk
@@ -0,0 +1,23 @@
+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 \
+ 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..d434150977
--- /dev/null
+++ b/engines/mortevielle/mortevielle.cpp
@@ -0,0 +1,458 @@
+/* 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 MortevielleGameDescription *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);
+ _savegameManager.setParent(this);
+ _menu.setParent(this);
+
+ _lastGameFrame = 0;
+ _mouseClick = false;
+ _inMainGameLoop = false;
+ _quitGame = false;
+ _pauseStartTime = -1;
+
+ _roomPresenceLuc = false;
+ _roomPresenceIda = false;
+ _purpleRoomPresenceLeo = false;
+ _roomPresenceGuy = false;
+ _roomPresenceEva = false;
+ _roomPresenceMax = false;
+ _roomPresenceBob = false;
+ _roomPresencePat = false;
+ _toiletsPresenceBobMax = false;
+ _bathRoomPresenceBobMax = false;
+ _juliaRoomPresenceLeo = 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;
+ _place = -1;
+
+ _x26KeyCount = -1;
+ _caff = -1;
+ _day = 0;
+
+ _curPict = nullptr;
+ _curAnim = nullptr;
+ _rightFramePict = nullptr;
+}
+
+MortevielleEngine::~MortevielleEngine() {
+ free(_curPict);
+ free(_curAnim);
+ free(_rightFramePict);
+}
+
+/**
+ * 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);
+}
+
+/**
+ * Pause the game.
+ */
+void MortevielleEngine::pauseEngineIntern(bool pause) {
+ Engine::pauseEngineIntern(pause);
+ if (pause) {
+ if (_pauseStartTime == -1)
+ _pauseStartTime = readclock();
+ } else {
+ if (_pauseStartTime != -1) {
+ int pauseEndTime = readclock();
+ _currentTime += (pauseEndTime - _pauseStartTime);
+ if (_uptodatePresence)
+ _startTime += (pauseEndTime - _pauseStartTime);
+ }
+ _pauseStartTime = -1;
+ }
+}
+
+/**
+ * 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());
+
+ _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();
+
+ loadPalette();
+ loadCFIPH();
+ loadCFIEC();
+ decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64);
+ _x26KeyCount = 1;
+ initMaxAnswer();
+ initMouse();
+
+ loadPlaces();
+ _soundOff = false;
+ _largestClearScreen = false;
+
+ testKeyboard();
+ showConfigScreen();
+ testKeyboard();
+ clearScreen();
+
+ _soundManager.loadNoise();
+ _soundManager.loadAmbiantSounds();
+
+ 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 if (!strncmp(dataType, "VERB", 4)) {
+ _menu.readVerbNums(f, dataSize);
+ } 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();
+ else {
+ _caff = 51;
+ _text.taffich();
+ }
+
+ // Either load the initial game state savegame, or the specified savegame number
+ adzon();
+ resetVariables();
+ if (loadSlot != 0)
+ _savegameManager.loadSavegame(generateSaveFilename(loadSlot));
+
+ // Run the main game loop
+ mainGame();
+
+ // Cleanup (allocated in initialize())
+ _screenSurface.free();
+ free(_soundManager._cfiphBuffer);
+ free(_cfiecBuffer);
+
+ return Common::kNoError;
+}
+
+/**
+ * Show the game introduction
+ */
+void MortevielleEngine::showIntroduction() {
+ _dialogManager.displayIntroScreen(false);
+ _dialogManager.checkForF8(142, false);
+ if (shouldQuit())
+ return;
+
+ _dialogManager.displayIntroFrame2();
+ _dialogManager.checkForF8(143, true);
+ if (shouldQuit())
+ return;
+
+ showTitleScreen();
+ music();
+ _mixer->stopAll();
+}
+
+/**
+ * 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);
+
+ _menu.initMenu();
+
+ charToHour();
+ initGame();
+ clearScreen();
+ 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..5ae94987a0
--- /dev/null
+++ b/engines/mortevielle/mortevielle.h
@@ -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
+ */
+
+#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/outtext.h"
+
+namespace Mortevielle {
+
+// Debug channels
+enum {
+ kMortevielleCore = 1 << 0,
+ kMortevielleGraphics = 1 << 1,
+ kMortevielleSounds = 1 << 2
+};
+
+// Game languages
+enum {
+ MORTDAT_LANG_FRENCH = 0,
+ MORTDAT_LANG_ENGLISH = 1,
+ MORTDAT_LANG_GERMAN = 2
+};
+
+enum {
+ kUseOriginalData = 0,
+ kUseEngineDataFile = 1
+};
+
+// 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 kAsearch = 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;
+
+const int kResolutionScaler = 2;
+/*
+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, JULIA_ROOM = 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
+};
+
+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;
+};
+
+struct MortevielleGameDescription;
+
+class MortevielleEngine : public Engine {
+private:
+ const MortevielleGameDescription *_gameDescription;
+ Common::Stack<int> _keypresses;
+ uint32 _lastGameFrame;
+ Common::Point _mousePos;
+ Common::StringArray _engineStrings;
+ Common::StringArray _gameStrings;
+
+ int _menuOpcode;
+
+ 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 _juliaRoomPresenceLeo;
+ 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 _curSearchObjId;
+ int _controlMenu;
+ int _startTime;
+ int _endTime;
+ Common::Point _stdPal[91][17];
+
+ int _x26KeyCount;
+ int _roomDoorId;
+ int _openObjCount;
+ int _takeObjCount;
+ int _num;
+ int _searchCount;
+ bool _introSpeechPlayed;
+ int _inGameHourDuration;
+ int _x;
+ int _y;
+ int _currentHourCount;
+ int _currentTime;
+ int _pauseStartTime;
+
+ Common::String _hintPctMessage;
+ byte *_cfiecBuffer;
+ int _cfiecBufferSize;
+ int _openObjects[7];
+ 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 loadPalette();
+ void loadTexts();
+ 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 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 setRandomPresenceJuliaRoom(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 displayTextBlock(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);
+ int getFirstObject();
+ void prepareNextObject();
+ void putObject();
+ void resetObjectPlace();
+ void drawDiscussionBox();
+ void displayNarrativePicture(int af, int ob);
+ void menuUp();
+ void displayLookScreen(int objId);
+
+ void adzon();
+
+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;
+ float _addFix;
+ int _savedBitIndex;
+ int _numpal;
+ int _key;
+ bool _mouseClick;
+ SaveStruct _coreVar, _saveStruct;
+
+ int _maff;
+ int _caff;
+ int _crep;
+
+ byte _destinationArray[7][25];
+
+ byte *_curPict;
+ byte *_curAnim;
+ byte *_rightFramePict;
+
+ Debugger _debugger;
+ ScreenSurface _screenSurface;
+ PaletteManager _paletteManager;
+ GfxSurface _backgroundSurface;
+ Common::RandomSource _randomSource;
+ SoundManager _soundManager;
+ SavegameManager _savegameManager;
+ Menu _menu;
+ MouseHandler _mouse;
+ TextHandler _text;
+ DialogManager _dialogManager;
+
+ MortevielleEngine(OSystem *system, const MortevielleGameDescription *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();
+ virtual void pauseEngineIntern(bool pause);
+ virtual GUI::Debugger *getDebugger() {return &_debugger;}
+ uint32 getGameFlags() const;
+ Common::Language getLanguage() const;
+ Common::Language getOriginalLanguage() const;
+ bool useOriginalData() 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 clearScreen();
+};
+
+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..480b4381ef
--- /dev/null
+++ b/engines/mortevielle/mouse.cpp
@@ -0,0 +1,271 @@
+/* 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() {
+ _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 * kResolutionScaler)
+ newPos.x = 314 * kResolutionScaler;
+ 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 * kResolutionScaler;
+ cy = 1;
+ break;
+ case '3':
+ cy = 190;
+ cx = 315 * kResolutionScaler;
+ break;
+ case '5':
+ cy = 100;
+ cx = 155 * kResolutionScaler;
+ 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 = kResolutionScaler * 32;
+ cy = 8;
+ break;
+ case 'D':
+ cx = 80 * kResolutionScaler;
+ cy = 8;
+ break;
+ case 'A':
+ cx = 126 * kResolutionScaler;
+ cy = 8;
+ break;
+ case 'S':
+ cx = 174 * kResolutionScaler;
+ cy = 8;
+ break;
+ case 'P':
+ cx = 222 * kResolutionScaler;
+ cy = 8;
+ break;
+ case 'F':
+ cx = kResolutionScaler * 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..90d1ef310e
--- /dev/null
+++ b/engines/mortevielle/mouse.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This 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;
+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..d50f4005de
--- /dev/null
+++ b/engines/mortevielle/outtext.cpp
@@ -0,0 +1,308 @@
+/* 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) {
+ Common::String s;
+ int i, j;
+
+ // Safeguard: add $ just in case
+ inputStr += '$';
+
+ _vm->_screenSurface.putxy(x, y);
+ int 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 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 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);
+ _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 != _vm->_menu._opcodeEnter)) {
+ 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..c14a03cd60
--- /dev/null
+++ b/engines/mortevielle/saveload.cpp
@@ -0,0 +1,332 @@
+/* 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'
+ */
+bool 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)) {
+ warning("Unable to open save file '%s'", filename.c_str());
+ return false;
+ }
+ 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;
+
+ return true;
+}
+
+/**
+ * Load a saved game
+ */
+Common::Error SavegameManager::loadGame(const Common::String &filename) {
+ g_vm->_mouse.hideMouse();
+ g_vm->displayEmptyHand();
+ if (loadSavegame(filename)) {
+ /* Initialization */
+ g_vm->charToHour();
+ g_vm->initGame();
+ g_vm->gameLoaded();
+ g_vm->_mouse.showMouse();
+ return Common::kNoError;
+ } else
+ return Common::kUnknownError;
+}
+
+/**
+ * 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.getPixels(), 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..79747e6889
--- /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);
+ bool 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..b670246726
--- /dev/null
+++ b/engines/mortevielle/sound.cpp
@@ -0,0 +1,800 @@
+/* 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 "audio/decoders/raw.h"
+#include "common/scummsys.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};
+
+SoundManager::SoundManager(Audio::Mixer *mixer) {
+ _mixer = mixer;
+ _audioStream = nullptr;
+ _ambiantNoiseBuf = nullptr;
+ _noiseBuf = nullptr;
+
+ _soundType = 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;
+ }
+ _buildingSentence = false;
+}
+
+SoundManager::~SoundManager() {
+ if (_audioStream)
+ _audioStream->finish();
+ free(_ambiantNoiseBuf);
+ free(_noiseBuf);
+}
+
+/**
+ * Decode music data
+ */
+int SoundManager::decodeMusic(const byte *PSrc, byte *PDest, int size) {
+ static const int tab[16] = { -96, -72, -48, -32, -20, -12, -8, -4, 0, 4, 8, 12, 20, 32, 48, 72 };
+
+ uint seed = 128;
+ int v;
+ int decompSize = 0;
+ int skipSize = 0;
+
+ for (int idx1 = 0; idx1 < size; ++idx1) {
+ byte srcByte = *PSrc++;
+ v = tab[srcByte >> 4];
+ seed += v;
+ *PDest++ = seed & 0xff;
+
+ v = tab[srcByte & 0xf];
+ seed += v;
+ *PDest++ = seed & 0xff;
+
+ if (srcByte == 0)
+ skipSize += 2;
+ else {
+ decompSize += skipSize + 2;
+ skipSize = 0;
+ }
+ }
+ return decompSize;
+}
+
+/**
+ * Load sonmus.mor file
+ * @remarks Originally called 'charge_son'
+ */
+void SoundManager::loadAmbiantSounds() {
+ Common::File f;
+ if (!f.open("sonmus.mor"))
+ error("Missing file - sonmus.mor");
+
+ free(_ambiantNoiseBuf);
+ int size = f.size();
+ byte *compMusicBuf1 = (byte *)malloc(sizeof(byte) * size);
+ _ambiantNoiseBuf = (byte *)malloc(sizeof(byte) * size * 2);
+ f.read(compMusicBuf1, size);
+ f.close();
+
+ decodeMusic(compMusicBuf1, _ambiantNoiseBuf, size);
+ free(compMusicBuf1);
+}
+
+/**
+ * Speech function - Load Noise files
+ * @remarks Originally called 'charge_bruit' and 'charge_bruit5'
+ */
+void SoundManager::loadNoise() {
+ Common::File f1, f2;
+
+ if (!f1.open("bruits")) //Translation: "noise"
+ error("Missing file - bruits");
+ if (!f2.open("bruit5"))
+ error("Missing file - bruit5");
+
+ _noiseBuf = (byte *)malloc(sizeof(byte) * (f1.size() + f2.size()));
+ assert(f1.size() > 32000);
+
+ f1.read(_noiseBuf, 32000); // 250 * 128
+ f2.read(&_noiseBuf[32000], f2.size());
+ f1.read(&_noiseBuf[32000 + f2.size()], f1.size() - 32000); // 19072
+
+ f1.close();
+ f2.close();
+}
+
+void SoundManager::regenbruit() {
+ int i = 69876;
+ for (int j = 0; j < 100; j++) {
+ _cfiphBuffer[j] = READ_BE_UINT16(&_noiseBuf[i]);
+ i += 2;
+ }
+}
+
+void SoundManager::litph(tablint &t, int typ, int tempo) {
+ // Skip speech
+ if (_soundType == 0)
+ return;
+
+ if (!_buildingSentence) {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+ _buildingSentence = true;
+ }
+ int freq = tempo * 252; // 25.2 * 10
+ int i = 0;
+ while (i < _ptr_oct) {
+ int idx = _troctBuf[i];
+ i++;
+ switch(idx) {
+ case 0: {
+ int val = _troctBuf[i];
+ i++;
+ if (_soundType == 0)
+ warning("TODO: vclas");
+ else if (_soundType == 1) {
+ debugC(5, kMortevielleSounds, "litph - duson");
+ const static int noiseAdr[] = {0, 17224,
+ 17224, 33676,
+ 33676, 51014,
+ 51014, 59396,
+ 59396, 61286,
+ 61286, 69875};
+ if (val > 5) {
+ warning("unhandled index %d", val);
+ } else {
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(freq, false);
+ _audioStream->queueBuffer(&_noiseBuf[noiseAdr[val * 2]], noiseAdr[(val * 2) + 1] - noiseAdr[(val * 2)], DisposeAfterUse::NO, Audio::FLAG_UNSIGNED);
+ }
+ } else { // 2
+ debugC(5, kMortevielleSounds, "litph - vadson");
+ const static int ambiantNoiseAdr[] = {0, 14020,
+ 14020, 18994,
+ 18994, 19630,
+ 19630, 22258,
+ 22258, 37322,
+ 37322, 44472,
+ 44472, 52324,
+ 52324, 59598,
+ 59598, 69748};
+ if (val > 8) {
+ warning("unhandled index %d", val);
+ } else {
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(freq, false);
+ _audioStream->queueBuffer(&_ambiantNoiseBuf[ambiantNoiseAdr[val * 2]], ambiantNoiseAdr[(val * 2) + 1] - ambiantNoiseAdr[(val * 2)], DisposeAfterUse::NO, Audio::FLAG_UNSIGNED);
+ }
+ }
+ i++;
+ break;
+ }
+ case 2: {
+ int val = _troctBuf[i];
+ i++;
+ int tmpidx = (val * 12) + 268;
+ val = _troctBuf[i];
+ i++;
+ warning("TODO: reech %d %d", tmpidx, val);
+ }
+ break;
+ case 4:
+ if (_soundType) {
+ i += 2;
+ } else {
+ // Speech
+ warning("TODO: Interphoneme: consonne:%d voyelle:%d", _troctBuf[i], _troctBuf[i + 1]);
+ i += 2;
+ }
+ break;
+ case 6:
+ warning("TODO: pari2");
+ i += 2;
+ break;
+ default:
+ static byte emptyBuf[19] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ if (idx == 62)
+ warning("TODO: blab");
+ else if (idx == 32) {
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(freq, false);
+ _audioStream->queueBuffer(emptyBuf, 19, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED);
+ } else if (idx == 35) {
+ if (i < _ptr_oct)
+ warning("unexpected 35 - stop the buffering");
+ i = _ptr_oct;
+ } else if (idx == 46) {
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(freq, false);
+ for (int j = 0; j < 10; j++)
+ _audioStream->queueBuffer(emptyBuf, 19, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED);
+ } else {
+ warning("Other code: %d - %d %d", idx, _troctBuf[i], _troctBuf[i + 1]);
+ }
+ break;
+ }
+ }
+}
+
+void SoundManager::playSong(const byte* buf, uint size, uint loops) {
+ int freq = kTempoMusic * 252; // 25.2 * 10
+ Audio::SeekableAudioStream *raw = Audio::makeRawStream(buf, size, freq, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO);
+ Audio::AudioStream *stream = Audio::makeLoopingAudioStream(raw, loops);
+ Audio::SoundHandle songHandle;
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &songHandle, stream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES);
+
+ while (_mixer->isSoundHandleActive(songHandle) && !_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit())
+ ;
+ // In case the handle is still active, stop it.
+ _mixer->stopHandle(songHandle);
+}
+
+void SoundManager::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+void SoundManager::spfrac(int wor) {
+ _queue[2]._rep = (uint)wor >> 12;
+ if ((_soundType == 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 SoundManager::charg_car(int &currWordNumb) {
+ assert(currWordNumb < 1712);
+ int wor = READ_BE_UINT16(&_wordBuf[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_ -= 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 SoundManager::entroct(byte o) {
+ assert(_ptr_oct < 10576);
+ _troctBuf[_ptr_oct] = o;
+ ++_ptr_oct;
+}
+
+void SoundManager::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);
+ }
+}
+
+/**
+ * Load phoneme sound file
+ * @remarks Originally called 'charge_phbruit'
+ */
+void SoundManager::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();
+}
+
+void SoundManager::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) {
+ 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) {
+ 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);
+ }
+ 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:
+ 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)) {
+ 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:
+ 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)) {
+ 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 SoundManager::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 SoundManager::initQueue() {
+ _queue[2]._rep = 0;
+ _queue[2]._freq = 0;
+ _queue[2]._acc = 0;
+ moveQueue();
+ moveQueue();
+}
+
+/**
+ * Handle a phoneme
+ * @remarks Originally called 'trait_ph'
+ */
+void SoundManager::handlePhoneme() {
+ const uint16 deca[3] = {300, 30, 40};
+
+ uint16 startPos = _cfiphBuffer[_phonemeNumb - 1] + deca[_soundType];
+ uint16 endPos = _cfiphBuffer[_phonemeNumb] + deca[_soundType];
+ int wordCount = endPos - startPos;
+
+ startPos /= 2;
+ endPos /= 2;
+ assert((endPos - startPos) < 1711);
+ for (int i = startPos, currWord = 0; i < endPos; i++, currWord += 2)
+ WRITE_BE_UINT16(&_wordBuf[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)'#');
+
+#ifdef DEBUG
+ warning("---");
+ for (int i = 0; i < _ptr_oct; ) {
+ if ((_troctBuf[i] == 32) || (_troctBuf[i] == 35) || (_troctBuf[i] == 46)) {
+ warning("%d", _troctBuf[i]);
+ i++;
+ } else {
+ warning("%d %d %d", _troctBuf[i], _troctBuf[i + 1], _troctBuf[i + 1]);
+ i += 3;
+ }
+ }
+ warning("---");
+#endif
+}
+
+/**
+ * Start speech
+ * @remarks Originally called 'parole'
+ */
+void SoundManager::startSpeech(int rep, int ht, int typ) {
+ uint16 savph[501];
+ int tempo;
+
+ // Hack to avoid a crash in the ending version. To be removed when the speech are implemented
+ if ((rep == 141) && (typ == 0))
+ return;
+
+ if (_vm->_soundOff)
+ return;
+
+ _phonemeNumb = rep;
+ int haut = ht;
+ _soundType = typ;
+ if (_soundType != 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:
+ regenbruit();
+ break;
+ case 2:
+ loadPhonemeSounds();
+ break;
+ default:
+ break;
+ }
+ handlePhoneme();
+ litph(_tbi, typ, tempo);
+
+ _buildingSentence = false;
+ if (typ != 0) {
+ _audioStream->finish();
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream);
+ _audioStream = nullptr;
+ }
+
+ if (_soundType != 0) {
+ for (int i = 0; i <= 500; ++i)
+ _cfiphBuffer[i] = savph[i];
+ }
+ _vm->setPal(_vm->_numpal);
+}
+
+void SoundManager::waitSpeech() {
+ while (_mixer->isSoundHandleActive(_soundHandle) && !_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit())
+ ;
+ // In case the handle is still active, stop it.
+ _mixer->stopHandle(_soundHandle);
+
+ if (!_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit())
+ g_system->delayMillis(600);
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/sound.h b/engines/mortevielle/sound.h
new file mode 100644
index 0000000000..cc0567fd98
--- /dev/null
+++ b/engines/mortevielle/sound.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_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;
+
+const int kNullValue = 255;
+const int kTempoMusic = 71;
+const int kTempoNoise = 78;
+const int kTempoF = 80;
+const int kTempoM = 89;
+
+struct SpeechQueue {
+ int _val;
+ int _code;
+ int _acc;
+ int _freq;
+ int _rep;
+};
+
+typedef int tablint[256];
+
+class SoundManager {
+private:
+ MortevielleEngine *_vm;
+
+ byte *_ambiantNoiseBuf;
+ byte *_noiseBuf;
+ int _phonemeNumb;
+ int _soundType;
+ SpeechQueue _queue[3];
+ byte _wordBuf[1712];
+ byte _troctBuf[10576];
+ bool _buildingSentence;
+ int _ptr_oct;
+ int _tbi[256];
+
+ Audio::QueuingAudioStream *_audioStream;
+
+ void loadPhonemeSounds();
+ void moveQueue();
+ void initQueue();
+ void handlePhoneme();
+
+ void spfrac(int wor);
+ void charg_car(int &currWordNumb);
+ void entroct(byte o);
+ void cctable(tablint &t);
+ void trait_car();
+
+ void regenbruit();
+ void litph(tablint &t, int typ, int tempo);
+
+public:
+ SoundManager(Audio::Mixer *mixer);
+ ~SoundManager();
+
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+ uint16 *_cfiphBuffer;
+
+ void setParent(MortevielleEngine *vm);
+
+ int decodeMusic(const byte *PSrc, byte *PDest, int size);
+ void playSong(const byte *buf, uint usize, uint loops);
+ void loadAmbiantSounds();
+ void loadNoise();
+ void startSpeech(int rep, int ht, int typ);
+ void waitSpeech();
+};
+
+} // End of namespace Mortevielle
+
+#endif
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp
new file mode 100644
index 0000000000..c4f2d5714b
--- /dev/null
+++ b/engines/mortevielle/utils.cpp
@@ -0,0 +1,3405 @@
+/* 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 "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() {
+ bool end = false;
+ // If there isn't any pending keypress, wait until there is
+ while (!shouldQuit() && !end) {
+ end = 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;
+ if (keyPressed() || _mouseClick) {
+ _soundManager._mixer->stopHandle(_soundManager._soundHandle);
+ }
+ } while (!((_menu._menuSelected) || (temps > lim) || (funct) || (_anyone)));
+ _inMainGameLoop = false;
+
+ _menu.eraseMenu();
+ _menu._menuDisplayed = false;
+ 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);
+ 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 == _menu._opcodeSound) || (_currAction == _menu._opcodeLift)) {
+ handledOpcodeFl = true;
+ if ((_currAction == _menu._opcodeLift) || (_obpart)) {
+ endSearch();
+ _caff = _coreVar._currPlace;
+ _crep = 998;
+ } else
+ prepareNextObject();
+ menuUp();
+ }
+ }
+ }
+ 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 newTime = readclock();
+ int th = _currentHourCount + ((newTime - _currentTime) / _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 != JULIA_ROOM)
+ _juliaRoomPresenceLeo = 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]);
+
+ clearUpperRightPart();
+ if ((bitIndex & 128) == 128) {
+ _screenSurface.putxy(xp, 24);
+ _screenSurface.drawString("LEO", 4);
+ _menu.enableMenuItem(_menu._discussMenu[1]);
+ }
+ if ((bitIndex & 64) == 64) {
+ _screenSurface.putxy(xp, 32);
+ _screenSurface.drawString("PAT", 4);
+ _menu.enableMenuItem(_menu._discussMenu[2]);
+ }
+ if ((bitIndex & 32) == 32) {
+ _screenSurface.putxy(xp, 40);
+ _screenSurface.drawString("GUY", 4);
+ _menu.enableMenuItem(_menu._discussMenu[3]);
+ }
+ if ((bitIndex & 16) == 16) {
+ _screenSurface.putxy(xp, 48);
+ _screenSurface.drawString("EVA", 4);
+ _menu.enableMenuItem(_menu._discussMenu[4]);
+ }
+ if ((bitIndex & 8) == 8) {
+ _screenSurface.putxy(xp, 56);
+ _screenSurface.drawString("BOB", 4);
+ _menu.enableMenuItem(_menu._discussMenu[5]);
+ }
+ if ((bitIndex & 4) == 4) {
+ _screenSurface.putxy(xp, 64);
+ _screenSurface.drawString("LUC", 4);
+ _menu.enableMenuItem(_menu._discussMenu[6]);
+ }
+ if ((bitIndex & 2) == 2) {
+ _screenSurface.putxy(xp, 72);
+ _screenSurface.drawString("IDA", 4);
+ _menu.enableMenuItem(_menu._discussMenu[7]);
+ }
+ if ((bitIndex & 1) == 1) {
+ _screenSurface.putxy(xp, 80);
+ _screenSurface.drawString("MAX", 4);
+ _menu.enableMenuItem(_menu._discussMenu[8]);
+ }
+ _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]);
+
+ 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
+ _juliaRoomPresenceLeo = 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 || _juliaRoomPresenceLeo)) ||
+ ((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 == JULIA_ROOM) && (_juliaRoomPresenceLeo)))
+ 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;
+ _currentTime = 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::setRandomPresenceJuliaRoom(int faithScore) {
+ if (!_juliaRoomPresenceLeo) {
+ 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
+ _soundManager.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
+ _soundManager.startSpeech(9, getRandomNumber(2, 4), 1);
+ else if ((_coreVar._currPlace == CHAPEL) && (getRandomNumber(1, 2) == 1))
+ // Type 1: Speech
+ _soundManager.startSpeech(8, 1, 1);
+ else if ((_coreVar._currPlace == WELL) && (getRandomNumber(1, 2) == 2))
+ // Type 1: Speech
+ _soundManager.startSpeech(12, 1, 1);
+ else if (_coreVar._currPlace == INSIDE_WELL)
+ // Type 1: Speech
+ _soundManager.startSpeech(13, 1, 1);
+ else
+ // Type 2 : music
+ _soundManager.startSpeech(getRandomNumber(1, 17), 1, 2);
+ }
+}
+
+/**
+ * Engine function - You lose!
+ * @remarks Originally called 'tperd'
+ */
+void MortevielleEngine::loseGame() {
+ resetOpenObjects();
+ _roomDoorId = OWN_ROOM;
+ _curSearchObjId = 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, 26, 5);
+ _dialogManager.drawF3F8();
+
+ key = 0;
+ do {
+ _soundManager.startSpeech(rep, haut[_caff - 69], 0);
+ key = _dialogManager.waitForF3F8();
+ if (shouldQuit())
+ return;
+ } while (key != 66);
+ clearScreen();
+ _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);
+ menuUp();
+ _mouse.hideMouse();
+ clearScreen();
+ drawDiscussionBox();
+ 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();
+}
+
+/**
+ * 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;
+ _startTime = 0;
+ _endTime = 0;
+ _searchCount = 0;
+ _roomDoorId = OWN_ROOM;
+ _syn = true;
+ _heroSearching = true;
+ _curSearchObjId = 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 == _menu._opcodeLeave) || (_currAction == _menu._opcodeSleep) || (_currAction == _menu._opcodeEat)) {
+ _controlMenu = 4;
+ menuUp();
+ return;
+ }
+ }
+
+ if (_currMenu == MENU_MOVE)
+ fctMove();
+ else if (_currMenu == MENU_DISCUSS)
+ fctDiscuss();
+ else if (_currMenu == MENU_INVENTORY)
+ fctInventoryTake();
+ else if (_currAction == _menu._opcodeAttach)
+ fctAttach();
+ else if (_currAction == _menu._opcodeWait)
+ fctWait();
+ else if (_currAction == _menu._opcodeForce)
+ fctForce();
+ else if (_currAction == _menu._opcodeSleep)
+ fctSleep();
+ else if (_currAction == _menu._opcodeListen)
+ fctListen();
+ else if (_currAction == _menu._opcodeEnter)
+ fctEnter();
+ else if (_currAction == _menu._opcodeClose)
+ fctClose();
+ else if (_currAction == _menu._opcodeSearch)
+ fctSearch();
+ else if (_currAction == _menu._opcodeKnock)
+ fctKnock();
+ else if (_currAction == _menu._opcodeScratch)
+ fctScratch();
+ else if (_currAction == _menu._opcodeRead)
+ fctRead();
+ else if (_currAction == _menu._opcodeEat)
+ fctEat();
+ else if (_currAction == _menu._opcodePlace)
+ fctPlace();
+ else if (_currAction == _menu._opcodeOpen)
+ fctOpen();
+ else if (_currAction == _menu._opcodeTake)
+ fctTake();
+ else if (_currAction == _menu._opcodeLook)
+ fctLook();
+ else if (_currAction == _menu._opcodeSmell)
+ fctSmell();
+ else if (_currAction == _menu._opcodeSound)
+ fctSound();
+ else if (_currAction == _menu._opcodeLeave)
+ fctLeave();
+ else if (_currAction == _menu._opcodeLift)
+ fctLift();
+ else if (_currAction == _menu._opcodeTurn)
+ fctTurn();
+ else if (_currAction == _menu._opcodeSSearch)
+ fctSelfSearch();
+ else if (_currAction == _menu._opcodeSRead)
+ fctSelfRead();
+ else if (_currAction == _menu._opcodeSPut)
+ fctSelfPut();
+ else if (_currAction == _menu._opcodeSLook)
+ fctSelftLook();
+
+ _hiddenHero = false;
+
+ if (_currAction == _menu._opcodeSHide)
+ fctSelfHide();
+ } else if (_anyone) {
+ interactNPC();
+ _anyone = false;
+ menuUp();
+ 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();
+ } else if ((_coreVar._faithScore > 99) && (hour > 0) && (hour < 9)) {
+ _crep = 1508;
+ loseGame();
+ } else if ((day > 1) && (hour > 8) && (!_loseGame)) {
+ _crep = 1502;
+ loseGame();
+ }
+ }
+ menuUp();
+}
+
+/**
+ * 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() {
+ Common::String st;
+
+ _mouse.hideMouse();
+
+ // Clear ambiance description
+ _screenSurface.fillRect(15, Common::Rect(544, 93, 600, 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);
+
+ int 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));
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Reset object place
+ * @remarks Originally called 'copcha'
+ */
+void MortevielleEngine::resetObjectPlace() {
+ 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() {
+ resetObjectPlace();
+
+ _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) {
+ for (int i = 1; i <= 16; ++i) {
+ _curPict[(2 * i)] = _stdPal[n][i].x;
+ _curPict[(2 * i) + 1] = _stdPal[n][i].y;
+ }
+}
+
+/**
+ * Engine function - Load Palette from File
+ * @remarks Originally called 'charpal'
+ */
+void MortevielleEngine::loadPalette() {
+ Common::File f;
+
+ 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");
+
+ // Skip CGA Palette and Patterns
+
+ f.close();
+}
+
+/**
+ * Engine function - Load Texts from File
+ * @remarks Originally called 'chartex'
+ */
+void MortevielleEngine::loadTexts() {
+ Common::File inpFile;
+ Common::File ntpFile;
+
+ _txxFileFl = false;
+ if (!useOriginalData()) {
+ warning("Using improved translation from 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::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");
+ }
+
+ _soundManager._cfiphBuffer = (uint16 *)malloc(sizeof(uint16) * (f.size() / 2));
+
+ for (int i = 0; i < (f.size() / 2); ++i)
+ _soundManager._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");
+
+ int size = f.size();
+ byte *compMusicBuf = (byte *)malloc(sizeof(byte) * size);
+ byte *musicBuf = (byte *)malloc(sizeof(byte) * size * 2);
+ f.read(compMusicBuf, size);
+ f.close();
+
+ int musicSize = _soundManager.decodeMusic(compMusicBuf, musicBuf, size);
+ free(compMusicBuf);
+
+ _soundManager.playSong(musicBuf, musicSize, 5);
+ while (keyPressed())
+ getChar();
+
+ free(musicBuf);
+}
+
+/**
+ * Engine function - Show title screen
+ * @remarks Originally called 'suite'
+ */
+void MortevielleEngine::showTitleScreen() {
+ clearScreen();
+ handleDescriptionText(7, 2035);
+ _caff = 51;
+ _text.taffich();
+ testKeyboard();
+ clearScreen();
+ draw(0, 0);
+
+ Common::String cpr = "COPYRIGHT 1989 : LANKHOR";
+ _screenSurface.putxy(104 + 72 * kResolutionScaler, 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);
+ _mouse.hideMouse();
+ displayPicture(_rightFramePict, 0, 0);
+ _mouse.showMouse();
+}
+
+/**
+ * Read the current system time
+ */
+int MortevielleEngine::readclock() {
+ return (int)(g_system->getMillis() / 1000);
+}
+
+/**
+ * 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 newTime = readclock();
+ if ((newTime - _currentTime) > _inGameHourDuration) {
+ bool activeMenu = _menu._menuActive;
+ _menu.eraseMenu();
+ _currentHourCount += ((newTime - _currentTime) / _inGameHourDuration);
+ _currentTime = newTime;
+ 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 JULIA_ROOM:
+ setRandomPresenceJuliaRoom(_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;
+ _startTime = readclock();
+ if (getRandomNumber(1, 5) < 5) {
+ clearVerbBar();
+ prepareScreenType2();
+ displayTextInVerbBar(getEngineString(S_HEAR_NOISE));
+ int rand = (getRandomNumber(0, 4)) - 2;
+ _soundManager.startSpeech(1, rand, 1);
+ _soundManager.waitSpeech();
+ clearVerbBar();
+ }
+ }
+ }
+ }
+
+ if (activeMenu)
+ _menu.drawMenu();
+ }
+ }
+ _endTime = readclock();
+ if ((_uptodatePresence) && ((_endTime - _startTime) > 17)) {
+ getPresenceBitIndex(_place);
+ _uptodatePresence = false;
+ _startTime = 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;
+
+ _mouse.hideMouse();
+
+ _screenSurface.drawRectangle(570, 118, 20, 10);
+ _screenSurface.drawRectangle(578, 114, 6, 18);
+
+ if (_minute == 0)
+ _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y - rg), 1);
+ else
+ _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y + rg), 1);
+
+ int hour12 = _hour;
+ if (hour12 > 12)
+ hour12 -= 12;
+ if (hour12 == 0)
+ hour12 = 12;
+
+ _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)(x + cv[0][hour12 - 1]) >> 1) * kResolutionScaler, y + cv[1][hour12 - 1], 1);
+ _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];
+ Common::strlcpy(tmp, s.c_str() + idx - 1, size + 1);
+
+ Common::String result(tmp);
+ delete[] tmp;
+ return result;
+}
+
+/**
+ * Clear Screen
+ * @remarks Originally called 'hirs'
+ */
+void MortevielleEngine::clearScreen() {
+ _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;
+ _soundManager.startSpeech(2, rand, 1);
+ _soundManager.waitSpeech();
+ // 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);
+ _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) {
+ Common::String tmpStr = getString(mesgId);
+ if ((y == 182) && ((int) tmpStr.size() > nb))
+ 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 + (kResolutionScaler - 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] = '*';
+ else 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 i = 1; i <= 6; ++i)
+ _openObjects[i] = 0;
+ _openObjCount = 0;
+}
+
+/**
+ * Display Text Block
+ * @remarks Originally called 'ecr2'
+ */
+void MortevielleEngine::displayTextBlock(Common::String text) {
+ // Some dead code was present in the original: removed
+ _screenSurface.putxy(8, 177);
+ int tlig = 59 + (kResolutionScaler - 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], strp);
+ _menu.disableMenuItem(_menu._inventoryMenu[8]);
+}
+
+/**
+ * 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) && (!_juliaRoomPresenceLeo))
+ 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 == JULIA_ROOM) && (!_juliaRoomPresenceLeo) && (!_purpleRoomPresenceLeo))
+ retVal = 10;
+ if ( ((roomId == PURPLE_ROOM) && (_juliaRoomPresenceLeo))
+ || ((roomId == JULIA_ROOM) && (_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 == JULIA_ROOM)
+ _juliaRoomPresenceLeo = 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];
+ _charAnswerCount[idx] = 0;
+ }
+}
+
+/**
+ * Get Presence
+ * @remarks Originally called 't11'
+ */
+int MortevielleEngine::getPresence(int roomId) {
+ int retVal = 0;
+ int rand;
+
+ int pres = getPresenceStats(rand, _coreVar._faithScore, roomId);
+ _place = roomId;
+ if ((roomId > OWN_ROOM) && (roomId < DINING_ROOM)) {
+ if (pres != -500) {
+ if (rand > pres) {
+ displayAloneText();
+ retVal = 0;
+ } else {
+ setPresenceFlags(_place);
+ retVal = getPresenceBitIndex(_place);
+ }
+ } else
+ retVal = getPresenceBitIndex(_place);
+ }
+
+ if (roomId > JULIA_ROOM) {
+ if ((roomId > LANDING) && (roomId != CHAPEL) && (roomId != ROOM26))
+ displayAloneText();
+ else {
+ int h = 0;
+ switch (roomId) {
+ case DINING_ROOM:
+ pres = getPresenceStatsDiningRoom(h);
+ break;
+ case BUREAU:
+ pres = getPresenceStatsBureau(h);
+ break;
+ case KITCHEN:
+ pres = getPresenceStatsKitchen();
+ break;
+ case ATTIC:
+ case CELLAR:
+ pres = getPresenceStatsAttic();
+ break;
+ case LANDING:
+ case ROOM26:
+ pres = getPresenceStatsLanding();
+ break;
+ case CHAPEL:
+ pres = getPresenceStatsChapel(h);
+ break;
+ }
+ pres += _coreVar._faithScore;
+ rand = getRandomNumber(1, 100);
+ if (rand > pres) {
+ displayAloneText();
+ retVal = 0;
+ } else {
+ switch (roomId) {
+ case DINING_ROOM:
+ pres = setPresenceDiningRoom(h);
+ break;
+ case BUREAU:
+ pres = setPresenceBureau(h);
+ break;
+ case KITCHEN:
+ case ATTIC:
+ case CELLAR:
+ pres = setPresenceKitchen();
+ break;
+ case LANDING:
+ case ROOM26:
+ pres = setPresenceLanding();
+ break;
+ case CHAPEL:
+ pres = setPresenceChapel(h);
+ break;
+ }
+ retVal = pres;
+ }
+ }
+ }
+
+ return retVal;
+}
+
+/**
+ * Display Question String
+ * @remarks Originally called 'writetp'
+ */
+void MortevielleEngine::displayQuestionText(Common::String s, int cmd) {
+ _screenSurface.drawString(s, 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 i = 1; i <= 6; ++i) {
+ if (_openObjects[i] != 0)
+ displayAnimFrame(1, _openObjects[i]);
+ }
+
+ switch (_caff) {
+ case ATTIC:
+ if (_coreVar._atticBallHoleObjectId == 141)
+ displayAnimFrame(1, 7);
+
+ if (_coreVar._atticRodHoleObjectId == 159)
+ displayAnimFrame(1, 6);
+ break;
+ case CELLAR:
+ if (_coreVar._cellarObjectId == 151)
+ displayAnimFrame(1, 2);
+ break;
+ case SECRET_PASSAGE:
+ if (_coreVar._secretPassageObjectId == 143)
+ displayAnimFrame(1, 1);
+ break;
+ case WELL:
+ if (_coreVar._wellObjectId != 0)
+ displayAnimFrame(1, 1);
+ break;
+ }
+ }
+
+ 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);
+ quest = keyPressed();
+ if (quest && shouldQuit())
+ return;
+ } 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();
+}
+
+/**
+ * Display Narrative Picture
+ * @remarks Originally called 'tlu'
+ */
+void MortevielleEngine::displayNarrativePicture(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;
+ _curSearchObjId = 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 :
+ displayNarrativePicture(_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);
+ }
+}
+
+/**
+ * Menu up
+ * @remarks Originally called 'mennor'
+ */
+void MortevielleEngine::menuUp() {
+ _menu.menuUp(_currMenu);
+}
+
+/**
+ * Draw discussion box
+ * @remarks Originally called 'premtet'
+ */
+void MortevielleEngine::drawDiscussionBox() {
+ draw(10, 80);
+ _screenSurface.drawBox(18, 79, 155, 92, 15);
+}
+
+/**
+ * Try to put an object somewhere
+ * @remarks Originally called 'ajchai'
+ */
+void MortevielleEngine::putObject() {
+ int putId = kAcha + ((_curSearchObjId - 1) * 10) - 1;
+ int i;
+ for (i = 1; (i <= 9) && (_tabdon[putId + i] != 0); i++)
+ ;
+
+ if (_tabdon[putId + i] == 0)
+ _tabdon[putId + i] = _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;
+
+ for (i = 1; (i <= 5) && (_coreVar._inventory[i] != 0); i++)
+ ;
+
+ 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)
+ _soundManager.startSpeech(5, 2, 1);
+ else
+ _soundManager.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 charIdx = convertBitIndexToCharacterIndex(_currBitIndex);
+ _caff = 69 + charIdx;
+ _crep = _caff;
+ _currMenu = MENU_DISCUSS;
+ _currAction = (_menu._discussMenu[charIdx]._menuId << 8) | _menu._discussMenu[charIdx]._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;
+ _soundManager.startSpeech(3, rand, 1);
+ clearDescriptionBar();
+ displayAloneText();
+ resetRoomVariables(MANOR_FRONT);
+ prepareDisplayText();
+ }
+ }
+ if (_menu._menuDisplayed)
+ _menu.drawMenu();
+}
+
+/**
+ * Search - Prepare next object
+ * @remarks Originally called 'tsuiv'
+ */
+void MortevielleEngine::prepareNextObject() {
+ int objId;
+ int tabIdx = kAcha + ((_curSearchObjId - 1) * 10) - 1;
+ int localSeearchCount = 0;
+ do {
+ ++localSeearchCount;
+ ++_searchCount;
+ objId = _tabdon[tabIdx + _searchCount];
+ } while ((objId == 0) && (_searchCount <= 9));
+
+ if ((objId != 0) && (_searchCount < 11)) {
+ _caff = objId;
+ _crep = _caff + 400;
+ if (_currBitIndex != 0)
+ // Someone is present in the room
+ _coreVar._faithScore += 2;
+ } else {
+ prepareDisplayText();
+ endSearch();
+ if (localSeearchCount > 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 * kResolutionScaler) && (_mouse._pos.y < 176) && (_mouse._pos.y > 12);
+ prepareRoom();
+ } while (!(qust || inRect || _anyone));
+
+ if (qust && (touch == '\103'))
+ _dialogManager.show(_hintPctMessage);
+ } 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] * kResolutionScaler;
+ sy = _tabdon[(a + cb + 1)];
+ cb += 2;
+ ix = _tabdon[a + cb] * kResolutionScaler;
+ 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;
+}
+
+/**
+ * Display LOOK Screen
+ * @remarks Originally called 'treg'
+ */
+void MortevielleEngine::displayLookScreen(int objId) {
+ int mdes = _caff;
+ _caff = objId;
+
+ if (((_caff > 29) && (_caff < 33)) || (_caff == 144) || (_caff == 147) || (_caff == 149) || (_currAction == _menu._opcodeSLook)) {
+ 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;
+ }
+}
+
+/**
+ * Search - Get the first object
+ * @remarks Originally called 'rechai'
+ */
+int MortevielleEngine::getFirstObject() {
+ int tmpPlace = _coreVar._currPlace;
+
+ if (_coreVar._currPlace == CRYPT)
+ tmpPlace = CELLAR;
+
+ return _tabdon[kAsearch + (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) {
+ _mouse.hideMouse();
+ _screenSurface.writeCharacter(Common::Point(306, 193), stat, 12);
+ _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/POTFILES b/engines/neverhood/POTFILES
new file mode 100644
index 0000000000..36628cf4dd
--- /dev/null
+++ b/engines/neverhood/POTFILES
@@ -0,0 +1,2 @@
+engines/neverhood/detection.cpp
+engines/neverhood/menumodule.cpp
diff --git a/engines/neverhood/background.cpp b/engines/neverhood/background.cpp
index 0a80bd8390..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() {
@@ -45,7 +45,7 @@ Background::~Background() {
}
void Background::createSurface(int surfacePriority, int16 width, int16 height) {
- _surface = new BaseSurface(_vm, surfacePriority, width, height);
+ _surface = new BaseSurface(_vm, surfacePriority, width, height, "background");
_surface->setTransparent(false);
_spriteResource.getPosition().x = width;
_spriteResource.getPosition().y = height;
diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp
index 9f5f46487c..c743037e63 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)
@@ -131,7 +131,8 @@ void BlbArchive::load(BlbArchiveEntry *entry, byte *buffer, uint32 size) {
break;
case 3: // DCL-compressed
if (!Common::decompressDCL(&_fd, buffer, entry->diskSize, entry->size))
- error("BlbArchive::load() Error during decompression of %08X", entry->fileHash);
+ error("BlbArchive::load() Error during decompression of %08X (offset: %d, disk size: %d, size: %d)",
+ entry->fileHash, entry->offset, entry->diskSize, entry->size);
break;
default:
error("BlbArchive::load() Unknown compression type %d", entry->comprType);
diff --git a/engines/neverhood/configure.engine b/engines/neverhood/configure.engine
new file mode 100644
index 0000000000..0767a631f9
--- /dev/null
+++ b/engines/neverhood/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine neverhood "Neverhood" no
diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp
new file mode 100644
index 0000000000..34438d821f
--- /dev/null
+++ b/engines/neverhood/console.cpp
@@ -0,0 +1,269 @@
+/* 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 "neverhood/console.h"
+#include "gui/debugger.h"
+#include "neverhood/neverhood.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/navigationscene.h"
+#include "neverhood/scene.h"
+#include "neverhood/smackerscene.h"
+#include "neverhood/sound.h"
+#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module3000_sprites.h"
+
+namespace Neverhood {
+
+Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) {
+ DCmd_Register("cheat", WRAP_METHOD(Console, Cmd_Cheat));
+ DCmd_Register("checkresource", WRAP_METHOD(Console, Cmd_CheckResource));
+ DCmd_Register("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource));
+ DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars));
+ DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound));
+ DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene));
+ DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces));
+}
+
+Console::~Console() {
+}
+
+bool Console::Cmd_Scene(int argc, const char **argv) {
+ if (argc != 3) {
+ int currentModule = _vm->_gameModule->getCurrentModuleNum();
+ int previousModule = _vm->_gameModule->getPreviousModuleNum();
+ int scenenNum = _vm->gameState().sceneNum;
+ SceneType sceneType = ((GameModule *)_vm->_gameModule->_childObject)->getSceneType();
+
+ const char *sceneTypes[] = { "normal", "smacker", "navigation" };
+
+ DebugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]);
+
+ if (sceneType == kSceneTypeNormal) {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ // Normal scenes have a background and a cursor file hash
+ DebugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash());
+ } else if (sceneType == kSceneTypeSmacker) {
+ SmackerScene *scene = (SmackerScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ // Smacker scenes have a file hash, or a list of hashes
+ // TODO: Only the first file hash is shown - any additional hashes, found in
+ // scenes with a list of hashes (two scenes in module 1100 and the making of
+ // video) aren't shown yet
+ DebugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash());
+ } else if (sceneType == kSceneTypeNavigation) {
+ NavigationScene *scene = (NavigationScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ // Navigation scenes have a navigation list and its index
+ NavigationList *navigationList = _vm->_staticData->getNavigationList(scene->getNavigationListId());
+ int navigationIndex = scene->getGlobalVar(V_NAVIGATION_INDEX);
+ NavigationItem curNavigation = (*navigationList)[navigationIndex];
+ DebugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex);
+ DebugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n",
+ curNavigation.fileHash, curNavigation.mouseCursorFileHash,
+ curNavigation.leftSmackerFileHash, curNavigation.middleSmackerFileHash, curNavigation.rightSmackerFileHash);
+ }
+
+ DebugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]);
+ DebugPrintf("Modules are incremental by 100, from 1000 to 3000\n");
+ } else {
+ int newModule = atoi(argv[1]);
+ int newScene = atoi(argv[2]);
+
+ _vm->gameState().sceneNum = newScene;
+ _vm->_gameModule->createModule(newModule, -1);
+ }
+
+ return true;
+}
+
+bool Console::Cmd_Surfaces(int argc, const char **argv) {
+ if (_vm->_gameModule->_childObject) {
+ ((Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject)->printSurfaces(this);
+ }
+ return true;
+}
+
+bool Console::Cmd_Cheat(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Cheats for various puzzles in the game\n");
+ DebugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]);
+ DebugPrintf("Cheats:\n-------\n");
+ DebugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n");
+ DebugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n");
+ DebugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n");
+ DebugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n");
+ 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");
+ return true;
+ }
+
+ Common::String cheatName = argv[1];
+ int moduleNum = _vm->_gameModule->getCurrentModuleNum();
+ int sceneNum = _vm->gameState().sceneNum;
+
+ if (cheatName == "buttons") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+
+ scene->setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 1); // kScene3010ButtonNameHashes[0]
+ scene->setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); // kScene3010ButtonNameHashes[1]
+ scene->setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); // kScene3010ButtonNameHashes[2]
+
+ DebugPrintf("All 3 door buttons have been enabled\n");
+ } else if (cheatName == "cannon") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+
+ for (int i = 0; i < 3; i++)
+ scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_1, i));
+
+ for (int i = 3; i < 6; i++)
+ scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_2, i - 3));
+
+ DebugPrintf("Puzzle solved\n");
+ } else if (cheatName == "dice") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ DebugPrintf("Good: (%d %d %d), current: (%d %d %d)\n",
+ scene->getSubVar(VA_GOOD_DICE_NUMBERS, 0), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 1), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 2),
+ scene->getSubVar(VA_CURR_DICE_NUMBERS, 0), scene->getSubVar(VA_CURR_DICE_NUMBERS, 1), scene->getSubVar(VA_CURR_DICE_NUMBERS, 2)
+ );
+ } else if (cheatName == "memory") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+
+ // Autosolve all tiles and leave only two matching tiles closed
+ for (int i = 0; i < 48; i++)
+ scene->setSubVar(VA_IS_TILE_MATCH, i, 1);
+
+ // Close the top left tile
+ scene->setSubVar(VA_IS_TILE_MATCH, 0, 0);
+
+ // Find and close the pair of the top left tile
+ for (int i = 0; i < 48; i++) {
+ if (i != 0 && scene->getSubVar(VA_TILE_SYMBOLS, i) == scene->getSubVar(VA_TILE_SYMBOLS, 0)) {
+ scene->setSubVar(VA_IS_TILE_MATCH, i, 0);
+ break;
+ }
+ }
+
+ DebugPrintf("Puzzle solved\n");
+ } else if (cheatName == "music") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ DebugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX));
+ } else if (cheatName == "radio") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ scene->setGlobalVar(V_RADIO_ENABLED, 1);
+
+ DebugPrintf("The radio has been enabled\n");
+ } else if (cheatName == "symbols") {
+ if (moduleNum == 1600 && sceneNum == 8) {
+ Scene1609 *scene = ((Scene1609 *)((Module1600 *)_vm->_gameModule->_childObject)->_childObject);
+
+ for (int index = 0; index < 12; index++) {
+ scene->_asSymbols[index]->change((int)scene->getSubVar(VA_CODE_SYMBOLS, index) + 12, index == (int)scene->getSubVar(VA_CODE_SYMBOLS, scene->_noisySymbolIndex));
+ }
+
+ scene->_changeCurrentSymbol = false;
+ scene->_symbolPosition = 11;
+ scene->_countdown1 = 36;
+
+ DebugPrintf("Puzzle solved\n");
+ } else {
+ DebugPrintf("Only available in module 1600, scene 8\n");
+ }
+ } else if (cheatName == "tubes") {
+ Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
+ DebugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2));
+ DebugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2));
+ }
+
+ return true;
+}
+
+bool Console::Cmd_Dumpvars(int argc, const char **argv) {
+ _vm->_gameVars->dumpVars(this);
+
+ 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;
+}
+
+bool Console::Cmd_CheckResource(int argc, const char **argv) {
+ const char *resourceNames[] = { "unknown", "unknown", "bitmap", "palette", "animation", "data", "text", "sound", "music", "unknown", "video" };
+
+ if (argc < 2) {
+ DebugPrintf("Gets information about a resource\n");
+ DebugPrintf("Usage: %s <resource hash>\n", argv[0]);
+ } else {
+ uint32 resourceHash = strtol(argv[1], NULL, 0);
+ ResourceHandle handle;
+
+ _vm->_res->queryResource(resourceHash, handle);
+ if (!handle.isValid()) {
+ DebugPrintf("Invalid resource hash\n");
+ } else {
+ DebugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size());
+ }
+ }
+
+ return true;
+}
+
+bool Console::Cmd_DumpResource(int argc, const char **argv) {
+ if (argc < 3) {
+ DebugPrintf("Dumps a resource to disk\n");
+ DebugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]);
+ } else {
+ uint32 resourceHash = strtol(argv[1], NULL, 0);
+ const char *outFileName = argv[2];
+ ResourceHandle handle;
+
+ _vm->_res->queryResource(resourceHash, handle);
+ if (!handle.isValid()) {
+ DebugPrintf("Invalid resource hash\n");
+ } else {
+ _vm->_res->loadResource(handle, _vm->applyResourceFixes());
+ Common::DumpFile outFile;
+ outFile.open(outFileName);
+ outFile.write(handle.data(), handle.size());
+ outFile.finalize();
+ outFile.close();
+ _vm->_res->unloadResource(handle);
+ }
+ }
+
+ return true;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/console.h b/engines/neverhood/console.h
new file mode 100644
index 0000000000..70260a96af
--- /dev/null
+++ b/engines/neverhood/console.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_CONSOLE_H
+#define NEVERHOOD_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Neverhood {
+
+class NeverhoodEngine;
+
+class Console : public GUI::Debugger {
+public:
+ Console(NeverhoodEngine *vm);
+ virtual ~Console(void);
+
+private:
+ NeverhoodEngine *_vm;
+
+ bool Cmd_Scene(int argc, const char **argv);
+ 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);
+ bool Cmd_CheckResource(int argc, const char **argv);
+ bool Cmd_DumpResource(int argc, const char **argv);
+
+};
+
+} // End of namespace Neverhood
+#endif
diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp
index 5f860f8519..e5486bbcf5 100644
--- a/engines/neverhood/detection.cpp
+++ b/engines/neverhood/detection.cpp
@@ -24,6 +24,7 @@
#include "engines/advancedDetector.h"
#include "common/file.h"
+#include "common/translation.h"
#include "neverhood/neverhood.h"
@@ -51,6 +52,10 @@ Common::Platform NeverhoodEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
+Common::Language NeverhoodEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
uint16 NeverhoodEngine::getVersion() const {
return _gameDescription->version;
}
@@ -59,6 +64,10 @@ bool NeverhoodEngine::isDemo() const {
return _gameDescription->desc.flags & ADGF_DEMO;
}
+bool NeverhoodEngine::applyResourceFixes() const {
+ return getLanguage() == Common::RU_RUS;
+}
+
}
static const PlainGameDescriptor neverhoodGames[] = {
@@ -143,6 +152,20 @@ static const NeverhoodGameDescription gameDescriptions[] = {
} // End of namespace Neverhood
+static const ExtraGuiOption neverhoodExtraGuiOption1 = {
+ _s("Use original save/load screens"),
+ _s("Use the original save/load screens, instead of the ScummVM ones"),
+ "originalsaveload",
+ false
+};
+
+static const ExtraGuiOption neverhoodExtraGuiOption2 = {
+ _s("Skip the Hall of Records storyboard scenes"),
+ _s("Allows the player to skip past the Hall of Records storyboard scenes"),
+ "skiphallofrecordsscenes",
+ false
+};
+
class NeverhoodMetaEngine : public AdvancedMetaEngine {
public:
NeverhoodMetaEngine() : AdvancedMetaEngine(Neverhood::gameDescriptions, sizeof(Neverhood::NeverhoodGameDescription), neverhoodGames) {
@@ -160,7 +183,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
-
+ virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
void removeSaveState(const char *target, int slot) const;
@@ -173,7 +196,7 @@ bool NeverhoodMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
(f == kSavesSupportPlayTime);
@@ -194,6 +217,13 @@ bool NeverhoodMetaEngine::createInstance(OSystem *syst, Engine **engine, const A
return gd != 0;
}
+const ExtraGuiOptions NeverhoodMetaEngine::getExtraGuiOptions(const Common::String &target) const {
+ ExtraGuiOptions options;
+ options.push_back(neverhoodExtraGuiOption1);
+ options.push_back(neverhoodExtraGuiOption2);
+ return options;
+}
+
SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Neverhood::NeverhoodEngine::SaveHeader header;
diff --git a/engines/neverhood/diskplayerscene.cpp b/engines/neverhood/diskplayerscene.cpp
index d972943759..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;
@@ -354,16 +354,14 @@ DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int
insertPuzzleMouse(0x000408A8, 20, 620);
showMouse(false);
- _diskSmackerPlayer = new SmackerPlayer(_vm, this, 0x08288103, false, true);
- addEntity(_diskSmackerPlayer);
- addSurface(_diskSmackerPlayer->getSurface());
+ _diskSmackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08288103, false, true));
_diskSmackerPlayer->setDrawPos(154, 86);
_vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
_palette->usePalette();
- SetMessageHandler(&DiskplayerScene::handleMessage);
- SetUpdateHandler(&DiskplayerScene::update);
+ SetMessageHandler(&DiskplayerScene::handleMessage);
+ SetUpdateHandler(&DiskplayerScene::update);
_appearCountdown = 6;
}
@@ -419,7 +417,7 @@ void DiskplayerScene::update() {
}
_diskIndex++;
while (!_diskAvailable[_diskIndex] && _diskIndex < 19)
- _diskIndex++;
+ _diskIndex++;
if (_diskIndex < 20) {
_appearCountdown = 1;
} else {
@@ -450,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();
@@ -464,45 +462,43 @@ uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam &param,
break;
case 0x2000:
tuneIn();
- break;
+ break;
case 0x2001:
stop();
- break;
+ break;
}
}
return 0;
}
-void DiskplayerScene::stop() {
- _diskSmackerPlayer->open(0x08288103, true);
+void DiskplayerScene::openSmacker(uint32 fileHash, bool keepLastFrame) {
+ _diskSmackerPlayer->open(fileHash, keepLastFrame);
_vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
_palette->usePalette();
+}
+
+void DiskplayerScene::stop() {
+ openSmacker(0x08288103, true);
_ssPlayButton->release();
_updateStatus = kUSStopped;
_diskSlots[_diskIndex]->activate();
}
void DiskplayerScene::tuneIn() {
- _diskSmackerPlayer->open(0x900001C1, false);
- _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
- _palette->usePalette();
+ openSmacker(0x900001C1, false);
_ssPlayButton->release();
_updateStatus = kUSTuningIn;
_diskSlots[_diskIndex]->activate();
}
void DiskplayerScene::playDisk() {
- _diskSmackerPlayer->open(kDiskplayerSmackerFileHashes[_diskIndex], false);
- _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
- _palette->usePalette();
+ openSmacker(kDiskplayerSmackerFileHashes[_diskIndex], false);
_updateStatus = kUSPlaying;
_diskSlots[_diskIndex]->play();
}
void DiskplayerScene::playStatic() {
- _diskSmackerPlayer->open(0x90000101, false);
- _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
- _palette->usePalette();
+ openSmacker(0x90000101, false);
_ssPlayButton->release();
_updateStatus = kUSPlaying;
_diskSlots[_diskIndex]->activate();
diff --git a/engines/neverhood/diskplayerscene.h b/engines/neverhood/diskplayerscene.h
index f3fd9ea874..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 {
@@ -99,6 +99,7 @@ protected:
bool _dropKey;
void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void openSmacker(uint32 fileHash, bool keepLastFrame);
void stop();
void tuneIn();
void playDisk();
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 fb8941ae43..5c29bf8a4f 100644
--- a/engines/neverhood/entity.h
+++ b/engines/neverhood/entity.h
@@ -60,14 +60,18 @@ protected:
// TODO: Disable heavy debug stuff in release mode
#define SetUpdateHandler(handler) \
- _updateHandlerCb = static_cast <void (Entity::*)(void)> (handler); \
- debug(5, "SetUpdateHandler(" #handler ")"); \
- _updateHandlerCbName = #handler
+ do { \
+ _updateHandlerCb = static_cast <void (Entity::*)(void)> (handler); \
+ debug(5, "SetUpdateHandler(" #handler ")"); \
+ _updateHandlerCbName = #handler; \
+ } while (0)
#define SetMessageHandler(handler) \
- _messageHandlerCb = static_cast <uint32 (Entity::*)(int messageNum, const MessageParam &param, Entity *sender)> (handler); \
- debug(5, "SetMessageHandler(" #handler ")"); \
- _messageHandlerCbName = #handler
+ do { \
+ _messageHandlerCb = static_cast <uint32 (Entity::*)(int messageNum, const MessageParam &param, Entity *sender)> (handler); \
+ debug(5, "SetMessageHandler(" #handler ")"); \
+ _messageHandlerCbName = #handler; \
+ } while (0)
const uint kMaxSoundResources = 16;
@@ -94,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 49682b0d29..699df2ae7d 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++)
@@ -194,21 +194,6 @@ void GameModule::initMemoryPuzzle() {
tileSymbolIndex = 0;
}
setSubVar(VA_IS_PUZZLE_INIT, 0xC8606803, 1);
-
- // DEBUG Enable to autosolve all tiles and leave only two matching tiles open
-#if 0
- for (int i = 0; i < 48; i++)
- setSubVar(VA_IS_TILE_MATCH, i, 1);
- int debugIndex = 0;
- setSubVar(VA_IS_TILE_MATCH, debugIndex, 0);
- for (int i = 0; i < 48; i++) {
- if (i != debugIndex && getSubVar(VA_TILE_SYMBOLS, i) == getSubVar(VA_TILE_SYMBOLS, debugIndex)) {
- setSubVar(VA_IS_TILE_MATCH, i, 0);
- break;
- }
- }
-#endif
-
}
}
@@ -231,7 +216,7 @@ void GameModule::initRadioPuzzle() {
setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 1);
setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 0);
setSubVar(VA_IS_PUZZLE_INIT, 0x08C80800, 1);
- }
+ }
}
void GameModule::initTestTubes1Puzzle() {
@@ -335,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;
}
@@ -426,6 +411,10 @@ void GameModule::checkRequests() {
}
if (_restoreGameRequested) {
_restoreGameRequested = false;
+ _vm->_audioResourceMan->stopAllMusic();
+ _vm->_audioResourceMan->stopAllSounds();
+ _vm->_soundMan->stopAllMusic();
+ _vm->_soundMan->stopAllSounds();
delete _childObject;
delete _prevChildObject;
_childObject = NULL;
@@ -438,8 +427,11 @@ void GameModule::checkRequests() {
}
void GameModule::createModule(int moduleNum, int which) {
- debug("GameModule::createModule(%d, %d)", moduleNum, which);
+ debug(1, "GameModule::createModule(%d, %d)", moduleNum, which);
_moduleNum = moduleNum;
+
+ delete _childObject;
+
switch (_moduleNum) {
case 1000:
setGlobalVar(V_MODULE_NAME, 0x03294419);
@@ -539,7 +531,7 @@ void GameModule::createModule(int moduleNum, int which) {
}
void GameModule::createModuleByHash(uint32 nameHash) {
- debug("GameModule::createModuleByHash(%08X)", nameHash);
+ debug(1, "GameModule::createModuleByHash(%08X)", nameHash);
switch (nameHash) {
case 0x03294419:
createModule(1000, -1);
@@ -684,7 +676,7 @@ void GameModule::updateModule() {
createModule(2300, 1);
break;
case 2300:
- debug("module 23000 _moduleResult : %d", _moduleResult);
+ debug(1, "module 23000 _moduleResult : %d", _moduleResult);
if (_moduleResult == 2)
createModule(1200, 0);
else if (_moduleResult == 0)
@@ -796,6 +788,7 @@ void GameModule::openMainMenu() {
createModule(1000, 0);
}
_vm->_screen->saveParams();
+ _vm->_screen->update();
_mainMenuRequested = false;
createMenuModule();
}
diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h
index 8101d38009..2f2fecf463 100644
--- a/engines/neverhood/gamemodule.h
+++ b/engines/neverhood/gamemodule.h
@@ -49,12 +49,16 @@ public:
void initWaterPipesPuzzle();
void initRadioPuzzle();
void initTestTubes1Puzzle();
- void initTestTubes2Puzzle();
+ void initTestTubes2Puzzle();
void initCannonSymbolsPuzzle();
void initCodeSymbolsPuzzle();
void initCubeSymbolsPuzzle();
void initCrystalColorsPuzzle();
uint32 getCurrRadioMusicFileHash();
+ int getCurrentModuleNum() { return _moduleNum; }
+ int getPreviousModuleNum() { return _moduleNum; }
+
+ void createModule(int moduleNum, int which);
protected:
int _moduleNum;
Entity *_prevChildObject;
@@ -64,7 +68,6 @@ protected:
bool _canRequestMainMenu;
bool _mainMenuRequested;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void createModule(int moduleNum, int which);
void createModuleByHash(uint32 nameHash);
void updateModule();
void openMainMenu();
diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp
index 87f5fe6dd9..9c080fea24 100644
--- a/engines/neverhood/gamevars.cpp
+++ b/engines/neverhood/gamevars.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "neverhood/console.h"
#include "neverhood/gamevars.h"
namespace Neverhood {
@@ -74,7 +75,7 @@ uint32 GameVars::getSubVar(uint32 nameHash, uint32 subNameHash) {
int16 subVarIndex = findSubVarIndex(varIndex, subNameHash);
if (subVarIndex != -1)
value = _vars[subVarIndex].value;
- }
+ }
return value;
}
@@ -123,10 +124,10 @@ int16 GameVars::getSubVarIndex(int16 varIndex, uint32 subNameHash) {
return subVarIndex;
}
-void GameVars::dumpVars() {
+void GameVars::dumpVars(Console *con) {
for (Common::Array<GameVar>::iterator it = _vars.begin(); it != _vars.end(); ++it) {
GameVar gameVar = *it;
- debug("%08X %08X %3d %3d", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex);
+ con->DebugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex);
}
}
diff --git a/engines/neverhood/gamevars.h b/engines/neverhood/gamevars.h
index 5337c13394..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 {
@@ -169,6 +169,8 @@ struct GameVar {
int16 firstIndex, nextIndex;
};
+class Console;
+
class GameVars {
public:
GameVars();
@@ -179,7 +181,7 @@ public:
void setGlobalVar(uint32 nameHash, uint32 value);
uint32 getSubVar(uint32 nameHash, uint32 subNameHash);
void setSubVar(uint32 nameHash, uint32 subNameHash, uint32 value);
- void dumpVars();
+ void dumpVars(Console *con);
protected:
Common::Array<GameVar> _vars;
int16 addVar(uint32 nameHash, uint32 value);
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index 5099c7a00e..490959020f 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -26,10 +26,10 @@
namespace Neverhood {
-BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height)
+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) {
-
+ _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;
@@ -130,7 +130,7 @@ void BaseSurface::copyFrom(Graphics::Surface *sourceSurface, int16 x, int16 y, N
// ShadowSurface
ShadowSurface::ShadowSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, BaseSurface *shadowSurface)
- : BaseSurface(vm, priority, width, height), _shadowSurface(shadowSurface) {
+ : BaseSurface(vm, priority, width, height, "shadow"), _shadowSurface(shadowSurface) {
// Empty
}
@@ -143,18 +143,18 @@ void ShadowSurface::draw() {
// FontSurface
FontSurface::FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight)
- : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows), _charsPerRow(charsPerRow), _numRows(numRows),
+ : 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;
}
FontSurface::FontSurface(NeverhoodEngine *vm, uint32 fileHash, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight)
- : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows), _charsPerRow(charsPerRow), _numRows(numRows),
+ : 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;
@@ -343,7 +343,7 @@ void unpackSpriteNormal(const byte *source, int width, int height, byte *dest, i
int calcDistance(int16 x1, int16 y1, int16 x2, int16 y2) {
const int16 deltaX = ABS(x1 - x2);
const int16 deltaY = ABS(y1 - y2);
- return sqrt((double)(deltaX * deltaX + deltaY * deltaY));
+ return (int)sqrt((double)(deltaX * deltaX + deltaY * deltaY));
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/graphics.h b/engines/neverhood/graphics.h
index a0ac1f09d5..b80bd60729 100644
--- a/engines/neverhood/graphics.h
+++ b/engines/neverhood/graphics.h
@@ -43,9 +43,11 @@ struct NDimensions {
struct NRect {
int16 x1, y1, x2, y2;
- NRect() : x1(0), y1(0), x2(0), y2(0) {}
-
- NRect(int16 x01, int16 y01, int16 x02, int16 y02) : x1(x01), y1(y01), x2(x02), y2(y02) {}
+ static NRect make(int16 x01, int16 y01, int16 x02, int16 y02) {
+ NRect r;
+ r.set(x01, y01, x02, y02);
+ return r;
+ }
void set(int16 x01, int16 y01, int16 x02, int16 y02) {
x1 = x01;
@@ -62,12 +64,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;
@@ -83,7 +85,7 @@ class MouseCursorResource;
class BaseSurface {
public:
- BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height);
+ BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, Common::String name);
virtual ~BaseSurface();
virtual void draw();
void clear();
@@ -104,10 +106,12 @@ public:
void setVisible(bool value) { _visible = value; }
void setTransparent(bool value) { _transparent = value; }
Graphics::Surface *getSurface() { return _surface; }
+ const Common::String getName() const { return _name; }
protected:
NeverhoodEngine *_vm;
int _priority;
bool _visible;
+ Common::String _name;
Graphics::Surface *_surface;
NDrawRect _drawRect;
NDrawRect _sysRect;
diff --git a/engines/neverhood/klaymen.cpp b/engines/neverhood/klaymen.cpp
index 06d606e18d..e1a0d72d50 100644
--- a/engines/neverhood/klaymen.cpp
+++ b/engines/neverhood/klaymen.cpp
@@ -33,31 +33,20 @@ 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},
- {1, kIdleChest},
- {1, kIdleHeadOff},
};
-static const KlaymenIdleTableItem klaymenIdleTable1002[] = {
- {1, kIdlePickEar},
- {2, kIdleWonderAbout}
-};
-
// Klaymen
Klaymen::Klaymen(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRectArray *clipRects)
@@ -65,8 +54,8 @@ Klaymen::Klaymen(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRec
_isWalkingOpenDoorNotified(false), _spitOutCountdown(0), _tapesToInsert(0), _keysToInsert(0), _busyStatus(0), _acceptInput(true),
_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) {
-
+ _idleTableNum(0), _otherSprite(NULL), _moveObjectCountdown(0), _walkResumeFrameIncr(0) {
+
createSurface(1000, 320, 200);
_x = x;
_y = y;
@@ -311,7 +300,7 @@ void Klaymen::stSitIdleTeleporterBlink() {
void Klaymen::stSitIdleTeleporterBlinkSecond() {
_busyStatus = 0;
_acceptInput = true;
- startAnimation(0x5C24C018, 0, -1);
+ startAnimation(0x582EC138, 0, -1);
SetUpdateHandler(&Klaymen::upSitIdleTeleporter);
SetMessageHandler(&Klaymen::hmLowLevel);
SetSpriteUpdate(NULL);
@@ -434,7 +423,7 @@ void Klaymen::stopWalking() {
}
void Klaymen::startIdleAnimation(uint32 fileHash, AnimationCb callback) {
- debug("startIdleAnimation(%08X)", fileHash);
+ debug(1, "startIdleAnimation(%08X)", fileHash);
NextState(callback);
SetUpdateHandler(&Klaymen::upIdleAnimation);
}
@@ -447,7 +436,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);
@@ -628,36 +617,6 @@ void Klaymen::startWalkToX(int16 x, bool walkExt) {
}
}
-void Klaymen::stWakeUp() {
- _busyStatus = 1;
- _acceptInput = false;
- startAnimation(0x527AC970, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmLowLevelAnimation);
- SetSpriteUpdate(NULL);
-}
-
-void Klaymen::stSleeping() {
- _busyStatus = 0;
- _acceptInput = true;
- startAnimation(0x5A38C110, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmSleeping);
- SetSpriteUpdate(NULL);
-}
-
-uint32 Klaymen::hmSleeping(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevel(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x03060012) {
- playSound(0, 0xC0238244);
- }
- break;
- }
- return messageResult;
-}
-
bool Klaymen::stStartAction(AnimationCb callback3) {
if (_busyStatus == 1) {
_busyStatus = 2;
@@ -684,35 +643,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 +679,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 +708,7 @@ void Klaymen::suSneaking() {
}
updateBounds();
}
-
+
}
void Klaymen::stSneak() {
@@ -761,7 +720,7 @@ void Klaymen::stSneak() {
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmSneaking);
SetSpriteUpdate(&Klaymen::suSneaking);
- FinalizeState(&Klaymen::evSneakingDone);
+ FinalizeState(&Klaymen::evSneakingDone);
}
void Klaymen::evSneakingDone() {
@@ -801,7 +760,7 @@ void Klaymen::stStartWalking() {
SetMessageHandler(&Klaymen::hmStartWalking);
SetSpriteUpdate(&Klaymen::suWalkingTestExit);
NextState(&Klaymen::stWalkingFirst);
- FinalizeState(&Klaymen::evStartWalkingDone);
+ FinalizeState(&Klaymen::evStartWalkingDone);
}
}
@@ -832,7 +791,7 @@ void Klaymen::stWalkingFirst() {
SetMessageHandler(&Klaymen::hmWalking);
SetSpriteUpdate(&Klaymen::suWalkingFirst);
NextState(&Klaymen::stUpdateWalkingFirst);
- FinalizeState(&Klaymen::evStartWalkingDone);
+ FinalizeState(&Klaymen::evStartWalkingDone);
}
void Klaymen::suWalkingFirst() {
@@ -882,20 +841,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 +887,7 @@ void Klaymen::suWalkingTestExit() {
}
updateBounds();
}
-
+
}
uint32 Klaymen::hmLever(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1363,7 +1322,7 @@ void Klaymen::stLargeStep() {
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmLargeStep);
SetSpriteUpdate(&Klaymen::suLargeStep);
- FinalizeState(&Klaymen::evLargeStepDone);
+ FinalizeState(&Klaymen::evLargeStepDone);
}
void Klaymen::evLargeStepDone() {
@@ -1372,11 +1331,11 @@ void Klaymen::evLargeStepDone() {
void Klaymen::suLargeStep() {
int16 xdiff = _destX - _x;
-
+
if (_doDeltaX) {
_deltaX = -_deltaX;
}
-
+
if (_currFrameIndex == 7) {
_deltaX = xdiff;
}
@@ -1385,7 +1344,7 @@ void Klaymen::suLargeStep() {
xdiff = _deltaX;
_deltaX = 0;
-
+
if (_x != _destX) {
HitRect *hitRectPrev = _parentScene->findHitRectAtPos(_x, _y);
_x += xdiff;
@@ -1420,7 +1379,7 @@ uint32 Klaymen::hmLargeStep(int messageNum, const MessageParam &param, Entity *s
case 0x3002:
_x = _destX;
gotoNextStateExt();
- break;
+ break;
}
return messageResult;
}
@@ -1512,112 +1471,11 @@ uint32 Klaymen::hmPeekWall(int messageNum, const MessageParam &param, Entity *se
return hmLowLevelAnimation(messageNum, param, sender);
}
-void Klaymen::stJumpToRing1() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpToRing1))) {
- _busyStatus = 0;
- startAnimation(0xD82890BA, 0, -1);
- setupJumpToRing();
- }
-}
-
-void Klaymen::setupJumpToRing() {
- _acceptInput = false;
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmJumpToRing);
- SetSpriteUpdate(&Klaymen::suUpdateDestX);
- NextState(&Klaymen::stHangOnRing);
- sendMessage(_attachedSprite, 0x482B, 0);
-}
-
-uint32 Klaymen::hmJumpToRing(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x168050A0) {
- sendMessage(_attachedSprite, 0x4806, 0);
- _acceptInput = true;
- } else if (param.asInteger() == 0x320AC306) {
- playSound(0, 0x5860C640);
- } else if (param.asInteger() == 0x4AB28209) {
- sendMessage(_attachedSprite, 0x482A, 0);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_attachedSprite, 0x482B, 0);
- }
- break;
- }
- return messageResult;
-}
-
void Klaymen::suUpdateDestX() {
AnimatedSprite::updateDeltaXY();
_destX = _x;
}
-void Klaymen::stHangOnRing() {
- _busyStatus = 0;
- _acceptInput = true;
- startAnimation(0x4829E0B8, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmLowLevel);
- SetSpriteUpdate(NULL);
-}
-
-void Klaymen::stJumpToRing2() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpToRing2))) {
- _busyStatus = 0;
- startAnimation(0x900980B2, 0, -1);
- setupJumpToRing();
- }
-}
-
-void Klaymen::stJumpToRing3() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpToRing3))) {
- _busyStatus = 0;
- _acceptInput = false;
- startAnimation(0xBA1910B2, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetSpriteUpdate(&Klaymen::suUpdateDestX);
- SetMessageHandler(&Klaymen::hmJumpToRing3);
- NextState(&Klaymen::stHoldRing3);
- sendMessage(_attachedSprite, 0x482B, 0);
- }
-}
-
-uint32 Klaymen::hmJumpToRing3(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x168050A0) {
- sendMessage(_attachedSprite, 0x4806, 0);
- } else if (param.asInteger() == 0x320AC306) {
- playSound(0, 0x5860C640);
- } else if (param.asInteger() == 0x4AB28209) {
- sendMessage(_attachedSprite, 0x482A, 0);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_attachedSprite, 0x482B, 0);
- }
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stHoldRing3() {
- _busyStatus = 0;
- _acceptInput = true;
- startAnimation(0x4A293FB0, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmHoldRing3);
- SetSpriteUpdate(NULL);
-}
-
-uint32 Klaymen::hmHoldRing3(int messageNum, const MessageParam &param, Entity *sender) {
- if (messageNum == 0x1008) {
- stReleaseRing();
- return 0;
- }
- return hmLowLevel(messageNum, param, sender);
-}
-
void Klaymen::stReleaseRing() {
_busyStatus = 1;
_acceptInput = false;
@@ -1629,14 +1487,6 @@ void Klaymen::stReleaseRing() {
SetSpriteUpdate(NULL);
}
-void Klaymen::stJumpToRing4() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpToRing4))) {
- _busyStatus = 0;
- startAnimation(0xB8699832, 0, -1);
- setupJumpToRing();
- }
-}
-
void Klaymen::startWalkToAttachedSpriteXDistance(int16 distance) {
startWalkToXDistance(_attachedSprite->getX(), distance);
}
@@ -1681,7 +1531,7 @@ void Klaymen::stStartClimbLadderDown() {
_ladderStatus = 2;
_acceptInput = true;
startAnimation(0x122D1505, 29 - _currFrameIndex, -1);
- }
+ }
}
}
@@ -1885,29 +1735,6 @@ uint32 Klaymen::hmTurnToBackToUse(int messageNum, const MessageParam &param, Ent
return messageResult;
}
-void Klaymen::stClayDoorOpen() {
- if (!stStartAction(AnimationCallback(&Klaymen::stClayDoorOpen))) {
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0x5CCCB330, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmClayDoorOpen);
- SetSpriteUpdate(&Klaymen::suUpdateDestX);
- }
-}
-
-uint32 Klaymen::hmClayDoorOpen(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x040D4186) {
- sendMessage(_attachedSprite, 0x4808, 0);
- }
- break;
- }
- return messageResult;
-}
-
void Klaymen::stTurnToUse() {
if (!stStartAction(AnimationCallback(&Klaymen::stTurnToUse))) {
_busyStatus = 2;
@@ -1979,7 +1806,7 @@ uint32 Klaymen::hmMoveObjectTurn(int messageNum, const MessageParam &param, Enti
break;
case 0x480A:
_isMoveObjectRequested = true;
- return 0;
+ return 0;
}
return hmLowLevelAnimation(messageNum, param, sender);
}
@@ -2336,29 +2163,6 @@ uint32 Klaymen::hmTeleporterAppearDisappear(int messageNum, const MessageParam &
return messageResult;
}
-uint32 Klaymen::hmShrink(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x80C110B5)
- sendMessage(_parentScene, 0x482A, 0);
- else if (param.asInteger() == 0x33288344)
- playSound(2, 0x10688664);
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stShrink() {
- _busyStatus = 0;
- _acceptInput = false;
- playSound(0, 0x4C69EA53);
- startAnimation(0x1AE88904, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmShrink);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
-}
-
void Klaymen::stStandWonderAbout() {
if (_x > 260)
setDoDeltaX(1);
@@ -2521,7 +2325,7 @@ void Klaymen::stInsertKey() {
more = true;
} while (more);
_keysToInsert++;
- }
+ }
}
if (_keysToInsert == 0) {
GotoState(NULL);
@@ -2537,61 +2341,6 @@ void Klaymen::stInsertKey() {
}
}
-uint32 Klaymen::hmReadNote(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x04684052) {
- _acceptInput = true;
- sendMessage(_parentScene, 0x2002, 0);
- }
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stReadNote() {
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0x123E9C9F, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmReadNote);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
-}
-
-uint32 Klaymen::hmHitByDoor(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- int16 speedUpFrameIndex;
- switch (messageNum) {
- case 0x1008:
- speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
- if (_currFrameIndex < speedUpFrameIndex) {
- startAnimation(0x35AA8059, speedUpFrameIndex, -1);
- _y = 438;
- }
- messageResult = 0;
- break;
- case 0x100D:
- if (param.asInteger() == 0x1A1A0785) {
- playSound(0, 0x40F0A342);
- } else if (param.asInteger() == 0x60428026) {
- playSound(0, 0x40608A59);
- }
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stHitByDoor() {
- _busyStatus = 1;
- _acceptInput = false;
- startAnimation(0x35AA8059, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmHitByDoor);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- playSound(0, 0x402E82D4);
-}
-
uint32 Klaymen::hmPeekWallReturn(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
switch (messageNum) {
@@ -2657,65 +2406,6 @@ void Klaymen::stPeekWallReturn() {
SetSpriteUpdate(NULL);
}
-void Klaymen::stPullHammerLever() {
- if (!stStartAction(AnimationCallback(&Klaymen::stPullHammerLever))) {
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0x00648953, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmPullHammerLever);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- }
-}
-
-uint32 Klaymen::hmPullHammerLever(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Klaymen::hmLever(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x4AB28209)
- sendMessage(_attachedSprite, 0x480F, 0);
- break;
- }
- return messageResult;
-}
-
-void Klaymen::suRidePlatformDown() {
- _platformDeltaY++;
- _y += _platformDeltaY;
- if (_y > 600)
- sendMessage(this, 0x1019, 0);
-}
-
-void Klaymen::stRidePlatformDown() {
- if (!stStartActionFromIdle(AnimationCallback(&Klaymen::stRidePlatformDown))) {
- _busyStatus = 1;
- sendMessage(_parentScene, 0x4803, 0);
- _acceptInput = false;
- _platformDeltaY = 0;
- startAnimation(0x5420E254, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmLowLevel);
- SetSpriteUpdate(&Klaymen::suRidePlatformDown);
- _vm->_soundMan->playSoundLooping(0xD3B02847);
- }
-}
-
-void Klaymen::stCrashDown() {
- playSound(0, 0x41648271);
- _busyStatus = 1;
- _acceptInput = false;
- startAnimationByHash(0x000BAB02, 0x88003000, 0);
- SetUpdateHandler(&Klaymen::update);
- SetSpriteUpdate(NULL);
- SetMessageHandler(&Klaymen::hmLowLevelAnimation);
- NextState(&Klaymen::stCrashDownFinished);
-}
-
-void Klaymen::stCrashDownFinished() {
- setDoDeltaX(2);
- stTryStandIdle();
-}
-
void Klaymen::upSpitOutFall() {
Klaymen::update();
if (_spitOutCountdown != 0 && (--_spitOutCountdown == 0)) {
@@ -2724,24 +2414,6 @@ void Klaymen::upSpitOutFall() {
}
}
-uint32 Klaymen::hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x168050A0) {
- sendMessage(_attachedSprite, 0x480F, 0);
- } else if (param.asInteger() == 0x586B0300) {
- sendMessage(_otherSprite, 0x480E, 1);
- } else if (param.asInteger() == 0x4AB28209) {
- sendMessage(_attachedSprite, 0x482A, 0);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_attachedSprite, 0x482B, 0);
- }
- break;
- }
- return messageResult;
-}
-
uint32 Klaymen::hmStandIdleSpecial(int messageNum, const MessageParam &param, Entity *sender) {
switch (messageNum) {
case 0x4811:
@@ -2766,106 +2438,6 @@ uint32 Klaymen::hmStandIdleSpecial(int messageNum, const MessageParam &param, En
return 0;
}
-uint32 Klaymen::hmPressDoorButton(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x942D2081) {
- _acceptInput = false;
- sendMessage(_attachedSprite, 0x2003, 0);
- } else if (param.asInteger() == 0xDA600012) {
- stHitByBoxingGlove();
- } else if (param.asInteger() == 0x0D01B294) {
- _acceptInput = false;
- sendMessage(_attachedSprite, 0x480B, 0);
- }
- break;
- }
- return messageResult;
-}
-
-uint32 Klaymen::hmMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x01084280) {
- sendMessage(_attachedSprite, 0x480B, (uint32)_doDeltaX);
- } else if (param.asInteger() == 0x02421405) {
- if (_isMoveObjectRequested) {
- if (sendMessage(_attachedSprite, 0x480C, (uint32)_doDeltaX) != 0)
- stContinueMovingVenusFlyTrap();
- } else {
- SetMessageHandler(&Klaymen::hmFirstMoveVenusFlyTrap);
- }
- } else if (param.asInteger() == 0x4AB28209) {
- sendMessage(_attachedSprite, 0x482A, 0);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_attachedSprite, 0x482B, 0);
- } else if (param.asInteger() == 0x32180101) {
- playSound(0, 0x405002D8);
- } else if (param.asInteger() == 0x0A2A9098) {
- playSound(0, 0x0460E2FA);
- }
- break;
- case 0x480A:
- _isMoveObjectRequested = true;
- return 0;
- }
- return hmLowLevelAnimation(messageNum, param, sender);
-}
-
-uint32 Klaymen::hmFirstMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x4AB28209) {
- sendMessage(_attachedSprite, 0x482A, 0);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_attachedSprite, 0x482B, 0);
- } else if (param.asInteger() == 0x32180101) {
- playSound(0, 0x405002D8);
- } else if (param.asInteger() == 0x0A2A9098) {
- playSound(0, 0x0460E2FA);
- }
- break;
- }
- return messageResult;
-}
-
-uint32 Klaymen::hmHitByBoxingGlove(int messageNum, const MessageParam &param, Entity *sender) {
- int16 speedUpFrameIndex;
- uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x1008:
- speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
- if (_currFrameIndex < speedUpFrameIndex) {
- startAnimation(0x35AA8059, speedUpFrameIndex, -1);
- _y = 435;
- }
- messageResult = 0;
- break;
- case 0x100D:
- if (param.asInteger() == 0x1A1A0785) {
- playSound(0, 0x40F0A342);
- } else if (param.asInteger() == 0x60428026) {
- playSound(0, 0x40608A59);
- }
- break;
- }
- return messageResult;
-}
-
-uint32 Klaymen::hmJumpAndFall(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmLowLevel(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x1307050A) {
- playSound(0, 0x40428A09);
- }
- break;
- }
- return messageResult;
-}
-
void Klaymen::suFallDown() {
AnimatedSprite::updateDeltaXY();
HitRect *hitRect = _parentScene->findHitRectAtPos(_x, _y + 10);
@@ -2877,19 +2449,6 @@ void Klaymen::suFallDown() {
_parentScene->checkCollision(this, 0xFFFF, 0x4810, 0);
}
-void Klaymen::stJumpToRingVenusFlyTrap() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpToRingVenusFlyTrap))) {
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0x584984B4, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmJumpToRingVenusFlyTrap);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- NextState(&Klaymen::stLandOnFeet);
- sendMessage(_attachedSprite, 0x482B, 0);
- }
-}
-
void Klaymen::stStandIdleSpecial() {
playSound(0, 0x56548280);
_busyStatus = 0;
@@ -2946,86 +2505,6 @@ void Klaymen::stFallTouchdown() {
stTryStandIdle();
}
-void Klaymen::stJumpAndFall() {
- if (!stStartAction(AnimationCallback(&Klaymen::stJumpAndFall))) {
- sendMessage(_parentScene, 0x1024, 3);
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0xB93AB151, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmJumpAndFall);
- SetSpriteUpdate(&Klaymen::suFallDown);
- NextState(&Klaymen::stLandOnFeet);
- }
-}
-
-void Klaymen::stDropFromRing() {
- if (_attachedSprite) {
- _x = _attachedSprite->getX();
- sendMessage(_attachedSprite, 0x4807, 0);
- _attachedSprite = NULL;
- }
- _busyStatus = 2;
- _acceptInput = false;
- startAnimation(0x586984B1, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmLowLevel);
- SetSpriteUpdate(&Klaymen::suFallDown);
- NextState(&Klaymen::stLandOnFeet);
-}
-
-void Klaymen::stPressDoorButton() {
- _busyStatus = 2;
- _acceptInput = true;
- setDoDeltaX(0);
- startAnimation(0x1CD89029, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmPressDoorButton);
- SetSpriteUpdate(&Klaymen::suAction);
-}
-
-void Klaymen::stHitByBoxingGlove() {
- _busyStatus = 1;
- _acceptInput = false;
- startAnimation(0x35AA8059, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmHitByBoxingGlove);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- FinalizeState(&Klaymen::evHitByBoxingGloveDone);
-}
-
-void Klaymen::evHitByBoxingGloveDone() {
- sendMessage(_parentScene, 0x1024, 1);
-}
-
-void Klaymen::stMoveVenusFlyTrap() {
- if (!stStartAction(AnimationCallback(&Klaymen::stMoveVenusFlyTrap))) {
- _busyStatus = 2;
- _isMoveObjectRequested = false;
- _acceptInput = true;
- setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
- startAnimation(0x5C01A870, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmMoveVenusFlyTrap);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- FinalizeState(&Klaymen::evMoveVenusFlyTrapDone);
- }
-}
-
-void Klaymen::stContinueMovingVenusFlyTrap() {
- _isMoveObjectRequested = false;
- _acceptInput = true;
- startAnimationByHash(0x5C01A870, 0x01084280, 0);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmMoveVenusFlyTrap);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- FinalizeState(&Klaymen::evMoveVenusFlyTrapDone);
-}
-
-void Klaymen::evMoveVenusFlyTrapDone() {
- sendMessage(_attachedSprite, 0x482A, 0);
-}
-
void Klaymen::suFallSkipJump() {
updateDeltaXY();
HitRect *hitRect = _parentScene->findHitRectAtPos(_x, _y + 10);
@@ -3049,50 +2528,7 @@ void Klaymen::stFallSkipJump() {
void Klaymen::upMoveObject() {
if (_x >= 380)
gotoNextStateExt();
- Klaymen::update();
-}
-
-uint32 Klaymen::hmMatch(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x51281850) {
- setGlobalVar(V_TNT_DUMMY_FUSE_LIT, 1);
- } else if (param.asInteger() == 0x43000538) {
- playSound(0, 0x21043059);
- } else if (param.asInteger() == 0x02B20220) {
- playSound(0, 0xC5408620);
- } else if (param.asInteger() == 0x0A720138) {
- playSound(0, 0xD4C08010);
- } else if (param.asInteger() == 0xB613A180) {
- playSound(0, 0x44051000);
- }
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stFetchMatch() {
- if (!stStartAction(AnimationCallback(&Klaymen::stFetchMatch))) {
- _busyStatus = 0;
- _acceptInput = false;
- setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
- startAnimation(0x9CAA0218, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmMatch);
- SetSpriteUpdate(NULL);
- NextState(&Klaymen::stLightMatch);
- }
-}
-
-void Klaymen::stLightMatch() {
- _busyStatus = 1;
- _acceptInput = false;
- setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
- startAnimation(0x1222A513, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmMatch);
- SetSpriteUpdate(NULL);
+ Klaymen::update();
}
uint32 Klaymen::hmMoveObject(int messageNum, const MessageParam &param, Entity *sender) {
@@ -3114,18 +2550,6 @@ uint32 Klaymen::hmMoveObject(int messageNum, const MessageParam &param, Entity *
return Klaymen::hmLowLevelAnimation(messageNum, param, sender);
}
-uint32 Klaymen::hmTumbleHeadless(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x000F0082) {
- playSound(0, 0x74E2810F);
- }
- break;
- }
- return messageResult;
-}
-
void Klaymen::stMoveObject() {
if (!stStartAction(AnimationCallback(&Klaymen::stMoveObject))) {
_busyStatus = 2;
@@ -3147,93 +2571,6 @@ void Klaymen::stContinueMoveObject() {
SetMessageHandler(&Klaymen::hmMoveObject);
}
-void Klaymen::stTumbleHeadless() {
- if (!stStartActionFromIdle(AnimationCallback(&Klaymen::stTumbleHeadless))) {
- _busyStatus = 1;
- _acceptInput = false;
- setDoDeltaX(0);
- startAnimation(0x2821C590, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmTumbleHeadless);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- NextState(&Klaymen::stTryStandIdle);
- sendMessage(_parentScene, 0x8000, 0);
- playSound(0, 0x62E0A356);
- }
-}
-
-void Klaymen::stCloseEyes() {
- if (!stStartActionFromIdle(AnimationCallback(&Klaymen::stCloseEyes))) {
- _busyStatus = 1;
- _acceptInput = false;
- startAnimation(0x5420E254, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmLowLevel);
- SetSpriteUpdate(NULL);
- }
-}
-
-uint32 Klaymen::hmSpit(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x16401CA6) {
- _canSpitPipe = true;
- if (_contSpitPipe)
- spitIntoPipe();
- } else if (param.asInteger() == 0xC11C0008) {
- _canSpitPipe = false;
- _acceptInput = false;
- _readyToSpit = false;
- } else if (param.asInteger() == 0x018A0001) {
- sendMessage(_parentScene, 0x2001, _spitDestPipeIndex);
- }
- break;
- }
- return messageResult;
-}
-
-void Klaymen::stTrySpitIntoPipe() {
- if (_readyToSpit) {
- _contSpitPipe = true;
- _spitContDestPipeIndex = _spitPipeIndex;
- if (_canSpitPipe)
- spitIntoPipe();
- } else if (!stStartAction(AnimationCallback(&Klaymen::stTrySpitIntoPipe))) {
- _busyStatus = 2;
- _acceptInput = true;
- _spitDestPipeIndex = _spitPipeIndex;
- _readyToSpit = true;
- _canSpitPipe = false;
- _contSpitPipe = false;
- startAnimation(0x1808B150, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmSpit);
- SetSpriteUpdate(NULL);
- }
-}
-
-void Klaymen::spitIntoPipe() {
- _contSpitPipe = false;
- _spitDestPipeIndex = _spitContDestPipeIndex;
- _canSpitPipe = false;
- _acceptInput = false;
- startAnimation(0x1B08B553, 0, -1);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmSpit);
- SetSpriteUpdate(NULL);
- NextState(&Klaymen::stContSpitIntoPipe);
-}
-
-void Klaymen::stContSpitIntoPipe() {
- _canSpitPipe = true;
- _acceptInput = true;
- startAnimationByHash(0x1808B150, 0x16401CA6, 0);
- SetUpdateHandler(&Klaymen::update);
- SetMessageHandler(&Klaymen::hmSpit);
- SetSpriteUpdate(NULL);
-}
-
void Klaymen::suRidePlatform() {
_x = _attachedSprite->getX() - 20;
_y = _attachedSprite->getY() + 46;
@@ -3344,2798 +2681,4 @@ void Klaymen::stPeekInsideBlink() {
_blinkCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
}
-// KmScene1001
-
-KmScene1001::KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-}
-
-uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stSleeping);
- break;
- case 0x480D:
- GotoState(&Klaymen::stPullHammerLever);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4836:
- if (param.asInteger() == 1) {
- sendMessage(_parentScene, 0x2002, 0);
- GotoState(&Klaymen::stWakeUp);
- }
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-// KmScene1002
-
-KmScene1002::KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- setKlaymenIdleTable1();
-}
-
-void KmScene1002::xUpdate() {
- if (_x >= 250 && _x <= 435 && _y >= 420) {
- if (_idleTableNum == 0) {
- setKlaymenIdleTable(klaymenIdleTable1002, ARRAYSIZE(klaymenIdleTable1002));
- _idleTableNum = 1;
- }
- } else if (_idleTableNum == 1) {
- setKlaymenIdleTable1();
- _idleTableNum = 0;
- }
-}
-
-uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x2001:
- GotoState(&Klaymen::stStandIdleSpecial);
- break;
- case 0x2007:
- _otherSprite = (Sprite*)param.asEntity();
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4803:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stJumpAndFall);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stDropFromRing);
- break;
- case 0x4804:
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4805:
- switch (param.asInteger()) {
- case 1:
- GotoState(&Klaymen::stJumpToRing1);
- break;
- case 2:
- GotoState(&Klaymen::stJumpToRing2);
- break;
- case 3:
- GotoState(&Klaymen::stJumpToRing3);
- break;
- case 4:
- GotoState(&Klaymen::stJumpToRing4);
- break;
- }
- break;
- case 0x480A:
- GotoState(&Klaymen::stMoveVenusFlyTrap);
- break;
- case 0x480D:
- GotoState(&Klaymen::stJumpToRingVenusFlyTrap);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressDoorButton);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- startWalkToAttachedSpriteXDistance(param.asInteger());
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2005, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2005, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2005, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2006, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-// KmScene1004
-
-KmScene1004::KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- _dataResource.load(0x01900A04);
-}
-
-uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReadNote);
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x4824:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = _dataResource.getPoint(param.asInteger()).y;
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4825:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = _dataResource.getPoint(param.asInteger()).y;
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4828:
- GotoState(&Klaymen::stTurnToBackToUse);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene1109::KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stWalkingFirst);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0x2C2A4A1C);
- break;
- case 0x483E:
- teleporterDisappear(0x3C2E4245);
- break;
- }
- return messageResult;
-}
-
-// KmScene1201
-
-KmScene1201::KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- setKlaymenIdleTable(klaymenIdleTable4, ARRAYSIZE(klaymenIdleTable4));
- _doYHitIncr = true;
-}
-
-uint32 KmScene1201::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- GotoState(&Klaymen::stMoveObject);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4813:
- GotoState(&Klaymen::stFetchMatch);
- break;
- case 0x4814:
- GotoState(&Klaymen::stTumbleHeadless);
- break;
- case 0x4815:
- GotoState(&Klaymen::stCloseEyes);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene1303::KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1303::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4804:
- GotoState(&Klaymen::stPeekWall1);
- break;
- case 0x483B:
- GotoState(&Klaymen::stPeekWallReturn);
- break;
- case 0x483C:
- GotoState(&Klaymen::stPeekWall2);
- break;
- }
- return 0;
-}
-
-KmScene1304::KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene1305::KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- GotoState(&Klaymen::stCrashDown);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- }
- return 0;
-}
-
-KmScene1306::KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- else
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- else
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0xEE084A04);
- break;
- case 0x483E:
- teleporterDisappear(0xB86A4274);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-KmScene1308::KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
- else
- GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
- case 0x480D:
- GotoState(&Klaymen::stUseLever);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stInsertKey);
- else
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x4827:
- GotoState(&Klaymen::stReleaseLever);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-// KmScene1401
-
-KmScene1401::KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
- else
- GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- }
- return 0;
-}
-
-// KmScene1402
-
-KmScene1402::KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- SetFilterY(&Sprite::defFilterY);
-}
-
-uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
- else
- GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- }
- return 0;
-}
-
-// KmScene1403
-
-KmScene1403::KmScene1403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- setKlaymenIdleTable(klaymenIdleTable4, ARRAYSIZE(klaymenIdleTable4));
-}
-
-uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
- else
- GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
- case 0x480D:
- GotoState(&Klaymen::stUseLever);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x4827:
- GotoState(&Klaymen::stReleaseLever);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-// KmScene1404
-
-KmScene1404::KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480A:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
- else
- GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene1608::KmScene1608(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2032:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2032, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2032, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-// KmScene1705
-
-KmScene1705::KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4803:
- GotoState(&Klaymen::stFallSkipJump);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- if (_isSittingInTeleporter) {
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- }
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0x5E0A4905);
- break;
- case 0x483E:
- teleporterDisappear(0xD86E4477);
- break;
- }
- return messageResult;
-}
-
-KmScene1901::KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2001::KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stWalkingFirst);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0xBE68CC54);
- break;
- case 0x483E:
- teleporterDisappear(0x18AB4ED4);
- break;
- }
- return messageResult;
-}
-
-KmScene2101::KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4811:
- GotoState(&Klaymen::stHitByDoor);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0xFF290E30);
- break;
- case 0x483E:
- teleporterDisappear(0x9A28CA1C);
- break;
- }
- return messageResult;
-}
-
-KmScene2201::KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount)
- : Klaymen(vm, parentScene, x, y) {
-
- _surface->setClipRects(clipRects, clipRectsCount);
- _dataResource.load(0x04104242);
-}
-
-uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x4819:
- GotoState(&Klaymen::stClayDoorOpen);
- break;
- case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2205::KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-void KmScene2205::xUpdate() {
- setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
-}
-
-uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stStartWalkingResume);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2206::KmScene2206(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- _walkResumeFrameIncr = 1;
- _vm->_soundMan->addSound(0x80101800, 0xD3B02847);
-}
-
-KmScene2206::~KmScene2206() {
- _vm->_soundMan->deleteSoundGroup(0x80101800);
-}
-
-void KmScene2206::xUpdate() {
- setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
-}
-
-uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4803:
- GotoState(&Klaymen::stRidePlatformDown);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stStartWalkingResume);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4812:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x4837:
- stopWalking();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2207::KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x2001:
- GotoState(&Klaymen::stRidePlatform);
- break;
- case 0x2005:
- suRidePlatform();
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480D:
- GotoState(&Klaymen::stInteractLever);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x4827:
- GotoState(&Klaymen::stReleaseLever);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
-KmScene2242::KmScene2242(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-void KmScene2242::xUpdate() {
- setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
-}
-
-uint32 KmScene2242::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stStartWalkingResume);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- return 0;
-}
-
-KmHallOfRecords::KmHallOfRecords(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
- // Empty
-}
-
-void KmHallOfRecords::xUpdate() {
- setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
-}
-
-uint32 KmHallOfRecords::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stStartWalkingResume);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- return 0;
-}
-
-KmScene2247::KmScene2247(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-void KmScene2247::xUpdate() {
- setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
-}
-
-uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stStartWalkingResume);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- 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) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x4832:
- GotoState(&Klaymen::stUseTube);
- break;
- case 0x4833:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAbout);
- else {
- _spitPipeIndex = sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stTrySpitIntoPipe);
- }
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-KmScene2402::KmScene2402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2402::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (!getGlobalVar(V_TV_JOKE_TOLD))
- GotoState(&Klaymen::stStandWonderAbout);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stWalkingFirst);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-KmScene2403::KmScene2403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x480D:
- GotoState(&Klaymen::stPullCord);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4816:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stPressButton);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stPressFloorButton);
- else
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- 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);
-}
-
-uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- if (param.asInteger() != 0) {
- _destX = param.asInteger();
- GotoState(&Klaymen::stWalkingFirst);
- } else
- GotoState(&Klaymen::stPeekWall);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- 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) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- }
- return messageResult;
-}
-
-KmScene2732::KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2732::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4804:
- GotoState(&Klaymen::stPeekInside);
- break;
- case 0x483C:
- GotoState(&Klaymen::stPeekInsideReturn);
- break;
- }
- return 0;
-}
-
-KmScene2801::KmScene2801(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- return 0;
-}
-
-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);
-}
-
-uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4803:
- _destY = param.asInteger();
- GotoState(&Klaymen::stJumpToGrab);
- break;
- case 0x4804:
- if (param.asInteger() == 3)
- GotoState(&Klaymen::stFinishGrow);
- break;
- case 0x480D:
- GotoState(&Klaymen::stPullCord);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else
- GotoState(&Klaymen::stWonderAboutHalf);
- break;
- case 0x482E:
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4838:
- GotoState(&Klaymen::stJumpToGrabRelease);
- break;
- }
- return 0;
-}
-
-KmScene2803Small::KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- _dataResource.load(0x81120132);
-}
-
-uint32 KmScene2803Small::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToXSmall(param.asPoint().x);
- break;
- case 0x4004:
- GotoState(&Klaymen::stStandIdleSmall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfterSmall);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalfSmall);
- else
- GotoState(&Klaymen::stWonderAboutSmall);
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStepSmall);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stWalkToFront2Small);
- else
- GotoState(&Klaymen::stWalkToFrontSmall);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToBackHalfSmall);
- else if (param.asInteger() == 2)
- GotoState(&Klaymen::stTurnToBackWalkSmall);
- else
- GotoState(&Klaymen::stTurnToBackSmall);
- break;
- case 0x4830:
- GotoState(&Klaymen::stShrink);
- break;
- }
- return 0;
-}
-
-KmScene2805::KmScene2805(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam &param) {
- uint32 messageResult = 0;
- switch (messageNum) {
- case 0x2000:
- _isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
- break;
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stSitIdleTeleporter);
- else
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481D:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stTurnToUseInTeleporter);
- break;
- case 0x481E:
- if (_isSittingInTeleporter)
- GotoState(&Klaymen::stReturnFromUseInTeleporter);
- break;
- case 0x4834:
- GotoState(&Klaymen::stStepOver);
- break;
- case 0x4835:
- sendMessage(_parentScene, 0x2000, 1);
- _isSittingInTeleporter = true;
- GotoState(&Klaymen::stSitInTeleporter);
- break;
- case 0x4836:
- sendMessage(_parentScene, 0x2000, 0);
- _isSittingInTeleporter = false;
- GotoState(&Klaymen::stGetUpFromTeleporter);
- break;
- case 0x483D:
- teleporterAppear(0xDE284B74);
- break;
- case 0x483E:
- teleporterDisappear(0xD82A4094);
- break;
- }
- return messageResult;
-}
-
-KmScene2806::KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
- bool needsLargeSurface, NRect *clipRects, uint clipRectsCount)
- : Klaymen(vm, parentScene, x, y) {
-
- if (needsLargeSurface) {
- NDimensions dimensions = _animResource.loadSpriteDimensions(0x2838C010);
- delete _surface;
- createSurface(1000, dimensions.width, dimensions.height);
- loadSound(3, 0x58E0C341);
- loadSound(4, 0x40A00342);
- loadSound(5, 0xD0A1C348);
- loadSound(6, 0x166FC6E0);
- loadSound(7, 0x00018040);
- }
-
- _dataResource.load(0x98182003);
- _surface->setClipRects(clipRects, clipRectsCount);
-}
-
-uint32 KmScene2806::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- startWalkToX(440, true);
- break;
- case 0x480D:
- GotoState(&Klaymen::stPullCord);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x4831:
- GotoState(&Klaymen::stGrow);
- break;
- case 0x4832:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stDrinkPotion);
- else
- GotoState(&Klaymen::stUseTube);
- break;
- }
- return 0;
-}
-
-KmScene2809::KmScene2809(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
- bool needsLargeSurface, NRect *clipRects, uint clipRectsCount)
- : Klaymen(vm, parentScene, x, y) {
-
- if (needsLargeSurface) {
- NDimensions dimensions = _animResource.loadSpriteDimensions(0x2838C010);
- delete _surface;
- createSurface(1000, dimensions.width, dimensions.height);
- loadSound(3, 0x58E0C341);
- loadSound(4, 0x40A00342);
- loadSound(5, 0xD0A1C348);
- loadSound(6, 0x166FC6E0);
- loadSound(7, 0x00018040);
- }
-
- _dataResource.load(0x1830009A);
- _surface->setClipRects(clipRects, clipRectsCount);
-}
-
-uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4804:
- startWalkToX(226, true);
- break;
- case 0x480D:
- GotoState(&Klaymen::stPullCord);
- break;
- case 0x4816:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x4831:
- GotoState(&Klaymen::stGrow);
- break;
- case 0x4832:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stDrinkPotion);
- else
- GotoState(&Klaymen::stUseTube);
- break;
- }
- return 0;
-}
-
-KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToXSmall(param.asPoint().x);
- break;
- case 0x4004:
- GotoState(&Klaymen::stStandIdleSmall);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x);
- break;
- case 0x481F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfterSmall);
- else if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalfSmall);
- else
- GotoState(&Klaymen::stWonderAboutSmall);
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStepSmall);
- else
- GotoState(&Klaymen::stWalkToFrontSmall);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToBackHalfSmall);
- else
- GotoState(&Klaymen::stTurnToBackSmall);
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- return 0;
-}
-
-KmScene2810::KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, uint clipRectsCount)
- : Klaymen(vm, parentScene, x, y) {
-
- _surface->setClipRects(clipRects, clipRectsCount);
-}
-
-uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4803:
- _destY = param.asInteger();
- GotoState(&Klaymen::stJumpToGrab);
- break;
- case 0x4804:
- if (param.asInteger() == 3)
- GotoState(&Klaymen::stFinishGrow);
- break;
- case 0x4812:
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x4818:
- startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481F:
- if (param.asInteger() == 0)
- GotoState(&Klaymen::stWonderAboutHalf);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stWonderAboutAfter);
- else if (param.asInteger() == 3)
- GotoState(&Klaymen::stTurnToUseHalf);
- else if (param.asInteger() == 4)
- GotoState(&Klaymen::stTurnAwayFromUse);
- else if (param.asInteger() == 5)
- GotoState(&Klaymen::stTurnToUseExt);
- else
- GotoState(&Klaymen::stWonderAbout);
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x4824:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = _dataResource.getPoint(param.asInteger()).y;
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4825:
- sendMessage(_parentScene, 0x2000, 0);
- _destY = _dataResource.getPoint(param.asInteger()).y;
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x4837:
- stopWalking();
- break;
- }
- return 0;
-}
-
-KmScene2812::KmScene2812(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
- : Klaymen(vm, parentScene, x, y) {
-
- // Empty
-}
-
-uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam &param) {
- switch (messageNum) {
- case 0x4001:
- case 0x4800:
- startWalkToX(param.asPoint().x, false);
- break;
- case 0x4004:
- GotoState(&Klaymen::stTryStandIdle);
- break;
- case 0x4805:
- _destY = param.asInteger();
- GotoState(&Klaymen::stJumpToGrabFall);
- break;
- case 0x4812:
- if (param.asInteger() == 2)
- GotoState(&Klaymen::stPickUpNeedle);
- else if (param.asInteger() == 1)
- GotoState(&Klaymen::stPickUpTube);
- else
- GotoState(&Klaymen::stPickUpGeneric);
- break;
- case 0x4817:
- setDoDeltaX(param.asInteger());
- gotoNextStateExt();
- break;
- case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
- break;
- case 0x481B:
- if (param.asPoint().y != 0)
- startWalkToXDistance(param.asPoint().y, param.asPoint().x);
- else
- startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
- case 0x481D:
- GotoState(&Klaymen::stTurnToUse);
- break;
- case 0x481E:
- GotoState(&Klaymen::stReturnFromUse);
- break;
- case 0x4820:
- sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
- break;
- case 0x4821:
- sendMessage(_parentScene, 0x2001, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
- break;
- case 0x4822:
- sendMessage(_parentScene, 0x2001, 0);
- _destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
- break;
- case 0x4823:
- sendMessage(_parentScene, 0x2002, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
- break;
- case 0x482D:
- setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
- gotoNextStateExt();
- break;
- case 0x482E:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stWalkToFrontNoStep);
- else
- GotoState(&Klaymen::stWalkToFront);
- break;
- case 0x482F:
- if (param.asInteger() == 1)
- GotoState(&Klaymen::stTurnToFront);
- else
- GotoState(&Klaymen::stTurnToBack);
- break;
- case 0x483F:
- startSpecialWalkRight(param.asInteger());
- break;
- case 0x4840:
- startSpecialWalkLeft(param.asInteger());
- break;
- }
- return 0;
-}
-
} // End of namespace Neverhood
diff --git a/engines/neverhood/klaymen.h b/engines/neverhood/klaymen.h
index 25443b5a35..a614560fc0 100644
--- a/engines/neverhood/klaymen.h
+++ b/engines/neverhood/klaymen.h
@@ -33,7 +33,6 @@ namespace Neverhood {
// TODO This code is horrible and weird and a lot of stuff needs renaming once a better name is found
// TODO Also the methods should probably rearranged and be grouped together more consistently
-class Klaymen;
class Scene;
const uint32 kKlaymenSpeedUpHash = 0x004A2148;
@@ -67,34 +66,30 @@ public:
void startIdleAnimation(uint32 fileHash, AnimationCb callback);
void upIdleAnimation();
+ // Idle animations - start
void stIdlePickEar();
void evIdlePickEarDone();
- uint32 hmIdlePickEar(int messageNum, const MessageParam &param, Entity *sender);
-
void stIdleSpinHead();
- uint32 hmIdleSpinHead(int messageNum, const MessageParam &param, Entity *sender);
-
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();
+ uint32 hmIdlePickEar(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmIdleSpinHead(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmIdleArms(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmIdleChest(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmIdleHeadOff(int messageNum, const MessageParam &param, Entity *sender);
+ // Idle animations - end
+
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 +129,7 @@ public:
void stPickUpTube();
uint32 hmPickUpTube(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stTurnToUse();
void stTurnToUseHalf();
void stTurnAwayFromUse();
@@ -150,12 +145,6 @@ public:
void stInsertKey();
uint32 hmInsertKey(int messageNum, const MessageParam &param, Entity *sender);
- void stReadNote();
- uint32 hmReadNote(int messageNum, const MessageParam &param, Entity *sender);
-
- void stHitByDoor();
- uint32 hmHitByDoor(int messageNum, const MessageParam &param, Entity *sender);
-
void stPeekWall();
uint32 hmPeekWall(int messageNum, const MessageParam &param, Entity *sender);
@@ -166,21 +155,8 @@ public:
void upPeekWallBlink();
void stPeekWall1();
-
void stPeekWall2();
- void stPullHammerLever();
- uint32 hmPullHammerLever(int messageNum, const MessageParam &param, Entity *sender);
-
- void stRidePlatformDown();
- void suRidePlatformDown();
-
- void stCrashDown();
- void stCrashDownFinished();
-
- void stShrink();
- uint32 hmShrink(int messageNum, const MessageParam &param, Entity *sender);
-
void stGrow();
uint32 hmGrow(int messageNum, const MessageParam &param, Entity *sender);
@@ -203,11 +179,6 @@ public:
void stLetGoOfLever();
void evLeverReleasedEvent();
- void stWakeUp();
-
- void stSleeping();
- uint32 hmSleeping(int messageNum, const MessageParam &param, Entity *sender);
-
void stPressButton();
void stPressFloorButton();
void stPressButtonSide();
@@ -228,20 +199,6 @@ public:
void stClimbLadderHalf();
uint32 hmClimbLadderHalf(int messageNum, const MessageParam &param, Entity *sender);
- void setupJumpToRing();
- void stJumpToRing1();
- void stJumpToRing2();
- void stJumpToRing4();
- uint32 hmJumpToRing(int messageNum, const MessageParam &param, Entity *sender);
-
- void stHangOnRing();
-
- void stJumpToRing3();
- uint32 hmJumpToRing3(int messageNum, const MessageParam &param, Entity *sender);
-
- void stHoldRing3();
- uint32 hmHoldRing3(int messageNum, const MessageParam &param, Entity *sender);
-
void stReleaseRing();
void stLandOnFeet();
@@ -263,33 +220,26 @@ 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);
void stSitIdleTeleporter();
void upSitIdleTeleporter();
-
void stSitIdleTeleporterBlink();
-
void stSitIdleTeleporterBlinkSecond();
void stTurnToUseInTeleporter();
-
void stReturnFromUseInTeleporter();
-
void stGetUpFromTeleporter();
void teleporterAppear(uint32 fileHash);
void teleporterDisappear(uint32 fileHash);
uint32 hmTeleporterAppearDisappear(int messageNum, const MessageParam &param, Entity *sender);
- void stClayDoorOpen();
- uint32 hmClayDoorOpen(int messageNum, const MessageParam &param, Entity *sender);
-
void stFallSkipJump();
void suFallSkipJump();
@@ -298,19 +248,6 @@ public:
uint32 hmMoveObject(int messageNum, const MessageParam &param, Entity *sender);
void upMoveObject();
- void stCloseEyes();
-
- void stTumbleHeadless();
- uint32 hmTumbleHeadless(int messageNum, const MessageParam &param, Entity *sender);
-
- void stFetchMatch();
- void stLightMatch();
- uint32 hmMatch(int messageNum, const MessageParam &param, Entity *sender);
-
- void stHitByBoxingGlove();
- uint32 hmHitByBoxingGlove(int messageNum, const MessageParam &param, Entity *sender);
- void evHitByBoxingGloveDone();
-
void stStandIdleSmall();
void stWonderAboutSmall();
void stWonderAboutHalfSmall();
@@ -326,35 +263,18 @@ public:
void stFinishGrow();
uint32 hmFinishGrow(int messageNum, const MessageParam &param, Entity *sender);
-
- void stJumpToRingVenusFlyTrap();
- uint32 hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
-
- void stDropFromRing();
void stStandIdleSpecial();
uint32 hmStandIdleSpecial(int messageNum, const MessageParam &param, Entity *sender);
- void stPressDoorButton();
- uint32 hmPressDoorButton(int messageNum, const MessageParam &param, Entity *sender);
-
void stSpitOutFall0();
void stSpitOutFall2();
void suFallDown();
void upSpitOutFall();
- void stJumpAndFall();
- uint32 hmJumpAndFall(int messageNum, const MessageParam &param, Entity *sender);
-
void stFalling();
void stFallTouchdown();
- void stMoveVenusFlyTrap();
- void stContinueMovingVenusFlyTrap();
- uint32 hmMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmFirstMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
- void evMoveVenusFlyTrapDone();
-
void stPeekInside();
void stPeekInsideReturn();
void stPeekInsideBlink();
@@ -363,7 +283,7 @@ public:
////////////////////////////////////////////////////////////////////////////
void stopWalking();
-
+
void suAction();
void suUpdateDestX();
void suWalkingTestExit();
@@ -375,13 +295,8 @@ public:
void setKlaymenIdleTable1();
void setKlaymenIdleTable2();
void setKlaymenIdleTable3();
-
- void setSoundFlag(bool value) { _soundFlag = value; }
- void spitIntoPipe();
- void stTrySpitIntoPipe();
- void stContSpitIntoPipe();
- uint32 hmSpit(int messageNum, const MessageParam &param, Entity *sender);
+ void setSoundFlag(bool value) { _soundFlag = value; }
void stRidePlatform();
void suRidePlatform();
@@ -416,7 +331,7 @@ protected:
NPointArray *_pathPoints;
bool _soundFlag;
-
+
int16 _spitOutCountdown;
bool _isSittingInTeleporter;
@@ -432,13 +347,6 @@ protected:
int _moveObjectCountdown;
- bool _canSpitPipe;
- bool _contSpitPipe;
- bool _readyToSpit;
- uint32 _spitPipeIndex;
- uint32 _spitDestPipeIndex;
- uint32 _spitContDestPipeIndex;
-
virtual void xUpdate();
virtual uint32 xHandleMessage(int messageNum, const MessageParam &param);
@@ -456,314 +364,9 @@ 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:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1002 : public Klaymen {
-public:
- KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1004 : public Klaymen {
-public:
- KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1109 : public Klaymen {
-public:
- KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1201 : public Klaymen {
-public:
- KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1303 : public Klaymen {
-public:
- KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1304 : public Klaymen {
-public:
- KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1305 : public Klaymen {
-public:
- KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1306 : public Klaymen {
-public:
- KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1308 : public Klaymen {
-public:
- KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1401 : public Klaymen {
-public:
- KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1402 : public Klaymen {
-public:
- KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1403 : public Klaymen {
-public:
- KmScene1403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1404 : public Klaymen {
-public:
- KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1608 : public Klaymen {
-public:
- KmScene1608(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1705 : public Klaymen {
-public:
- KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene1901 : public Klaymen {
-public:
- KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2001 : public Klaymen {
-public:
- KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2101 : public Klaymen {
-public:
- KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2201 : public Klaymen {
-public:
- KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2203 : public Klaymen {
-public:
- KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2205 : public Klaymen {
-public:
- KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2206 : public Klaymen {
-public:
- KmScene2206(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
- ~KmScene2206();
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2207 : public Klaymen {
-public:
- KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2242 : public Klaymen {
-public:
- KmScene2242(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmHallOfRecords : public Klaymen {
-public:
- KmHallOfRecords(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2247 : public Klaymen {
-public:
- KmScene2247(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- void xUpdate();
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2401 : public Klaymen {
-public:
- KmScene2401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2402 : public Klaymen {
-public:
- KmScene2402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2403 : public Klaymen {
-public:
- KmScene2403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2406 : public Klaymen {
-public:
- KmScene2406(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2501 : public Klaymen {
-public:
- KmScene2501(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2732 : public Klaymen {
-public:
- KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2801 : public Klaymen {
-public:
- KmScene2801(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2803 : public Klaymen {
-public:
- KmScene2803(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2803Small : public Klaymen {
-public:
- KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2805 : public Klaymen {
-public:
- KmScene2805(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2806 : public Klaymen {
-public:
- KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
- bool needsLargeSurface, NRect *clipRects, uint clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2809 : public Klaymen {
-public:
- KmScene2809(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
- bool needsLargeSurface, NRect *clipRects, uint clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2810Small : public Klaymen {
-public:
- KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2810 : public Klaymen {
-public:
- KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
- NRect *clipRects, uint clipRectsCount);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
-};
-
-class KmScene2812 : public Klaymen {
-public:
- KmScene2812(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
- uint32 xHandleMessage(int messageNum, const MessageParam &param);
};
} // End of namespace Neverhood
diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp
index a8631cb0d6..6b0635598f 100644
--- a/engines/neverhood/menumodule.cpp
+++ b/engines/neverhood/menumodule.cpp
@@ -20,6 +20,11 @@
*
*/
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+#include "gui/saveload.h"
+
#include "neverhood/menumodule.h"
#include "neverhood/gamemodule.h"
@@ -68,17 +73,19 @@ 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);
createScene(MAIN_MENU, -1);
}
MenuModule::~MenuModule() {
_vm->_mixer->pauseAll(false);
+ _vm->toggleSoundUpdate(true);
_vm->_screen->setPaletteData(_savedPaletteData);
}
@@ -153,7 +160,8 @@ void MenuModule::updateScene() {
createScene(MAKING_OF, -1);
break;
case kMainMenuToggleMusic:
- // TODO Toggle music 0048A367
+ _vm->toggleMusic(!_vm->musicIsEnabled());
+ _vm->_mixer->muteSoundType(Audio::Mixer::kMusicSoundType, !_vm->musicIsEnabled());
createScene(MAIN_MENU, -1);
break;
case kMainMenuDeleteGame:
@@ -191,24 +199,26 @@ uint32 MenuModule::handleMessage(int messageNum, const MessageParam &param, Enti
}
void MenuModule::createLoadGameMenu() {
- _savegameSlot = -1;
- _savegameList = new SavegameList();
- loadSavegameList();
+ refreshSaveGameList();
_childObject = new LoadGameMenu(_vm, this, _savegameList);
}
void MenuModule::createSaveGameMenu() {
- _savegameSlot = -1;
- _savegameList = new SavegameList();
- loadSavegameList();
+ refreshSaveGameList();
_childObject = new SaveGameMenu(_vm, this, _savegameList);
}
void MenuModule::createDeleteGameMenu() {
+ refreshSaveGameList();
+ _childObject = new DeleteGameMenu(_vm, this, _savegameList);
+}
+
+void MenuModule::refreshSaveGameList() {
_savegameSlot = -1;
+ delete _savegameList;
+ _savegameList = NULL;
_savegameList = new SavegameList();
loadSavegameList();
- _childObject = new DeleteGameMenu(_vm, this, _savegameList);
}
void MenuModule::handleLoadGameMenuAction(bool doLoad) {
@@ -257,7 +267,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());
@@ -315,7 +325,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,
@@ -327,37 +337,37 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
0x16C62130,
0x16C62100
};
-
+
static const NRect kMenuButtonCollisionBounds[] = {
- NRect(52, 121, 110, 156),
- NRect(52, 192, 109, 222),
- NRect(60, 257, 119, 286),
- NRect(67, 326, 120, 354),
- NRect(70, 389, 128, 416),
- NRect(523, 113, 580, 144),
- NRect(525, 176, 577, 206),
- NRect(527, 384, 580, 412),
- NRect(522, 255, 580, 289)
+ { 52, 121, 110, 156 },
+ { 52, 192, 109, 222 },
+ { 60, 257, 119, 286 },
+ { 67, 326, 120, 354 },
+ { 70, 389, 128, 416 },
+ { 523, 113, 580, 144 },
+ { 525, 176, 577, 206 },
+ { 527, 384, 580, 412 },
+ { 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);
+
+ insertStaticSprite(0x41137051, 100); // "Options" header text
+ insertStaticSprite(0xC10B2015, 100); // Button texts
+
+ if (!_vm->musicIsEnabled())
+ insertStaticSprite(0x0C24C0EE, 100); // "Music is off" button
for (uint buttonIndex = 0; buttonIndex < 9; ++buttonIndex) {
Sprite *menuButton = insertSprite<MenuButton>(this, buttonIndex,
kMenuButtonFileHashes[buttonIndex], kMenuButtonCollisionBounds[buttonIndex]);
addCollisionSprite(menuButton);
}
-
- SetUpdateHandler(&Scene::update);
- SetMessageHandler(&MainMenu::handleMessage);
+
+ SetUpdateHandler(&Scene::update);
+ SetMessageHandler(&MainMenu::handleMessage);
}
@@ -387,23 +397,25 @@ 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;
-
+
+ _vm->toggleSoundUpdate(true);
_musicResource = new MusicResource(_vm);
_musicResource->load(0x30812225);
_musicResource->play(0);
-
+
}
CreditsScene::~CreditsScene() {
_musicResource->unload();
delete _musicResource;
+ _vm->toggleSoundUpdate(false);
}
void CreditsScene::update() {
@@ -460,7 +472,7 @@ Widget::Widget(NeverhoodEngine *vm, int16 x, int16 y, GameStateMenu *parentScene
SetUpdateHandler(&Widget::update);
SetMessageHandler(&Widget::handleMessage);
-
+
setPosition(x, y);
}
@@ -523,7 +535,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() {
@@ -564,7 +576,8 @@ TextEditWidget::TextEditWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateM
_maxVisibleChars = (_rect.x2 - _rect.x1) / _fontSurface->getCharWidth();
_cursorPos = 0;
-
+ _textLabelWidget = NULL;
+
SetUpdateHandler(&TextEditWidget::update);
SetMessageHandler(&TextEditWidget::handleMessage);
}
@@ -608,7 +621,7 @@ void TextEditWidget::initialize() {
_textLabelWidget->initialize();
if (_cursorFileHash != 0) {
cursorSpriteResource.load(_cursorFileHash, true);
- _cursorSurface = new BaseSurface(_vm, 0, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height);
+ _cursorSurface = new BaseSurface(_vm, 0, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height, "cursor");
_cursorSurface->drawSpriteResourceEx(cursorSpriteResource, false, false, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height);
_cursorSurface->setVisible(!_readOnly);
}
@@ -757,9 +770,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();
@@ -797,7 +808,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();
@@ -821,7 +832,7 @@ void SavegameListBox::scrollUp() {
}
void SavegameListBox::scrollDown() {
- if (_lastVisibleItem < (int)_textLabelItems.size()) {
+ if (_lastVisibleItem < (int)_textLabelItems.size() - 1) {
++_firstVisibleItem;
++_lastVisibleItem;
refresh();
@@ -838,7 +849,7 @@ void SavegameListBox::pageUp() {
}
void SavegameListBox::pageDown() {
- int amount = MIN((int)_textLabelItems.size() - _lastVisibleItem, _maxVisibleItemsCount);
+ int amount = MIN((int)_textLabelItems.size() - _lastVisibleItem - 1, _maxVisibleItemsCount);
if (amount > 0) {
_firstVisibleItem += amount;
_lastVisibleItem += amount;
@@ -846,17 +857,68 @@ void SavegameListBox::pageDown() {
}
}
+int GameStateMenu::scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc) {
+ const EnginePlugin *plugin = NULL;
+ EngineMan.findGame(ConfMan.get("gameid"), &plugin);
+ GUI::SaveLoadChooser *dialog;
+ Common::String desc;
+ int slot;
+
+ if (isSave) {
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ desc = dialog->getResultString();
+
+ if (desc.empty())
+ desc = dialog->createDefaultSaveDescription(slot);
+
+ if (desc.size() > 29)
+ desc = Common::String(desc.c_str(), 29);
+
+ saveDesc = desc;
+ } else {
+ dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ }
+
+ delete dialog;
+
+ return slot;
+}
+
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);
-
+
+ if (!ConfMan.getBool("originalsaveload")) {
+ Common::String saveDesc;
+ int saveCount = savegameList->size();
+ int slot = scummVMSaveLoadDialog(isSave, saveDesc);
+
+ if (slot >= 0) {
+ if (!isSave) {
+ ((MenuModule*)_parentModule)->setLoadgameInfo(slot);
+ } else {
+ ((MenuModule*)_parentModule)->setSavegameInfo(saveDesc,
+ slot, slot >= saveCount);
+ }
+ leaveScene(0);
+ } else {
+ leaveScene(1);
+ }
+ return;
+ }
+
setBackground(backgroundFileHash);
setPalette(backgroundFileHash);
insertScreenMouse(mouseFileHash, mouseRect);
@@ -869,13 +931,13 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
_textEditWidget = new TextEditWidget(_vm, textEditX, textEditY, this, 29,
_fontSurface, textEditBackgroundFileHash, textEditRect);
- if (textEditCursorFileHash != 0)
+ if (isSave)
_textEditWidget->setCursor(textEditCursorFileHash, 2, 13);
else
_textEditWidget->setReadOnly(true);
_textEditWidget->initialize();
setCurrWidget(_textEditWidget);
-
+
for (uint buttonIndex = 0; buttonIndex < 6; ++buttonIndex) {
Sprite *menuButton = insertSprite<MenuButton>(this, buttonIndex,
buttonFileHashes[buttonIndex], buttonCollisionBounds[buttonIndex]);
@@ -884,7 +946,6 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
SetUpdateHandler(&Scene::update);
SetMessageHandler(&GameStateMenu::handleMessage);
-
}
GameStateMenu::~GameStateMenu() {
@@ -969,17 +1030,17 @@ static const uint32 kSaveGameMenuButtonFileHashes[] = {
};
static const NRect kSaveGameMenuButtonCollisionBounds[] = {
- NRect(518, 106, 602, 160),
- NRect(516, 378, 596, 434),
- NRect(394, 108, 458, 206),
- NRect(400, 204, 458, 276),
- NRect(398, 292, 456, 352),
- NRect(396, 352, 460, 444)
+ { 518, 106, 602, 160 },
+ { 516, 378, 596, 434 },
+ { 394, 108, 458, 206 },
+ { 400, 204, 458, 276 },
+ { 398, 292, 456, 352 },
+ { 396, 352, 460, 444 }
};
-static const NRect kSaveGameMenuListBoxRect(0, 0, 320, 272);
-static const NRect kSaveGameMenuTextEditRect(0, 0, 377, 17);
-static const NRect kSaveGameMenuMouseRect(50, 47, 427, 64);
+static const NRect kSaveGameMenuListBoxRect = { 0, 0, 320, 272 };
+static const NRect kSaveGameMenuTextEditRect = { 0, 0, 377, 17 };
+static const NRect kSaveGameMenuMouseRect = { 50, 47, 427, 64 };
SaveGameMenu::SaveGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList)
: GameStateMenu(vm, parentModule, savegameList, kSaveGameMenuButtonFileHashes, kSaveGameMenuButtonCollisionBounds,
@@ -1003,17 +1064,17 @@ static const uint32 kLoadGameMenuButtonFileHashes[] = {
};
static const NRect kLoadGameMenuButtonCollisionBounds[] = {
- NRect( 44, 115, 108, 147),
- NRect( 52, 396, 112, 426),
- NRect(188, 116, 245, 196),
- NRect(189, 209, 239, 269),
- NRect(187, 301, 233, 349),
- NRect(182, 358, 241, 433)
+ { 44, 115, 108, 147 },
+ { 52, 396, 112, 426 },
+ { 188, 116, 245, 196 },
+ { 189, 209, 239, 269 },
+ { 187, 301, 233, 349 },
+ { 182, 358, 241, 433 }
};
-static const NRect kLoadGameMenuListBoxRect(0, 0, 320, 271);
-static const NRect kLoadGameMenuTextEditRect(0, 0, 320, 17);
-static const NRect kLoadGameMenuMouseRect(263, 48, 583, 65);
+static const NRect kLoadGameMenuListBoxRect = { 0, 0, 320, 271 };
+static const NRect kLoadGameMenuTextEditRect = { 0, 0, 320, 17 };
+static const NRect kLoadGameMenuMouseRect = { 263, 48, 583, 65 };
LoadGameMenu::LoadGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList)
: GameStateMenu(vm, parentModule, savegameList, kLoadGameMenuButtonFileHashes, kLoadGameMenuButtonCollisionBounds,
@@ -1036,21 +1097,21 @@ static const uint32 kDeleteGameMenuButtonFileHashes[] = {
};
static const NRect kDeleteGameMenuButtonCollisionBounds[] = {
- NRect(518, 46, 595, 91),
- NRect(524, 322, 599, 369),
- NRect(395, 40, 462, 127),
- NRect(405, 126, 460, 185),
- NRect(397, 205, 456, 273),
- NRect(395, 278, 452, 372)
+ { 518, 46, 595, 91 },
+ { 524, 322, 599, 369 },
+ { 395, 40, 462, 127 },
+ { 405, 126, 460, 185 },
+ { 397, 205, 456, 273 },
+ { 395, 278, 452, 372 }
};
-static const NRect kDeleteGameMenuListBoxRect(0, 0, 320, 271);
-static const NRect kDeleteGameMenuTextEditRect(0, 0, 320, 17);
+static const NRect kDeleteGameMenuListBoxRect = { 0, 0, 320, 271 };
+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) {
@@ -1071,10 +1132,10 @@ QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule
};
static const NRect kQueryOverwriteMenuCollisionBounds[] = {
- NRect(145, 334, 260, 385),
- NRect(365, 340, 477, 388)
+ { 145, 334, 260, 385 },
+ { 365, 340, 477, 388 }
};
-
+
setBackground(0x043692C4);
setPalette(0x043692C4);
insertScreenMouse(0x692C004B);
@@ -1097,7 +1158,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 08858ad204..9da9c849a9 100644
--- a/engines/neverhood/menumodule.h
+++ b/engines/neverhood/menumodule.h
@@ -45,6 +45,7 @@ public:
void setLoadgameInfo(uint index);
void setSavegameInfo(const Common::String &description, uint index, bool newSavegame);
void setDeletegameInfo(uint index);
+ void refreshSaveGameList();
protected:
int _sceneNum;
byte *_savedPaletteData;
@@ -78,7 +79,6 @@ class MainMenu : public Scene {
public:
MainMenu(NeverhoodEngine *vm, Module *parentModule);
protected:
- Sprite *_musicOnButton;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
@@ -123,8 +123,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();
@@ -205,13 +205,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);
@@ -229,6 +229,7 @@ protected:
Common::String _savegameDescription;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
virtual void performAction();
+ int scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc);
};
class SaveGameMenu : public GameStateMenu {
diff --git a/engines/neverhood/microtiles.cpp b/engines/neverhood/microtiles.cpp
index e19be52b5a..3dd6475046 100644
--- a/engines/neverhood/microtiles.cpp
+++ b/engines/neverhood/microtiles.cpp
@@ -118,8 +118,6 @@ RectangleList *MicroTileArray::getRectangles() {
for (y = 0; y < _tilesH; ++y) {
for (x = 0; x < _tilesW; ++x) {
-
- int start;
int finish = 0;
BoundingBox boundingBox = _tiles[i];
@@ -132,8 +130,6 @@ RectangleList *MicroTileArray::getRectangles() {
y0 = (y * TileSize) + TileY0(boundingBox);
y1 = (y * TileSize) + TileY1(boundingBox);
- start = i;
-
if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) { // check if the tile continues
while (!finish) {
++x;
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/module.h b/engines/neverhood/module.h
index e98012cbea..8ab2159030 100644
--- a/engines/neverhood/module.h
+++ b/engines/neverhood/module.h
@@ -48,9 +48,11 @@ public:
Module(NeverhoodEngine *vm, Module *parentModule);
virtual ~Module();
virtual void draw();
+ SceneType getSceneType() { return _sceneType; }
+
+ Entity *_childObject;
protected:
Module *_parentModule;
- Entity *_childObject;
bool _done;
uint32 _moduleResult;
SceneType _sceneType;
diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index 714fc3079b..9c1220134c 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/neverhood
MODULE_OBJS = \
background.o \
blbarchive.o \
+ console.o \
detection.o \
diskplayerscene.o \
entity.o \
@@ -14,26 +15,44 @@ MODULE_OBJS = \
microtiles.o \
module.o \
modules/module1000.o \
+ modules/module1000_sprites.o \
modules/module1100.o \
+ modules/module1100_sprites.o \
modules/module1200.o \
+ modules/module1200_sprites.o \
modules/module1300.o \
+ modules/module1300_sprites.o \
modules/module1400.o \
+ modules/module1400_sprites.o \
modules/module1500.o \
modules/module1600.o \
+ modules/module1600_sprites.o \
modules/module1700.o \
+ modules/module1700_sprites.o \
modules/module1800.o \
modules/module1900.o \
+ modules/module1900_sprites.o \
modules/module2000.o \
+ modules/module2000_sprites.o \
modules/module2100.o \
+ modules/module2100_sprites.o \
modules/module2200.o \
+ modules/module2200_sprites.o \
modules/module2300.o \
modules/module2400.o \
+ modules/module2400_sprites.o \
modules/module2500.o \
+ modules/module2500_sprites.o \
modules/module2600.o \
+ modules/module2600_sprites.o \
modules/module2700.o \
+ modules/module2700_sprites.o \
modules/module2800.o \
+ modules/module2800_sprites.o \
modules/module2900.o \
+ modules/module2900_sprites.o \
modules/module3000.o \
+ modules/module3000_sprites.o \
mouse.o \
navigationscene.o \
neverhood.o \
diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp
index ef2872ba2e..534fb2ec2f 100644
--- a/engines/neverhood/modules/module1000.cpp
+++ b/engines/neverhood/modules/module1000.cpp
@@ -21,15 +21,14 @@
*/
#include "neverhood/modules/module1000.h"
+#include "neverhood/modules/module1000_sprites.h"
namespace Neverhood {
Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
- debug("Create Module1000(%d)", which);
- _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144;
+ _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144;
_vm->_soundMan->addMusic(0x03294419, 0x061880C6);
_vm->_soundMan->addMusic(0x03294419, _musicFileHash);
@@ -48,7 +47,7 @@ Module1000::~Module1000() {
}
void Module1000::createScene(int sceneNum, int which) {
- debug("Module1000::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1000::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -120,231 +119,18 @@ void Module1000::updateScene() {
}
}
-// Scene1001
-
-AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- createSurface(800, 137, 242);
- _x = 726;
- _y = 440;
- stShowIdleDoor();
- loadSound(1, 0xED403E03);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1001Door::handleMessage);
-}
-
-uint32 AsScene1001Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- hammerHitsDoor();
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return 0;
-}
-
-void AsScene1001Door::hammerHitsDoor() {
- switch (getGlobalVar(V_DOOR_STATUS)) {
- case 0:
- case 1:
- playSound(0, 0x65482F03);
- startAnimation(0x624C0498, 1, 3);
- NextState(&AsScene1001Door::stShowIdleDoor);
- break;
- case 2:
- playSound(1);
- startAnimation(0x624C0498, 6, 6);
- NextState(&AsScene1001Door::stBustedDoorMove);
- break;
- default:
- // Nothing
- break;
- }
- incGlobalVar(V_DOOR_STATUS, 1);
-}
-
-void AsScene1001Door::stShowIdleDoor() {
- switch (getGlobalVar(V_DOOR_STATUS)) {
- case 1:
- startAnimation(0x624C0498, 4, -1);
- _newStickFrameIndex = 4;
- break;
- case 2:
- startAnimation(0x624C0498, 1, -1);
- _newStickFrameIndex = 1;
- break;
- case 3:
- stopAnimation();
- setVisible(false);
- break;
- default:
- startAnimation(0x624C0498, 0, -1);
- _newStickFrameIndex = 0;
- break;
- }
-}
-
-void AsScene1001Door::stBustedDoorMove() {
- setGlobalVar(V_DOOR_BUSTED, 1);
- startAnimation(0x624C0498, 6, 6);
- NextState(&AsScene1001Door::stBustedDoorGone);
- _x = 30;
-}
-
-void AsScene1001Door::stBustedDoorGone() {
- playSound(0);
- stopAnimation();
- setVisible(false);
-}
-
-AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor)
- : AnimatedSprite(vm, 1100), _asDoor(asDoor) {
-
- _x = 547;
- _y = 206;
- createSurface(900, 177, 192);
- startAnimation(0x022C90D4, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1001Hammer::handleMessage);
-}
-
-uint32 AsScene1001Hammer::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x00352100)
- sendMessage(_asDoor, 0x2000, 0);
- else if (param.asInteger() == 0x0A1A0109)
- playSound(0, 0x66410886);
- break;
- case 0x2000:
- startAnimation(0x022C90D4, 1, -1);
- playSound(0, 0xE741020A);
- _newStickFrameIndex = STICK_LAST_FRAME;
- break;
- }
- return 0;
-}
-
-AsScene1001Window::AsScene1001Window(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200) {
-
- _x = 320;
- _y = 240;
- createSurface(100, 66, 129);
- startAnimation(0xC68C2299, 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1001Window::handleMessage);
-}
-
-uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x0E0A1410)
- playSound(0, 0x60803F10);
- break;
- case 0x2001:
- startAnimation(0xC68C2299, 0, -1);
- break;
- case 0x3002:
- SetMessageHandler(NULL);
- setGlobalVar(V_WINDOW_OPEN, 1);
- setVisible(false);
- break;
- }
- return 0;
-}
-
-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);
- _newStickFrameIndex = 0;
- _x = x;
- _y = y;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1001Lever::handleMessage);
-}
-
-uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x00C0C444)
- sendMessage(_parentScene, 0x480F, 0);
- else if (param.asInteger() == 0xC41A02C0)
- playSound(0, 0x40581882);
- break;
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x3002:
- startAnimation(0x04A98C36, 0, -1);
- _newStickFrameIndex = 0;
- break;
- case 0x480F:
- startAnimation(0x04A98C36, 0, -1);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- 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;
- 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) {
- case 0x480B:
- sendMessage(_parentScene, 0x480B, 0);
- setVisible(true);
- _countdown = 8;
- playSound(0, _soundFileHash);
- break;
- }
- 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);
@@ -375,7 +161,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);
@@ -441,719 +227,6 @@ uint32 Scene1001::handleMessage(int messageNum, const MessageParam &param, Entit
return messageResult;
}
-// Scene1002
-
-AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) {
-
- SetUpdateHandler(&AsScene1002Ring::update);
-
- if (_isSpecial) {
- createSurface(990, 68, 314);
- if (isRingLow) {
- startAnimation(0x04103090, 0, -1);
- SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
- } else {
- startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
- SetMessageHandler(&AsScene1002Ring::hmRingIdle);
- }
- } else {
- createSurface(990, 68, 138);
- startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
- SetMessageHandler(&AsScene1002Ring::hmRingIdle);
- }
-
- setClipRect(0, clipY1, 640, 480);
-
- _x = x;
- _y = y;
-
- setDoDeltaX(_vm->_rnd->getRandomNumber(1));
-
-}
-
-void AsScene1002Ring::update() {
- updateAnim();
- updatePosition();
-}
-
-uint32 AsScene1002Ring::hmRingIdle(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4806:
- setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
- sendMessage(_parentScene, 0x4806, 0);
- SetMessageHandler(&AsScene1002Ring::hmRingPulled1);
- startAnimation(_isSpecial ? 0x87502558 : 0x80DD4010, 0, -1);
- break;
- case 0x480F:
- setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
- sendMessage(_parentScene, 0x480F, 0);
- SetMessageHandler(&AsScene1002Ring::hmRingPulled2);
- startAnimation(0x861A2020, 0, -1);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002Ring::hmRingPulled1(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- startAnimation(_isSpecial ? 0x78D0A812 : 0xB85D2A10, 0, -1);
- SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
- break;
- case 0x4807:
- sendMessage(_parentScene, 0x4807, 0);
- setDoDeltaX(_vm->_rnd->getRandomNumber(1));
- startAnimation(0x8258A030, 0, -1);
- SetMessageHandler(&AsScene1002Ring::hmRingReleased);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002Ring::hmRingPulled2(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- startAnimation(0x04103090, 0, -1);
- SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002Ring::hmRingHangingLow(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4807:
- sendMessage(_parentScene, 0x4807, 0);
- setDoDeltaX(_vm->_rnd->getRandomNumber(1));
- startAnimation(0x8258A030, 0, -1);
- SetMessageHandler(&AsScene1002Ring::hmRingReleased);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmRingIdle(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x05410F72)
- playSound(0, 0x21EE40A9);
- break;
- case 0x3002:
- startAnimation(0xA85C4011, 0, -1);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-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);
- SetMessageHandler(&AsScene1002Door::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsScene1002Door::update() {
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 AsScene1002Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4808:
- setGlobalVar(V_FLYTRAP_RING_DOOR, 1);
- SetSpriteUpdate(&AsScene1002Door::suOpenDoor);
- break;
- case 0x4809:
- setGlobalVar(V_FLYTRAP_RING_DOOR, 0);
- SetSpriteUpdate(&AsScene1002Door::suCloseDoor);
- break;
- }
- return messageResult;
-}
-
-void AsScene1002Door::suOpenDoor() {
- if (_y > 49) {
- _y -= 8;
- if (_y < 49) {
- SetSpriteUpdate(NULL);
- _y = 49;
- }
- _needRefresh = true;
- }
-}
-
-void AsScene1002Door::suCloseDoor() {
- if (_y < 239) {
- _y += 8;
- if (_y > 239) {
- SetSpriteUpdate(NULL);
- _y = 239;
- }
- _needRefresh = true;
- }
-}
-
-AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1400) {
-
- createSurface(1025, 88, 165);
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage);
-}
-
-uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2004:
- _x = ((Sprite*)sender)->getX() - 98;
- _y = ((Sprite*)sender)->getY() - 111;
- startAnimation(0x0422255A, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
-AsScene1002DoorSpy::AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect)
- : AnimatedSprite(vm, 1300), _clipRect(clipRect), _parentScene(parentScene), _asDoor(asDoor), _asBoxingGloveHitEffect(asScene1002BoxingGloveHitEffect) {
-
- createSurface(800, 136, 147);
- setClipRect(clipRect);
- suDoorSpy();
- loadSound(0, 0xC0C40298);
- startAnimation(0x586C1D48, 0, 0);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
- SetSpriteUpdate(&AsScene1002DoorSpy::suDoorSpy);
-}
-
-uint32 AsScene1002DoorSpy::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0xA61CA1C2)
- sendMessage(_asBoxingGloveHitEffect, 0x2004, 0);
- else if (param.asInteger() == 0x14CE0620)
- playSound(0);
- break;
- case 0x2003:
- stDoorSpyBoxingGlove();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002DoorSpy::hmDoorSpyAnimation(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1002DoorSpy::suDoorSpy() {
- _x = _asDoor->getX() + 34;
- _y = _asDoor->getY() + 175;
-}
-
-void AsScene1002DoorSpy::stDoorSpyIdle() {
- setClipRect(_clipRect);
- _parentScene->setSurfacePriority(getSurface(), 800);
- startAnimation(0x586C1D48, 0, 0);
- SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
-}
-
-void AsScene1002DoorSpy::stDoorSpyBoxingGlove() {
- setClipRect(0, 0, 640, 480);
- _parentScene->setSurfacePriority(getSurface(), 1200);
- startAnimation(0x586C1D48, 1, -1);
- SetMessageHandler(&AsScene1002DoorSpy::hmDoorSpyAnimation);
- NextState(&AsScene1002DoorSpy::stDoorSpyIdle);
-}
-
-SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
- : StaticSprite(vm, 1100), _parentScene(parentScene), _status(0) {
-
- _soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000;
- _fileHashes[0] = fileHash1;
- _fileHashes[1] = fileHash2;
- createSurface(surfacePriority, 40, 40);
- loadSprite(fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
- setVisible(false);
- SetUpdateHandler(&SsCommonPressButton::update);
- SetMessageHandler(&SsCommonPressButton::handleMessage);
-}
-
-void SsCommonPressButton::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
- _fileHashes[0] = fileHash1;
- _fileHashes[1] = fileHash2;
- loadSprite(_status == 2 ? fileHash2 : fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
-}
-
-void SsCommonPressButton::update() {
- if (_countdown != 0 && (--_countdown) == 0) {
- if (_status == 1) {
- _status = 2;
- loadSprite(_fileHashes[1], kSLFDefDrawOffset | kSLFDefPosition);
- _countdown = 4;
- } else if (_status == 2) {
- _status = 3;
- loadSprite(_fileHashes[0], kSLFDefDrawOffset | kSLFDefPosition);
- _countdown = 4;
- } else if (_status == 3) {
- _status = 0;
- setVisible(false);
- }
- }
-}
-
-uint32 SsCommonPressButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x480B:
- sendMessage(_parentScene, 0x480B, 0);
- _status = 1;
- _countdown = 4;
- setVisible(true);
- playSound(0, _soundFileHash);
- break;
- }
- return messageResult;
-}
-
-AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _isSecond(isSecond), _countdown(0) {
-
- createSurface(995, 175, 195);
- if (!_isSecond) {
- if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
- setDoDeltaX(1);
- _x = 366;
- _y = 435;
- stRingGrabbed();
- } else {
- _x = 174 + getGlobalVar(V_FLYTRAP_POSITION_1) * 32;
- _y = 435;
- stIdle();
- }
- } else {
- _x = 186 + getGlobalVar(V_FLYTRAP_POSITION_2) * 32;
- _y = 364;
- if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) {
- stRingGrabbed();
- } else {
- stIdle();
- }
- }
- _flags = 4;
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
-}
-
-void AsScene1002VenusFlyTrap::update() {
- if (_countdown != 0 && (--_countdown == 0))
- gotoNextState();
- AnimatedSprite::update();
-}
-
-void AsScene1002VenusFlyTrap::upIdle() {
- if (_countdown == 0 && _klaymen->getX() - 20 > _x)
- setDoDeltaX(1);
- else if (_klaymen->getX() + 20 < _x)
- setDoDeltaX(0);
- update();
-}
-
-uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x000890C4)
- playSound(0, 0xC21190D8);
- else if (param.asInteger() == 0x522200A0)
- playSound(0, 0x931080C8);
- break;
- case 0x1011:
- if (_isSecond) {
- if (_x >= 154 && _x <= 346) {
- sendMessage(_parentScene, 0x2000, 0);
- messageResult = 1;
- }
- } else {
- if (_x >= 174 && _x <= 430) {
- sendMessage(_parentScene, 0x2000, 0);
- messageResult = 1;
- }
- }
- break;
- case 0x480B:
- setDoDeltaX(param.asInteger() != 0 ? 1 : 0);
- if (!_isSecond) {
- if (getGlobalVar(V_FLYTRAP_RING_DOOR))
- stRelease();
- else
- stWalk();
- } else {
- if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE))
- stRelease();
- else
- stWalk();
- }
- break;
- case 0x480C:
- if (_isSecond) {
- if (_x >= 154 && _x <= 346)
- messageResult = 1;
- else
- messageResult = 0;
- } else {
- if (_x >= 174 && _x <= 430)
- messageResult = 1;
- else
- messageResult = 0;
- }
- break;
- case 0x480E:
- if (param.asInteger() == 1)
- stGrabRing();
- break;
- case 0x4810:
- swallowKlaymen();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 995);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1015);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002VenusFlyTrap::hmAnimationSimple(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x000890C4)
- playSound(0, 0xC21190D8);
- else if (param.asInteger() == 0x41881801) {
- if (_isSecond) {
- if (_x > 330)
- sendMessage(_klaymen, 0x4811, 2);
- else
- sendMessage(_klaymen, 0x4811, 0);
- } else {
- sendMessage(_klaymen, 0x4811, 0);
- }
- } else if (param.asInteger() == 0x522200A0)
- playSound(0, 0x931080C8);
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 995);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1015);
- break;
- }
- return messageResult;
-}
-
-void AsScene1002VenusFlyTrap::stWalkBack() {
- setDoDeltaX(2);
- startAnimation(0xC4080034, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
- NextState(&AsScene1002VenusFlyTrap::stIdle);
-}
-
-void AsScene1002VenusFlyTrap::stWalk() {
- startAnimation(0xC4080034, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
- NextState(&AsScene1002VenusFlyTrap::stIdle);
-}
-
-void AsScene1002VenusFlyTrap::stRelease() {
- sendMessage(_parentScene, 0x4807, 0);
- startAnimation(0x82292851, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
- NextState(&AsScene1002VenusFlyTrap::stIdle);
-}
-
-void AsScene1002VenusFlyTrap::stGrabRing() {
- setDoDeltaX(1);
- startAnimation(0x86A82A11, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
- NextState(&AsScene1002VenusFlyTrap::stRingGrabbed);
-}
-
-void AsScene1002VenusFlyTrap::stRingGrabbed() {
- startAnimation(0xB5A86034, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
-}
-
-void AsScene1002VenusFlyTrap::stKlaymenInside() {
- startAnimation(0x31303094, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(NULL);
- NextState(&AsScene1002VenusFlyTrap::stKlaymenInsideMoving);
- _countdown = 24;
-}
-
-void AsScene1002VenusFlyTrap::stIdle() {
- startAnimation(0xC8204250, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::upIdle);
- SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
- if (_isSecond) {
- if (_x >= 154 && _x <= 346)
- setGlobalVar(V_FLYTRAP_POSITION_2, (_x - 186) / 32);
- else {
- NextState(&AsScene1002VenusFlyTrap::stWalkBack);
- _countdown = 12;
- }
- } else {
- if (_x >= 174 && _x <= 430)
- setGlobalVar(V_FLYTRAP_POSITION_1, (_x - 174) / 32);
- else {
- NextState(&AsScene1002VenusFlyTrap::stWalkBack);
- _countdown = 12;
- }
- }
-}
-
-void AsScene1002VenusFlyTrap::stKlaymenInsideMoving() {
- startAnimation(0x152920C4, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
- NextState(&AsScene1002VenusFlyTrap::stSpitOutKlaymen);
-}
-
-void AsScene1002VenusFlyTrap::stSpitOutKlaymen() {
- startAnimation(0x84001117, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
- NextState(&AsScene1002VenusFlyTrap::stIdle);
-}
-
-void AsScene1002VenusFlyTrap::swallowKlaymen() {
- if (_x - 15 < _klaymen->getX() && _x + 15 > _klaymen->getX()) {
- if (_isSecond)
- setDoDeltaX(_x > 265 && _x < 330 ? 1 : 0);
- else
- setDoDeltaX(_x > 320 ? 1 : 0);
- sendMessage(_klaymen, 0x2001, 0);
- startAnimation(0x8C2C80D4, 0, -1);
- SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
- SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
- NextState(&AsScene1002VenusFlyTrap::stKlaymenInside);
- }
-}
-
-AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200), _countdown(0) {
-
- createSurface(850, 186, 212);
- _x = 320;
- _y = 240;
- if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
- startAnimation(0x004A4495, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else
- setVisible(false);
- SetUpdateHandler(&AsScene1002OutsideDoorBackground::update);
- SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
-}
-
-void AsScene1002OutsideDoorBackground::update() {
- if (_countdown != 0 && (--_countdown == 0)) {
- if (_isDoorClosed)
- stCloseDoor();
- else
- stOpenDoor();
- }
- AnimatedSprite::update();
-}
-
-uint32 AsScene1002OutsideDoorBackground::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageResult) {
- case 0x4808:
- _isDoorClosed = false;
- _countdown = 2;
- break;
- case 0x4809:
- _isDoorClosed = true;
- _countdown = 2;
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1002OutsideDoorBackground::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageResult) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1002OutsideDoorBackground::stOpenDoor() {
- startAnimation(0x004A4495, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- setVisible(true);
- SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
-}
-
-void AsScene1002OutsideDoorBackground::stCloseDoor() {
- startAnimation(0x004A4495, -1, -1);
- _playBackwards = true;
- setVisible(true);
- SetMessageHandler(&AsScene1002OutsideDoorBackground::hmAnimation);
- NextState(&AsScene1002OutsideDoorBackground::stDoorClosed);
-}
-
-void AsScene1002OutsideDoorBackground::stDoorClosed() {
- setVisible(false);
- stopAnimation();
-}
-
-AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen)
- : AnimatedSprite(vm, 1200), _klaymen(klaymen) {
-
- createSurface(1200, 40, 163);
- setVisible(false);
- SetUpdateHandler(&AsScene1002KlaymenLadderHands::update);
- SetMessageHandler(&Sprite::handleMessage);
-}
-
-void AsScene1002KlaymenLadderHands::update() {
- if (_klaymen->getCurrAnimFileHash() == 0x3A292504) {
- startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1);
- _newStickFrameIndex = _klaymen->getFrameIndex();
- setVisible(true);
- _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();
- setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
- } else
- setVisible(false);
- AnimatedSprite::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);
- SetMessageHandler(&AsScene1002KlaymenPeekHand::handleMessage);
-}
-
-void AsScene1002KlaymenPeekHand::update() {
- if (_klaymen->getCurrAnimFileHash() == 0xAC20C012 && _klaymen->getFrameIndex() < 50) {
- startAnimation(0x9820C913, _klaymen->getFrameIndex(), -1);
- _newStickFrameIndex = _klaymen->getFrameIndex();
- setVisible(true);
- _x = _klaymen->getX();
- _y = _klaymen->getY();
- setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
- } else
- setVisible(false);
- AnimatedSprite::update();
-}
-
-uint32 AsScene1002KlaymenPeekHand::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x4AB28209) {
- sendMessage(_parentScene, 0x1022, 1200);
- _isClipRectSaved = true;
- _savedClipRect = _surface->getClipRect();
- setClipRect(0, 0, 640, 480);
- } else if (param.asInteger() == 0x88001184) {
- sendMessage(_parentScene, 0x1022, 1000);
- if (_isClipRectSaved)
- setClipRect(_savedClipRect);
- }
- break;
- }
- return messageResult;
-}
-
Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isKlaymenFloor(false), _isClimbingLadder(false) {
@@ -1247,7 +320,7 @@ Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which)
sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap);
_asOutsideDoorBackground = insertSprite<AsScene1002OutsideDoorBackground>();
-
+
setRectList(0x004B43A0);
loadSound(1, 0x60755842);
@@ -1324,11 +397,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);
@@ -1362,11 +435,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);
@@ -1381,70 +454,15 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam &param, Entit
setSpriteSurfacePriority(_ssCeiling, 1015);
setSpriteSurfacePriority(_ssLadderArch, 1015);
break;
- }
- return messageResult;
-}
-
-// StaticScene
-
-StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash)
- : Scene(vm, parentModule) {
-
- SetMessageHandler(&StaticScene::handleMessage);
-
- setBackground(backgroundFileHash);
- setPalette(backgroundFileHash);
- insertPuzzleMouse(cursorFileHash, 20, 620);
-}
-
-uint32 StaticScene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- Scene::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x0001:
- if (param.asPoint().x <= 20 || param.asPoint().x >= 620)
- leaveScene(0);
- break;
}
- return 0;
-}
-
-// Scene1004
-
-AsScene1004TrashCan::AsScene1004TrashCan(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- _x = 330;
- _y = 327;
- createSurface(800, 56, 50);
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1004TrashCan::handleMessage);
-}
-
-uint32 AsScene1004TrashCan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x225A8587)
- playSound(0, 0x109AFC4C);
- break;
- case 0x2002:
- startAnimation(0xEB312C11, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return 0;
+ return messageResult;
}
Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteAreaStatus(-1) {
Sprite *tempSprite;
-
+
SetUpdateHandler(&Scene1004::update);
SetMessageHandler(&Scene1004::handleMessage);
@@ -1477,16 +495,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());
@@ -1520,7 +538,7 @@ uint32 Scene1004::handleMessage(int messageNum, const MessageParam &param, Entit
break;
}
return messageResult;
-}
+}
void Scene1004::updatePaletteArea() {
if (_klaymen->getY() < 150) {
@@ -1538,8 +556,6 @@ void Scene1004::updatePaletteArea() {
}
}
-// Scene1005
-
Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
@@ -1559,7 +575,7 @@ Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which)
}
drawTextToBackground();
-
+
}
uint32 Scene1005::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1567,7 +583,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;
@@ -1616,19 +632,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))
@@ -1643,7 +659,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;
@@ -1662,7 +678,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..4b17c92b3b 100644
--- a/engines/neverhood/modules/module1000.h
+++ b/engines/neverhood/modules/module1000.h
@@ -29,8 +29,6 @@
namespace Neverhood {
-// Module1000
-
class Module1000 : public Module {
public:
Module1000(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -42,53 +40,6 @@ protected:
void updateScene();
};
-// Scene1001
-
-class AsScene1001Door : public AnimatedSprite {
-public:
- AsScene1001Door(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void hammerHitsDoor();
- void stShowIdleDoor();
- void stBustedDoorMove();
- void stBustedDoorGone();
-};
-
-class AsScene1001Hammer : public AnimatedSprite {
-public:
- AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor);
-protected:
- Sprite *_asDoor;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1001Window : public AnimatedSprite {
-public:
- AsScene1001Window(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1001Lever : public AnimatedSprite {
-public:
- AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsCommonButtonSprite : public StaticSprite {
-public:
- SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash);
-protected:
- Scene *_parentScene;
- uint32 _soundFileHash;
- int16 _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1001 : public Scene {
public:
Scene1001(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -102,136 +53,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// TODO: Move this to some common file since it's used several times
-
-class StaticScene : public Scene {
-public:
- StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-// Scene1002
-
-class AsScene1002Ring : public AnimatedSprite {
-public:
- AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow);
-protected:
- Scene *_parentScene;
- bool _isSpecial;
- void update();
- uint32 hmRingIdle(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmRingPulled1(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmRingPulled2(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmRingHangingLow(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmRingReleased(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1002Door : public StaticSprite {
-public:
- AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect);
-protected:
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suOpenDoor();
- void suCloseDoor();
-};
-
-class AsScene1002BoxingGloveHitEffect : public AnimatedSprite {
-public:
- AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1002DoorSpy : public AnimatedSprite {
-public:
- AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect);
-protected:
- Scene *_parentScene;
- Sprite *_asDoor;
- Sprite *_asBoxingGloveHitEffect;
- NRect _clipRect;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmDoorSpyAnimation(int messageNum, const MessageParam &param, Entity *sender);
- void suDoorSpy();
- void stDoorSpyIdle();
- void stDoorSpyBoxingGlove();
-};
-
-class SsCommonPressButton : public StaticSprite {
-public:
- SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
- void setFileHashes(uint32 fileHash1, uint32 fileHash2);
-protected:
- Scene *_parentScene;
- uint32 _soundFileHash;
- uint32 _fileHashes[2];
- int _status;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1002VenusFlyTrap : public AnimatedSprite {
-public:
- AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond);
-protected:
- Scene *_parentScene;
- Sprite *_klaymen;
- int _countdown;
- bool _isSecond;
- void update();
- void upIdle();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmAnimationSimple(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmAnimationExt(int messageNum, const MessageParam &param, Entity *sender);
- void stWalkBack();
- void stWalk();
- void stRelease();
- void stGrabRing();
- void stRingGrabbed();
- void stKlaymenInside();
- void stIdle();
- void stKlaymenInsideMoving();
- void stSpitOutKlaymen();
- void swallowKlaymen();
-};
-
-class AsScene1002OutsideDoorBackground : public AnimatedSprite {
-public:
- AsScene1002OutsideDoorBackground(NeverhoodEngine *vm);
-protected:
- int _countdown;
- bool _isDoorClosed;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stCloseDoor();
- void stDoorClosed();
-};
-
-class AsScene1002KlaymenLadderHands : public AnimatedSprite {
-public:
- AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen);
-protected:
- Klaymen *_klaymen;
- void update();
-};
-
-class AsScene1002KlaymenPeekHand : public AnimatedSprite {
-public:
- AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen);
-protected:
- Scene *_parentScene;
- Klaymen *_klaymen;
- bool _isClipRectSaved;
- NRect _savedClipRect;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1002 : public Scene {
public:
Scene1002(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -260,15 +81,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1004
-
-class AsScene1004TrashCan : public AnimatedSprite {
-public:
- AsScene1004TrashCan(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1004 : public Scene {
public:
Scene1004(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -281,8 +93,6 @@ protected:
void updatePaletteArea();
};
-// Scene1005
-
class Scene1005 : public Scene {
public:
Scene1005(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module1000_sprites.cpp b/engines/neverhood/modules/module1000_sprites.cpp
new file mode 100644
index 0000000000..573474de02
--- /dev/null
+++ b/engines/neverhood/modules/module1000_sprites.cpp
@@ -0,0 +1,1632 @@
+/* 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 "neverhood/modules/module1000_sprites.h"
+
+namespace Neverhood {
+
+AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ createSurface(800, 137, 242);
+ _x = 726;
+ _y = 440;
+ stShowIdleDoor();
+ loadSound(1, 0xED403E03);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1001Door::handleMessage);
+}
+
+uint32 AsScene1001Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ hammerHitsDoor();
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return 0;
+}
+
+void AsScene1001Door::hammerHitsDoor() {
+ switch (getGlobalVar(V_DOOR_STATUS)) {
+ case 0:
+ case 1:
+ playSound(0, 0x65482F03);
+ startAnimation(0x624C0498, 1, 3);
+ NextState(&AsScene1001Door::stShowIdleDoor);
+ break;
+ case 2:
+ playSound(1);
+ startAnimation(0x624C0498, 6, 6);
+ NextState(&AsScene1001Door::stBustedDoorMove);
+ break;
+ default:
+ // Nothing
+ break;
+ }
+ incGlobalVar(V_DOOR_STATUS, 1);
+}
+
+void AsScene1001Door::stShowIdleDoor() {
+ switch (getGlobalVar(V_DOOR_STATUS)) {
+ case 1:
+ startAnimation(0x624C0498, 4, -1);
+ _newStickFrameIndex = 4;
+ break;
+ case 2:
+ startAnimation(0x624C0498, 1, -1);
+ _newStickFrameIndex = 1;
+ break;
+ case 3:
+ stopAnimation();
+ setVisible(false);
+ break;
+ default:
+ startAnimation(0x624C0498, 0, -1);
+ _newStickFrameIndex = 0;
+ break;
+ }
+}
+
+void AsScene1001Door::stBustedDoorMove() {
+ setGlobalVar(V_DOOR_BUSTED, 1);
+ startAnimation(0x624C0498, 6, 6);
+ NextState(&AsScene1001Door::stBustedDoorGone);
+ _x = 30;
+}
+
+void AsScene1001Door::stBustedDoorGone() {
+ playSound(0);
+ stopAnimation();
+ setVisible(false);
+}
+
+AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor)
+ : AnimatedSprite(vm, 1100), _asDoor(asDoor) {
+
+ _x = 547;
+ _y = 206;
+ createSurface(900, 177, 192);
+ startAnimation(0x022C90D4, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1001Hammer::handleMessage);
+}
+
+uint32 AsScene1001Hammer::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x00352100)
+ sendMessage(_asDoor, 0x2000, 0);
+ else if (param.asInteger() == 0x0A1A0109)
+ playSound(0, 0x66410886);
+ break;
+ case 0x2000:
+ startAnimation(0x022C90D4, 1, -1);
+ playSound(0, 0xE741020A);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ break;
+ }
+ return 0;
+}
+
+AsScene1001Window::AsScene1001Window(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200) {
+
+ _x = 320;
+ _y = 240;
+ createSurface(100, 66, 129);
+ startAnimation(0xC68C2299, 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1001Window::handleMessage);
+}
+
+uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x0E0A1410)
+ playSound(0, 0x60803F10);
+ break;
+ case 0x2001:
+ startAnimation(0xC68C2299, 0, -1);
+ break;
+ case 0x3002:
+ SetMessageHandler(NULL);
+ setGlobalVar(V_WINDOW_OPEN, 1);
+ setVisible(false);
+ break;
+ }
+ return 0;
+}
+
+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);
+ _newStickFrameIndex = 0;
+ _x = x;
+ _y = y;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1001Lever::handleMessage);
+}
+
+uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x00C0C444)
+ sendMessage(_parentScene, 0x480F, 0);
+ else if (param.asInteger() == 0xC41A02C0)
+ playSound(0, 0x40581882);
+ break;
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x3002:
+ startAnimation(0x04A98C36, 0, -1);
+ _newStickFrameIndex = 0;
+ break;
+ case 0x480F:
+ startAnimation(0x04A98C36, 0, -1);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ 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;
+ 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) {
+ case 0x480B:
+ sendMessage(_parentScene, 0x480B, 0);
+ setVisible(true);
+ _countdown = 8;
+ playSound(0, _soundFileHash);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) {
+
+ SetUpdateHandler(&AsScene1002Ring::update);
+
+ if (_isSpecial) {
+ createSurface(990, 68, 314);
+ if (isRingLow) {
+ startAnimation(0x04103090, 0, -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
+ } else {
+ startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingIdle);
+ }
+ } else {
+ createSurface(990, 68, 138);
+ startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingIdle);
+ }
+
+ setClipRect(0, clipY1, 640, 480);
+
+ _x = x;
+ _y = y;
+
+ setDoDeltaX(_vm->_rnd->getRandomNumber(1));
+
+}
+
+void AsScene1002Ring::update() {
+ updateAnim();
+ updatePosition();
+}
+
+uint32 AsScene1002Ring::hmRingIdle(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4806:
+ setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
+ sendMessage(_parentScene, 0x4806, 0);
+ SetMessageHandler(&AsScene1002Ring::hmRingPulled1);
+ startAnimation(_isSpecial ? 0x87502558 : 0x80DD4010, 0, -1);
+ break;
+ case 0x480F:
+ setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
+ sendMessage(_parentScene, 0x480F, 0);
+ SetMessageHandler(&AsScene1002Ring::hmRingPulled2);
+ startAnimation(0x861A2020, 0, -1);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002Ring::hmRingPulled1(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ startAnimation(_isSpecial ? 0x78D0A812 : 0xB85D2A10, 0, -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
+ break;
+ case 0x4807:
+ sendMessage(_parentScene, 0x4807, 0);
+ setDoDeltaX(_vm->_rnd->getRandomNumber(1));
+ startAnimation(0x8258A030, 0, -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingReleased);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002Ring::hmRingPulled2(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ startAnimation(0x04103090, 0, -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002Ring::hmRingHangingLow(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4807:
+ sendMessage(_parentScene, 0x4807, 0);
+ setDoDeltaX(_vm->_rnd->getRandomNumber(1));
+ startAnimation(0x8258A030, 0, -1);
+ SetMessageHandler(&AsScene1002Ring::hmRingReleased);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmRingIdle(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x05410F72)
+ playSound(0, 0x21EE40A9);
+ break;
+ case 0x3002:
+ startAnimation(0xA85C4011, 0, -1);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+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);
+ SetMessageHandler(&AsScene1002Door::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsScene1002Door::update() {
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 AsScene1002Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4808:
+ setGlobalVar(V_FLYTRAP_RING_DOOR, 1);
+ SetSpriteUpdate(&AsScene1002Door::suOpenDoor);
+ break;
+ case 0x4809:
+ setGlobalVar(V_FLYTRAP_RING_DOOR, 0);
+ SetSpriteUpdate(&AsScene1002Door::suCloseDoor);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1002Door::suOpenDoor() {
+ if (_y > 49) {
+ _y -= 8;
+ if (_y < 49) {
+ SetSpriteUpdate(NULL);
+ _y = 49;
+ }
+ _needRefresh = true;
+ }
+}
+
+void AsScene1002Door::suCloseDoor() {
+ if (_y < 239) {
+ _y += 8;
+ if (_y > 239) {
+ SetSpriteUpdate(NULL);
+ _y = 239;
+ }
+ _needRefresh = true;
+ }
+}
+
+AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1400) {
+
+ createSurface(1025, 88, 165);
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage);
+}
+
+uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2004:
+ _x = ((Sprite*)sender)->getX() - 98;
+ _y = ((Sprite*)sender)->getY() - 111;
+ startAnimation(0x0422255A, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1002DoorSpy::AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect)
+ : AnimatedSprite(vm, 1300), _clipRect(clipRect), _parentScene(parentScene), _asDoor(asDoor), _asBoxingGloveHitEffect(asScene1002BoxingGloveHitEffect) {
+
+ createSurface(800, 136, 147);
+ setClipRect(clipRect);
+ suDoorSpy();
+ loadSound(0, 0xC0C40298);
+ startAnimation(0x586C1D48, 0, 0);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
+ SetSpriteUpdate(&AsScene1002DoorSpy::suDoorSpy);
+}
+
+uint32 AsScene1002DoorSpy::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0xA61CA1C2)
+ sendMessage(_asBoxingGloveHitEffect, 0x2004, 0);
+ else if (param.asInteger() == 0x14CE0620)
+ playSound(0);
+ break;
+ case 0x2003:
+ stDoorSpyBoxingGlove();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002DoorSpy::hmDoorSpyAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1002DoorSpy::suDoorSpy() {
+ _x = _asDoor->getX() + 34;
+ _y = _asDoor->getY() + 175;
+}
+
+void AsScene1002DoorSpy::stDoorSpyIdle() {
+ setClipRect(_clipRect);
+ _parentScene->setSurfacePriority(getSurface(), 800);
+ startAnimation(0x586C1D48, 0, 0);
+ SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
+}
+
+void AsScene1002DoorSpy::stDoorSpyBoxingGlove() {
+ setClipRect(0, 0, 640, 480);
+ _parentScene->setSurfacePriority(getSurface(), 1200);
+ startAnimation(0x586C1D48, 1, -1);
+ SetMessageHandler(&AsScene1002DoorSpy::hmDoorSpyAnimation);
+ NextState(&AsScene1002DoorSpy::stDoorSpyIdle);
+}
+
+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;
+ _fileHashes[0] = fileHash1;
+ _fileHashes[1] = fileHash2;
+ createSurface(surfacePriority, 40, 40);
+ loadSprite(fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+ setVisible(false);
+ SetUpdateHandler(&SsCommonPressButton::update);
+ SetMessageHandler(&SsCommonPressButton::handleMessage);
+}
+
+void SsCommonPressButton::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
+ _fileHashes[0] = fileHash1;
+ _fileHashes[1] = fileHash2;
+ loadSprite(_status == 2 ? fileHash2 : fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+}
+
+void SsCommonPressButton::update() {
+ if (_countdown != 0 && (--_countdown) == 0) {
+ if (_status == 1) {
+ _status = 2;
+ loadSprite(_fileHashes[1], kSLFDefDrawOffset | kSLFDefPosition);
+ _countdown = 4;
+ } else if (_status == 2) {
+ _status = 3;
+ loadSprite(_fileHashes[0], kSLFDefDrawOffset | kSLFDefPosition);
+ _countdown = 4;
+ } else if (_status == 3) {
+ _status = 0;
+ setVisible(false);
+ }
+ }
+}
+
+uint32 SsCommonPressButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x480B:
+ sendMessage(_parentScene, 0x480B, 0);
+ _status = 1;
+ _countdown = 4;
+ setVisible(true);
+ playSound(0, _soundFileHash);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _isSecond(isSecond), _countdown(0) {
+
+ createSurface(995, 175, 195);
+ if (!_isSecond) {
+ if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
+ setDoDeltaX(1);
+ _x = 366;
+ _y = 435;
+ stRingGrabbed();
+ } else {
+ _x = 174 + getGlobalVar(V_FLYTRAP_POSITION_1) * 32;
+ _y = 435;
+ stIdle();
+ }
+ } else {
+ _x = 186 + getGlobalVar(V_FLYTRAP_POSITION_2) * 32;
+ _y = 364;
+ if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) {
+ stRingGrabbed();
+ } else {
+ stIdle();
+ }
+ }
+ _flags = 4;
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+}
+
+void AsScene1002VenusFlyTrap::update() {
+ if (_countdown != 0 && (--_countdown == 0))
+ gotoNextState();
+ AnimatedSprite::update();
+}
+
+void AsScene1002VenusFlyTrap::upIdle() {
+ if (_countdown == 0 && _klaymen->getX() - 20 > _x)
+ setDoDeltaX(1);
+ else if (_klaymen->getX() + 20 < _x)
+ setDoDeltaX(0);
+ update();
+}
+
+uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x000890C4)
+ playSound(0, 0xC21190D8);
+ else if (param.asInteger() == 0x522200A0)
+ playSound(0, 0x931080C8);
+ break;
+ case 0x1011:
+ if (_isSecond) {
+ if (_x >= 154 && _x <= 346) {
+ sendMessage(_parentScene, 0x2000, 0);
+ messageResult = 1;
+ }
+ } else {
+ if (_x >= 174 && _x <= 430) {
+ sendMessage(_parentScene, 0x2000, 0);
+ messageResult = 1;
+ }
+ }
+ break;
+ case 0x480B:
+ setDoDeltaX(param.asInteger() != 0 ? 1 : 0);
+ if (!_isSecond) {
+ if (getGlobalVar(V_FLYTRAP_RING_DOOR))
+ stRelease();
+ else
+ stWalk();
+ } else {
+ if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE))
+ stRelease();
+ else
+ stWalk();
+ }
+ break;
+ case 0x480C:
+ if (_isSecond) {
+ if (_x >= 154 && _x <= 346)
+ messageResult = 1;
+ else
+ messageResult = 0;
+ } else {
+ if (_x >= 174 && _x <= 430)
+ messageResult = 1;
+ else
+ messageResult = 0;
+ }
+ break;
+ case 0x480E:
+ if (param.asInteger() == 1)
+ stGrabRing();
+ break;
+ case 0x4810:
+ swallowKlaymen();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 995);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1015);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002VenusFlyTrap::hmAnimationSimple(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x000890C4)
+ playSound(0, 0xC21190D8);
+ else if (param.asInteger() == 0x41881801) {
+ if (_isSecond) {
+ if (_x > 330)
+ sendMessage(_klaymen, 0x4811, 2);
+ else
+ sendMessage(_klaymen, 0x4811, 0);
+ } else {
+ sendMessage(_klaymen, 0x4811, 0);
+ }
+ } else if (param.asInteger() == 0x522200A0)
+ playSound(0, 0x931080C8);
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 995);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1015);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1002VenusFlyTrap::stWalkBack() {
+ setDoDeltaX(2);
+ startAnimation(0xC4080034, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
+ NextState(&AsScene1002VenusFlyTrap::stIdle);
+}
+
+void AsScene1002VenusFlyTrap::stWalk() {
+ startAnimation(0xC4080034, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
+ NextState(&AsScene1002VenusFlyTrap::stIdle);
+}
+
+void AsScene1002VenusFlyTrap::stRelease() {
+ sendMessage(_parentScene, 0x4807, 0);
+ startAnimation(0x82292851, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
+ NextState(&AsScene1002VenusFlyTrap::stIdle);
+}
+
+void AsScene1002VenusFlyTrap::stGrabRing() {
+ setDoDeltaX(1);
+ startAnimation(0x86A82A11, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
+ NextState(&AsScene1002VenusFlyTrap::stRingGrabbed);
+}
+
+void AsScene1002VenusFlyTrap::stRingGrabbed() {
+ startAnimation(0xB5A86034, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
+}
+
+void AsScene1002VenusFlyTrap::stKlaymenInside() {
+ startAnimation(0x31303094, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(NULL);
+ NextState(&AsScene1002VenusFlyTrap::stKlaymenInsideMoving);
+ _countdown = 24;
+}
+
+void AsScene1002VenusFlyTrap::stIdle() {
+ startAnimation(0xC8204250, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::upIdle);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
+ if (_isSecond) {
+ if (_x >= 154 && _x <= 346)
+ setGlobalVar(V_FLYTRAP_POSITION_2, (_x - 186) / 32);
+ else {
+ NextState(&AsScene1002VenusFlyTrap::stWalkBack);
+ _countdown = 12;
+ }
+ } else {
+ if (_x >= 174 && _x <= 430)
+ setGlobalVar(V_FLYTRAP_POSITION_1, (_x - 174) / 32);
+ else {
+ NextState(&AsScene1002VenusFlyTrap::stWalkBack);
+ _countdown = 12;
+ }
+ }
+}
+
+void AsScene1002VenusFlyTrap::stKlaymenInsideMoving() {
+ startAnimation(0x152920C4, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
+ NextState(&AsScene1002VenusFlyTrap::stSpitOutKlaymen);
+}
+
+void AsScene1002VenusFlyTrap::stSpitOutKlaymen() {
+ startAnimation(0x84001117, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
+ NextState(&AsScene1002VenusFlyTrap::stIdle);
+}
+
+void AsScene1002VenusFlyTrap::swallowKlaymen() {
+ if (_x - 15 < _klaymen->getX() && _x + 15 > _klaymen->getX()) {
+ if (_isSecond)
+ setDoDeltaX(_x > 265 && _x < 330 ? 1 : 0);
+ else
+ setDoDeltaX(_x > 320 ? 1 : 0);
+ sendMessage(_klaymen, 0x2001, 0);
+ startAnimation(0x8C2C80D4, 0, -1);
+ SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
+ SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
+ NextState(&AsScene1002VenusFlyTrap::stKlaymenInside);
+ }
+}
+
+AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200), _countdown(0), _isDoorClosed(true) {
+
+ createSurface(850, 186, 212);
+ _x = 320;
+ _y = 240;
+ if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
+ startAnimation(0x004A4495, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else
+ setVisible(false);
+ SetUpdateHandler(&AsScene1002OutsideDoorBackground::update);
+ SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
+}
+
+void AsScene1002OutsideDoorBackground::update() {
+ if (_countdown != 0 && (--_countdown == 0)) {
+ if (_isDoorClosed)
+ stCloseDoor();
+ else
+ stOpenDoor();
+ }
+ AnimatedSprite::update();
+}
+
+uint32 AsScene1002OutsideDoorBackground::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageResult) {
+ case 0x4808:
+ _isDoorClosed = false;
+ _countdown = 2;
+ break;
+ case 0x4809:
+ _isDoorClosed = true;
+ _countdown = 2;
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002OutsideDoorBackground::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageResult) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1002OutsideDoorBackground::stOpenDoor() {
+ startAnimation(0x004A4495, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ setVisible(true);
+ SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
+}
+
+void AsScene1002OutsideDoorBackground::stCloseDoor() {
+ startAnimation(0x004A4495, -1, -1);
+ _playBackwards = true;
+ setVisible(true);
+ SetMessageHandler(&AsScene1002OutsideDoorBackground::hmAnimation);
+ NextState(&AsScene1002OutsideDoorBackground::stDoorClosed);
+}
+
+void AsScene1002OutsideDoorBackground::stDoorClosed() {
+ setVisible(false);
+ stopAnimation();
+}
+
+AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen)
+ : AnimatedSprite(vm, 1200), _klaymen(klaymen) {
+
+ createSurface(1200, 40, 163);
+ setVisible(false);
+ SetUpdateHandler(&AsScene1002KlaymenLadderHands::update);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+void AsScene1002KlaymenLadderHands::update() {
+ if (_klaymen->getCurrAnimFileHash() == 0x3A292504) {
+ startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1);
+ _newStickFrameIndex = _klaymen->getFrameIndex();
+ setVisible(true);
+ _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();
+ setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
+ } else
+ setVisible(false);
+ AnimatedSprite::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);
+ SetMessageHandler(&AsScene1002KlaymenPeekHand::handleMessage);
+}
+
+void AsScene1002KlaymenPeekHand::update() {
+ if (_klaymen->getCurrAnimFileHash() == 0xAC20C012 && _klaymen->getFrameIndex() < 50) {
+ startAnimation(0x9820C913, _klaymen->getFrameIndex(), -1);
+ _newStickFrameIndex = _klaymen->getFrameIndex();
+ setVisible(true);
+ _x = _klaymen->getX();
+ _y = _klaymen->getY();
+ setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
+ } else
+ setVisible(false);
+ AnimatedSprite::update();
+}
+
+uint32 AsScene1002KlaymenPeekHand::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_parentScene, 0x1022, 1200);
+ _isClipRectSaved = true;
+ _savedClipRect = _surface->getClipRect();
+ setClipRect(0, 0, 640, 480);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_parentScene, 0x1022, 1000);
+ if (_isClipRectSaved)
+ setClipRect(_savedClipRect);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1004TrashCan::AsScene1004TrashCan(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ _x = 330;
+ _y = 327;
+ createSurface(800, 56, 50);
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1004TrashCan::handleMessage);
+}
+
+uint32 AsScene1004TrashCan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x225A8587)
+ playSound(0, 0x109AFC4C);
+ break;
+ case 0x2002:
+ startAnimation(0xEB312C11, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return 0;
+}
+
+static const KlaymenIdleTableItem klaymenIdleTable1002[] = {
+ {1, kIdlePickEar},
+ {2, kIdleWonderAbout}
+};
+
+KmScene1001::KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+}
+
+uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() == 2)
+ GotoState(&KmScene1001::stSleeping);
+ break;
+ case 0x480D:
+ GotoState(&KmScene1001::stPullHammerLever);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4836:
+ if (param.asInteger() == 1) {
+ sendMessage(_parentScene, 0x2002, 0);
+ GotoState(&KmScene1001::stWakeUp);
+ }
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+void KmScene1001::stWakeUp() {
+ _busyStatus = 1;
+ _acceptInput = false;
+ startAnimation(0x527AC970, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&Klaymen::hmLowLevelAnimation);
+ SetSpriteUpdate(NULL);
+}
+
+void KmScene1001::stSleeping() {
+ _busyStatus = 0;
+ _acceptInput = true;
+ startAnimation(0x5A38C110, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1001::hmSleeping);
+ SetSpriteUpdate(NULL);
+}
+
+uint32 KmScene1001::hmSleeping(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevel(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x03060012) {
+ playSound(0, 0xC0238244);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1001::stPullHammerLever() {
+ if (!stStartAction(AnimationCallback(&KmScene1001::stPullHammerLever))) {
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0x00648953, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1001::hmPullHammerLever);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ }
+}
+
+uint32 KmScene1001::hmPullHammerLever(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Klaymen::hmLever(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x4AB28209)
+ sendMessage(_attachedSprite, 0x480F, 0);
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1002::KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ setKlaymenIdleTable1();
+}
+
+void KmScene1002::xUpdate() {
+ if (_x >= 250 && _x <= 435 && _y >= 420) {
+ if (_idleTableNum == 0) {
+ setKlaymenIdleTable(klaymenIdleTable1002, ARRAYSIZE(klaymenIdleTable1002));
+ _idleTableNum = 1;
+ }
+ } else if (_idleTableNum == 1) {
+ setKlaymenIdleTable1();
+ _idleTableNum = 0;
+ }
+}
+
+uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x2001:
+ GotoState(&Klaymen::stStandIdleSpecial);
+ break;
+ case 0x2007:
+ _otherSprite = (Sprite*)param.asEntity();
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4803:
+ if (param.asInteger() == 1)
+ GotoState(&KmScene1002::stJumpAndFall);
+ else if (param.asInteger() == 2)
+ GotoState(&KmScene1002::stDropFromRing);
+ break;
+ case 0x4804:
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4805:
+ switch (param.asInteger()) {
+ case 1:
+ GotoState(&KmScene1002::stJumpToRing1);
+ break;
+ case 2:
+ GotoState(&KmScene1002::stJumpToRing2);
+ break;
+ case 3:
+ GotoState(&KmScene1002::stJumpToRing3);
+ break;
+ case 4:
+ GotoState(&KmScene1002::stJumpToRing4);
+ break;
+ }
+ break;
+ case 0x480A:
+ GotoState(&KmScene1002::stMoveVenusFlyTrap);
+ break;
+ case 0x480D:
+ GotoState(&KmScene1002::stJumpToRingVenusFlyTrap);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&KmScene1002::stPressDoorButton);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ startWalkToAttachedSpriteXDistance(param.asInteger());
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2005, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2005, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2005, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2006, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+void KmScene1002::setupJumpToRing() {
+ _acceptInput = false;
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmJumpToRing);
+ SetSpriteUpdate(&Klaymen::suUpdateDestX);
+ NextState(&KmScene1002::stHangOnRing);
+ sendMessage(_attachedSprite, 0x482B, 0);
+}
+
+uint32 KmScene1002::hmJumpToRing(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x168050A0) {
+ sendMessage(_attachedSprite, 0x4806, 0);
+ _acceptInput = true;
+ } else if (param.asInteger() == 0x320AC306) {
+ playSound(0, 0x5860C640);
+ } else if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_attachedSprite, 0x482A, 0);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_attachedSprite, 0x482B, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1002::stHangOnRing() {
+ _busyStatus = 0;
+ _acceptInput = true;
+ startAnimation(0x4829E0B8, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&Klaymen::hmLowLevel);
+ SetSpriteUpdate(NULL);
+}
+
+void KmScene1002::stJumpToRing1() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing1))) {
+ _busyStatus = 0;
+ startAnimation(0xD82890BA, 0, -1);
+ setupJumpToRing();
+ }
+}
+
+void KmScene1002::stJumpToRing2() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing2))) {
+ _busyStatus = 0;
+ startAnimation(0x900980B2, 0, -1);
+ setupJumpToRing();
+ }
+}
+
+void KmScene1002::stJumpToRing3() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing3))) {
+ _busyStatus = 0;
+ _acceptInput = false;
+ startAnimation(0xBA1910B2, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetSpriteUpdate(&Klaymen::suUpdateDestX);
+ SetMessageHandler(&KmScene1002::hmJumpToRing3);
+ NextState(&KmScene1002::stHoldRing3);
+ sendMessage(_attachedSprite, 0x482B, 0);
+ }
+}
+
+uint32 KmScene1002::hmJumpToRing3(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x168050A0) {
+ sendMessage(_attachedSprite, 0x4806, 0);
+ } else if (param.asInteger() == 0x320AC306) {
+ playSound(0, 0x5860C640);
+ } else if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_attachedSprite, 0x482A, 0);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_attachedSprite, 0x482B, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1002::stHoldRing3() {
+ _busyStatus = 0;
+ _acceptInput = true;
+ startAnimation(0x4A293FB0, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmHoldRing3);
+ SetSpriteUpdate(NULL);
+}
+
+uint32 KmScene1002::hmHoldRing3(int messageNum, const MessageParam &param, Entity *sender) {
+ if (messageNum == 0x1008) {
+ stReleaseRing();
+ return 0;
+ }
+ return hmLowLevel(messageNum, param, sender);
+}
+
+void KmScene1002::stJumpToRing4() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing4))) {
+ _busyStatus = 0;
+ startAnimation(0xB8699832, 0, -1);
+ setupJumpToRing();
+ }
+}
+
+void KmScene1002::stJumpToRingVenusFlyTrap() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRingVenusFlyTrap))) {
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0x584984B4, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmJumpToRingVenusFlyTrap);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ NextState(&KmScene1002::stLandOnFeet);
+ sendMessage(_attachedSprite, 0x482B, 0);
+ }
+}
+
+uint32 KmScene1002::hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x168050A0) {
+ sendMessage(_attachedSprite, 0x480F, 0);
+ } else if (param.asInteger() == 0x586B0300) {
+ sendMessage(_otherSprite, 0x480E, 1);
+ } else if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_attachedSprite, 0x482A, 0);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_attachedSprite, 0x482B, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1002::stJumpAndFall() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stJumpAndFall))) {
+ sendMessage(_parentScene, 0x1024, 3);
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0xB93AB151, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmJumpAndFall);
+ SetSpriteUpdate(&Klaymen::suFallDown);
+ NextState(&KmScene1002::stLandOnFeet);
+ }
+}
+
+void KmScene1002::stDropFromRing() {
+ if (_attachedSprite) {
+ _x = _attachedSprite->getX();
+ sendMessage(_attachedSprite, 0x4807, 0);
+ _attachedSprite = NULL;
+ }
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0x586984B1, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&Klaymen::hmLowLevel);
+ SetSpriteUpdate(&Klaymen::suFallDown);
+ NextState(&KmScene1002::stLandOnFeet);
+}
+
+uint32 KmScene1002::hmJumpAndFall(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevel(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x1307050A) {
+ playSound(0, 0x40428A09);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1002::stMoveVenusFlyTrap() {
+ if (!stStartAction(AnimationCallback(&KmScene1002::stMoveVenusFlyTrap))) {
+ _busyStatus = 2;
+ _isMoveObjectRequested = false;
+ _acceptInput = true;
+ setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
+ startAnimation(0x5C01A870, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmMoveVenusFlyTrap);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ FinalizeState(&KmScene1002::evMoveVenusFlyTrapDone);
+ }
+}
+
+void KmScene1002::stContinueMovingVenusFlyTrap() {
+ _isMoveObjectRequested = false;
+ _acceptInput = true;
+ startAnimationByHash(0x5C01A870, 0x01084280, 0);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmMoveVenusFlyTrap);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ FinalizeState(&KmScene1002::evMoveVenusFlyTrapDone);
+}
+
+void KmScene1002::evMoveVenusFlyTrapDone() {
+ sendMessage(_attachedSprite, 0x482A, 0);
+}
+
+uint32 KmScene1002::hmMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x01084280) {
+ sendMessage(_attachedSprite, 0x480B, (uint32)_doDeltaX);
+ } else if (param.asInteger() == 0x02421405) {
+ if (_isMoveObjectRequested) {
+ if (sendMessage(_attachedSprite, 0x480C, (uint32)_doDeltaX) != 0)
+ stContinueMovingVenusFlyTrap();
+ } else {
+ SetMessageHandler(&KmScene1002::hmFirstMoveVenusFlyTrap);
+ }
+ } else if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_attachedSprite, 0x482A, 0);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_attachedSprite, 0x482B, 0);
+ } else if (param.asInteger() == 0x32180101) {
+ playSound(0, 0x405002D8);
+ } else if (param.asInteger() == 0x0A2A9098) {
+ playSound(0, 0x0460E2FA);
+ }
+ break;
+ case 0x480A:
+ _isMoveObjectRequested = true;
+ return 0;
+ }
+ return hmLowLevelAnimation(messageNum, param, sender);
+}
+
+uint32 KmScene1002::hmFirstMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x4AB28209) {
+ sendMessage(_attachedSprite, 0x482A, 0);
+ } else if (param.asInteger() == 0x88001184) {
+ sendMessage(_attachedSprite, 0x482B, 0);
+ } else if (param.asInteger() == 0x32180101) {
+ playSound(0, 0x405002D8);
+ } else if (param.asInteger() == 0x0A2A9098) {
+ playSound(0, 0x0460E2FA);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1002::stPressDoorButton() {
+ _busyStatus = 2;
+ _acceptInput = true;
+ setDoDeltaX(0);
+ startAnimation(0x1CD89029, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmPressDoorButton);
+ SetSpriteUpdate(&Klaymen::suAction);
+}
+
+void KmScene1002::stHitByBoxingGlove() {
+ _busyStatus = 1;
+ _acceptInput = false;
+ startAnimation(0x35AA8059, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1002::hmHitByBoxingGlove);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ FinalizeState(&KmScene1002::evHitByBoxingGloveDone);
+}
+
+void KmScene1002::evHitByBoxingGloveDone() {
+ sendMessage(_parentScene, 0x1024, 1);
+}
+
+uint32 KmScene1002::hmPressDoorButton(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x942D2081) {
+ _acceptInput = false;
+ sendMessage(_attachedSprite, 0x2003, 0);
+ } else if (param.asInteger() == 0xDA600012) {
+ stHitByBoxingGlove();
+ } else if (param.asInteger() == 0x0D01B294) {
+ _acceptInput = false;
+ sendMessage(_attachedSprite, 0x480B, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+uint32 KmScene1002::hmHitByBoxingGlove(int messageNum, const MessageParam &param, Entity *sender) {
+ int16 speedUpFrameIndex;
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1008:
+ speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
+ if (_currFrameIndex < speedUpFrameIndex) {
+ startAnimation(0x35AA8059, speedUpFrameIndex, -1);
+ _y = 435;
+ }
+ messageResult = 0;
+ break;
+ case 0x100D:
+ if (param.asInteger() == 0x1A1A0785) {
+ playSound(0, 0x40F0A342);
+ } else if (param.asInteger() == 0x60428026) {
+ playSound(0, 0x40608A59);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1004::KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ _dataResource.load(0x01900A04);
+}
+
+uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x481E:
+ GotoState(&KmScene1004::stReadNote);
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2000, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2001, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x4824:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = _dataResource.getPoint(param.asInteger()).y;
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4825:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = _dataResource.getPoint(param.asInteger()).y;
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4828:
+ GotoState(&Klaymen::stTurnToBackToUse);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+uint32 KmScene1004::hmReadNote(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x04684052) {
+ _acceptInput = true;
+ sendMessage(_parentScene, 0x2002, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1004::stReadNote() {
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0x123E9C9F, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1004::hmReadNote);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1000_sprites.h b/engines/neverhood/modules/module1000_sprites.h
new file mode 100644
index 0000000000..564b3cc335
--- /dev/null
+++ b/engines/neverhood/modules/module1000_sprites.h
@@ -0,0 +1,262 @@
+/* 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 NEVERHOOD_MODULES_MODULE1000_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1000_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsScene1001Door : public AnimatedSprite {
+public:
+ AsScene1001Door(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void hammerHitsDoor();
+ void stShowIdleDoor();
+ void stBustedDoorMove();
+ void stBustedDoorGone();
+};
+
+class AsScene1001Hammer : public AnimatedSprite {
+public:
+ AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor);
+protected:
+ Sprite *_asDoor;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1001Window : public AnimatedSprite {
+public:
+ AsScene1001Window(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1001Lever : public AnimatedSprite {
+public:
+ AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsCommonButtonSprite : public StaticSprite {
+public:
+ SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash);
+protected:
+ Scene *_parentScene;
+ uint32 _soundFileHash;
+ int16 _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1002Ring : public AnimatedSprite {
+public:
+ AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow);
+protected:
+ Scene *_parentScene;
+ bool _isSpecial;
+ void update();
+ uint32 hmRingIdle(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmRingPulled1(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmRingPulled2(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmRingHangingLow(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmRingReleased(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1002Door : public StaticSprite {
+public:
+ AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect);
+protected:
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suOpenDoor();
+ void suCloseDoor();
+};
+
+class AsScene1002BoxingGloveHitEffect : public AnimatedSprite {
+public:
+ AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1002DoorSpy : public AnimatedSprite {
+public:
+ AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect);
+protected:
+ Scene *_parentScene;
+ Sprite *_asDoor;
+ Sprite *_asBoxingGloveHitEffect;
+ NRect _clipRect;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmDoorSpyAnimation(int messageNum, const MessageParam &param, Entity *sender);
+ void suDoorSpy();
+ void stDoorSpyIdle();
+ void stDoorSpyBoxingGlove();
+};
+
+class SsCommonPressButton : public StaticSprite {
+public:
+ SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
+ void setFileHashes(uint32 fileHash1, uint32 fileHash2);
+protected:
+ Scene *_parentScene;
+ uint32 _soundFileHash;
+ uint32 _fileHashes[2];
+ int _status;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1002VenusFlyTrap : public AnimatedSprite {
+public:
+ AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond);
+protected:
+ Scene *_parentScene;
+ Sprite *_klaymen;
+ int _countdown;
+ bool _isSecond;
+ void update();
+ void upIdle();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmAnimationSimple(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmAnimationExt(int messageNum, const MessageParam &param, Entity *sender);
+ void stWalkBack();
+ void stWalk();
+ void stRelease();
+ void stGrabRing();
+ void stRingGrabbed();
+ void stKlaymenInside();
+ void stIdle();
+ void stKlaymenInsideMoving();
+ void stSpitOutKlaymen();
+ void swallowKlaymen();
+};
+
+class AsScene1002OutsideDoorBackground : public AnimatedSprite {
+public:
+ AsScene1002OutsideDoorBackground(NeverhoodEngine *vm);
+protected:
+ int _countdown;
+ bool _isDoorClosed;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stCloseDoor();
+ void stDoorClosed();
+};
+
+class AsScene1002KlaymenLadderHands : public AnimatedSprite {
+public:
+ AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen);
+protected:
+ Klaymen *_klaymen;
+ void update();
+};
+
+class AsScene1002KlaymenPeekHand : public AnimatedSprite {
+public:
+ AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen);
+protected:
+ Scene *_parentScene;
+ Klaymen *_klaymen;
+ bool _isClipRectSaved;
+ NRect _savedClipRect;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1004TrashCan : public AnimatedSprite {
+public:
+ AsScene1004TrashCan(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1001 : public Klaymen {
+public:
+ KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stWakeUp();
+ void stSleeping();
+ void stPullHammerLever();
+ uint32 hmSleeping(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmPullHammerLever(int messageNum, const MessageParam &param, Entity *sender);
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1002 : public Klaymen {
+public:
+ KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stJumpToRing1();
+ void stJumpToRing2();
+ void stJumpToRing3();
+ void stJumpToRing4();
+ void setupJumpToRing();
+ void stHangOnRing();
+ void stHoldRing3();
+ void stDropFromRing();
+ void stJumpToRingVenusFlyTrap();
+ void stJumpAndFall();
+ void stMoveVenusFlyTrap();
+ void stContinueMovingVenusFlyTrap();
+ void evMoveVenusFlyTrapDone();
+ void stPressDoorButton();
+ void stHitByBoxingGlove();
+ void evHitByBoxingGloveDone();
+
+ uint32 hmJumpToRing(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmJumpToRing3(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmHoldRing3(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmJumpAndFall(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmFirstMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmPressDoorButton(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmHitByBoxingGlove(int messageNum, const MessageParam &param, Entity *sender);
+
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1004 : public Klaymen {
+public:
+ KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stReadNote();
+ uint32 hmReadNote(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1000_SPRITES_H */
diff --git a/engines/neverhood/modules/module1100.cpp b/engines/neverhood/modules/module1100.cpp
index 5a5e52e5b0..af2df2e742 100644
--- a/engines/neverhood/modules/module1100.cpp
+++ b/engines/neverhood/modules/module1100.cpp
@@ -20,9 +20,10 @@
*
*/
-#include "neverhood/modules/module1100.h"
#include "neverhood/gamemodule.h"
#include "neverhood/navigationscene.h"
+#include "neverhood/modules/module1100.h"
+#include "neverhood/modules/module1100_sprites.h"
namespace Neverhood {
@@ -40,7 +41,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) {
@@ -64,7 +65,8 @@ Module1100::~Module1100() {
void Module1100::createScene(int sceneNum, int which) {
static const uint32 kSmackerFileHashList06[] = {0x10880805, 0x1088081D, 0};
static const uint32 kSmackerFileHashList07[] = {0x00290321, 0x01881000, 0};
- debug("Module1100::createScene(%d, %d)", sceneNum, which);
+ static const byte kNavigationTypes02[] = {1, 0, 4, 1};
+ debug(1, "Module1100::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -80,9 +82,9 @@ void Module1100::createScene(int sceneNum, int which) {
case 2:
_vm->gameState().sceneNum = 2;
if (getGlobalVar(V_ROBOT_TARGET)) {
- createNavigationScene(0x004B84F0, which);
+ createNavigationScene(0x004B84F0, which, kNavigationTypes02);
} else {
- createNavigationScene(0x004B8490, which);
+ createNavigationScene(0x004B8490, which, kNavigationTypes02);
}
break;
case 3:
@@ -235,6 +237,13 @@ void Module1100::updateScene() {
}
}
+static const uint32 kScene1105BackgroundFileHashes[] = {
+ 0x20018662,
+ 0x20014202,
+ 0x20012202,
+ 0x20010002 // CHECKME: This used ??
+};
+
static const uint32 kScene1105FileHashes[] = {
0x00028006,
0x0100A425,
@@ -248,209 +257,29 @@ static const uint32 kScene1105FileHashes[] = {
0xB14A891E
};
-static const uint32 kScene1105BackgroundFileHashes[] = {
- 0x20018662,
- 0x20014202,
- 0x20012202,
- 0x20010002 // CHECKME: This used ??
-};
-
-static const uint32 kSsScene1105SymbolDieFileHashes[] = {
- 0,
- 0x90898414,
- 0x91098414,
- 0x92098414,
- 0x94098414,
- 0x98098414,
- 0x80098414,
- 0xB0098414,
- 0xD0098414,
- 0x10098414
-};
-
-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);
- setVisible(false);
-}
-
-void SsScene1105Button::update() {
- if (_countdown != 0 && (--_countdown == 0)) {
- sendMessage(_parentScene, 0x4807, 0);
- setVisible(false);
- }
-}
-
-uint32 SsScene1105Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0) {
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- }
- break;
- case 0x480B:
- _countdown = 8;
- setVisible(true);
- playSound(0, 0x44141000);
- break;
- }
- return messageResult;
-}
-
-SsScene1105Symbol::SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y)
- : StaticSprite(vm, 0) {
-
- loadSprite(fileHash, kSLFCenteredDrawOffset | kSLFSetPosition, 200, x, y);
-}
-
-void SsScene1105Symbol::hide() {
- setVisible(false);
- _needRefresh = true;
- updatePosition();
-}
-
-SsScene1105SymbolDie::SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y)
- : StaticSprite(vm, 1100), _dieIndex(dieIndex) {
-
- _x = x;
- _y = y;
- createSurface(200, 50, 50);
- loadSymbolSprite();
- SetMessageHandler(&SsScene1105SymbolDie::handleMessage);
-}
-
-uint32 SsScene1105SymbolDie::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- loadSymbolSprite();
- break;
- }
- return messageResult;
-}
-
-void SsScene1105SymbolDie::loadSymbolSprite() {
- loadSprite(kSsScene1105SymbolDieFileHashes[getSubVar(VA_CURR_DICE_NUMBERS, _dieIndex)], kSLFCenteredDrawOffset);
-}
-
-void SsScene1105SymbolDie::hide() {
- setVisible(false);
- _needRefresh = true;
- updatePosition();
-}
-
-AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- createSurface(100, 556, 328);
- _x = 320;
- _y = 240;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1105TeddyBear::handleMessage);
- startAnimation(0x65084002, 0, -1);
- _newStickFrameIndex = 0;
- setVisible(false);
- _needRefresh = true;
- updatePosition();
- loadSound(0, 0xCE840261);
- loadSound(1, 0xCCA41A62);
-}
-
-uint32 AsScene1105TeddyBear::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2002:
- if (getGlobalVar(V_ROBOT_TARGET)) {
- startAnimation(0x6B0C0432, 0, -1);
- playSound(0);
- } else {
- startAnimation(0x65084002, 0, -1);
- playSound(1);
- }
- break;
- case 0x3002:
- sendMessage(_parentScene, 0x2003, 0);
- stopAnimation();
- break;
- }
- return messageResult;
-}
-
-void AsScene1105TeddyBear::show() {
- setVisible(true);
- _needRefresh = true;
- updatePosition();
-}
-
-void AsScene1105TeddyBear::hide() {
- setVisible(false);
- _needRefresh = true;
- updatePosition();
-}
-
-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);
- SetUpdateHandler(&SsScene1105OpenButton::update);
- SetMessageHandler(&SsScene1105OpenButton::handleMessage);
-}
-
-void SsScene1105OpenButton::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0)) {
- setVisible(false);
- sendMessage(_parentScene, 0x2001, 0);
- }
-}
-
-uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = 0;
- Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0 && !_isClicked) {
- playSound(0);
- setVisible(true);
- _isClicked = true;
- _countdown = 4;
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
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) {
@@ -465,7 +294,7 @@ uint32 Scene1105::handleMessage(int messageNum, const MessageParam &param, Entit
_backgroundIndex = 15;
SetUpdateHandler(&Scene1105::upClosePanel);
} else
- _isPanelOpen = true;
+ _isClosePanelDone = true;
_leaveResult = 0;
}
}
@@ -554,27 +383,27 @@ void Scene1105::createObjects() {
_ssSymbolDice[1] = insertSprite<SsScene1105SymbolDie>(1, 339, 304);
_ssSymbolDice[2] = insertSprite<SsScene1105SymbolDie>(2, 485, 304);
- _ssSymbol1UpButton = insertSprite<SsScene1105Button>(this, 0x08002860, NRect(146, 362, 192, 403));
+ _ssSymbol1UpButton = insertSprite<SsScene1105Button>(this, 0x08002860, NRect::make(146, 362, 192, 403));
addCollisionSprite(_ssSymbol1UpButton);
- _ssSymbol1DownButton = insertSprite<SsScene1105Button>(this, 0x42012460, NRect(147, 404, 191, 442));
+ _ssSymbol1DownButton = insertSprite<SsScene1105Button>(this, 0x42012460, NRect::make(147, 404, 191, 442));
addCollisionSprite(_ssSymbol1DownButton);
- _ssSymbol2UpButton = insertSprite<SsScene1105Button>(this, 0x100030A0, NRect(308, 361, 355, 402));
+ _ssSymbol2UpButton = insertSprite<SsScene1105Button>(this, 0x100030A0, NRect::make(308, 361, 355, 402));
addCollisionSprite(_ssSymbol2UpButton);
- _ssSymbol2DownButton = insertSprite<SsScene1105Button>(this, 0x840228A0, NRect(306, 406, 352, 445));
+ _ssSymbol2DownButton = insertSprite<SsScene1105Button>(this, 0x840228A0, NRect::make(306, 406, 352, 445));
addCollisionSprite(_ssSymbol2DownButton);
- _ssSymbol3UpButton = insertSprite<SsScene1105Button>(this, 0x20000120, NRect(476, 358, 509, 394));
+ _ssSymbol3UpButton = insertSprite<SsScene1105Button>(this, 0x20000120, NRect::make(476, 358, 509, 394));
addCollisionSprite(_ssSymbol3UpButton);
- _ssSymbol3DownButton = insertSprite<SsScene1105Button>(this, 0x08043121, NRect(463, 401, 508, 438));
+ _ssSymbol3DownButton = insertSprite<SsScene1105Button>(this, 0x08043121, NRect::make(463, 401, 508, 438));
addCollisionSprite(_ssSymbol3DownButton);
- _ssActionButton = insertSprite<SsScene1105Button>(this, 0x8248AD35, NRect(280, 170, 354, 245));
+ _ssActionButton = insertSprite<SsScene1105Button>(this, 0x8248AD35, NRect::make(280, 170, 354, 245));
addCollisionSprite(_ssActionButton);
-
+
_isPanelOpen = true;
-
+
_asTeddyBear->show();
insertPuzzleMouse(0x18666208, 20, 620);
-
+
}
void Scene1105::upOpenPanel() {
@@ -625,13 +454,6 @@ void Scene1105::upClosePanel() {
}
void Scene1105::update() {
-
- // DEBUG: Show the correct code
- debug("(%d, %d) (%d, %d) (%d, %d)",
- getSubVar(VA_GOOD_DICE_NUMBERS, 0), getSubVar(VA_CURR_DICE_NUMBERS, 0),
- getSubVar(VA_GOOD_DICE_NUMBERS, 1), getSubVar(VA_CURR_DICE_NUMBERS, 1),
- getSubVar(VA_GOOD_DICE_NUMBERS, 2), getSubVar(VA_CURR_DICE_NUMBERS, 2));
-
Scene::update();
if (_countdown != 0 && (--_countdown == 0))
createObjects();
@@ -645,13 +467,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/module1100.h b/engines/neverhood/modules/module1100.h
index 373f6b703f..38bac1f298 100644
--- a/engines/neverhood/modules/module1100.h
+++ b/engines/neverhood/modules/module1100.h
@@ -29,8 +29,6 @@
namespace Neverhood {
-// Module1100
-
class Module1100 : public Module {
public:
Module1100(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -42,52 +40,9 @@ protected:
void updateScene();
};
-class SsScene1105Button : public StaticSprite {
-public:
- SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds);
-protected:
- Scene *_parentScene;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene1105Symbol : public StaticSprite {
-public:
- SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y);
- void hide();
-};
-
-class SsScene1105SymbolDie : public StaticSprite {
-public:
- SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y);
- void hide();
-protected:
- uint _dieIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void loadSymbolSprite();
-};
-
-class AsScene1105TeddyBear : public AnimatedSprite {
-public:
- AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene);
- void show();
- void hide();
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene1105OpenButton : public StaticSprite {
-public:
- SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- int _countdown;
- bool _isClicked;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class AsScene1105TeddyBear;
+class SsScene1105Symbol;
+class SsScene1105SymbolDie;
class Scene1105 : public Scene {
public:
diff --git a/engines/neverhood/modules/module1100_sprites.cpp b/engines/neverhood/modules/module1100_sprites.cpp
new file mode 100644
index 0000000000..51e0bb3f49
--- /dev/null
+++ b/engines/neverhood/modules/module1100_sprites.cpp
@@ -0,0 +1,265 @@
+/* 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 "neverhood/modules/module1100_sprites.h"
+
+namespace Neverhood {
+
+static const uint32 kSsScene1105SymbolDieFileHashes[] = {
+ 0,
+ 0x90898414,
+ 0x91098414,
+ 0x92098414,
+ 0x94098414,
+ 0x98098414,
+ 0x80098414,
+ 0xB0098414,
+ 0xD0098414,
+ 0x10098414
+};
+
+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);
+ setVisible(false);
+}
+
+void SsScene1105Button::update() {
+ if (_countdown != 0 && (--_countdown == 0)) {
+ sendMessage(_parentScene, 0x4807, 0);
+ setVisible(false);
+ }
+}
+
+uint32 SsScene1105Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0) {
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ }
+ break;
+ case 0x480B:
+ _countdown = 8;
+ setVisible(true);
+ playSound(0, 0x44141000);
+ break;
+ }
+ return messageResult;
+}
+
+SsScene1105Symbol::SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y)
+ : StaticSprite(vm, 0) {
+
+ loadSprite(fileHash, kSLFCenteredDrawOffset | kSLFSetPosition, 200, x, y);
+}
+
+void SsScene1105Symbol::hide() {
+ setVisible(false);
+ _needRefresh = true;
+ updatePosition();
+}
+
+SsScene1105SymbolDie::SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y)
+ : StaticSprite(vm, 1100), _dieIndex(dieIndex) {
+
+ _x = x;
+ _y = y;
+ createSurface(200, 50, 50);
+ loadSymbolSprite();
+ SetMessageHandler(&SsScene1105SymbolDie::handleMessage);
+}
+
+uint32 SsScene1105SymbolDie::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ loadSymbolSprite();
+ break;
+ }
+ return messageResult;
+}
+
+void SsScene1105SymbolDie::loadSymbolSprite() {
+ loadSprite(kSsScene1105SymbolDieFileHashes[getSubVar(VA_CURR_DICE_NUMBERS, _dieIndex)], kSLFCenteredDrawOffset);
+}
+
+void SsScene1105SymbolDie::hide() {
+ setVisible(false);
+ _needRefresh = true;
+ updatePosition();
+}
+
+AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(100, 556, 328);
+ _x = 320;
+ _y = 240;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1105TeddyBear::handleMessage);
+ startAnimation(0x65084002, 0, -1);
+ _newStickFrameIndex = 0;
+ setVisible(false);
+ _needRefresh = true;
+ updatePosition();
+ loadSound(0, 0xCE840261);
+ loadSound(1, 0xCCA41A62);
+}
+
+uint32 AsScene1105TeddyBear::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2002:
+ if (getGlobalVar(V_ROBOT_TARGET)) {
+ startAnimation(0x6B0C0432, 0, -1);
+ playSound(0);
+ } else {
+ startAnimation(0x65084002, 0, -1);
+ playSound(1);
+ }
+ break;
+ case 0x3002:
+ sendMessage(_parentScene, 0x2003, 0);
+ stopAnimation();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1105TeddyBear::show() {
+ setVisible(true);
+ _needRefresh = true;
+ updatePosition();
+}
+
+void AsScene1105TeddyBear::hide() {
+ setVisible(false);
+ _needRefresh = true;
+ updatePosition();
+}
+
+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);
+ SetUpdateHandler(&SsScene1105OpenButton::update);
+ SetMessageHandler(&SsScene1105OpenButton::handleMessage);
+}
+
+void SsScene1105OpenButton::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0)) {
+ setVisible(false);
+ sendMessage(_parentScene, 0x2001, 0);
+ }
+}
+
+uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = 0;
+ Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0 && !_isClicked) {
+ playSound(0);
+ setVisible(true);
+ _isClicked = true;
+ _countdown = 4;
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1109::KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stWalkingFirst);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0x2C2A4A1C);
+ break;
+ case 0x483E:
+ teleporterDisappear(0x3C2E4245);
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1100_sprites.h b/engines/neverhood/modules/module1100_sprites.h
new file mode 100644
index 0000000000..c8e5a838da
--- /dev/null
+++ b/engines/neverhood/modules/module1100_sprites.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.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE1100_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1100_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class SsScene1105Button : public StaticSprite {
+public:
+ SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene1105Symbol : public StaticSprite {
+public:
+ SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y);
+ void hide();
+};
+
+class SsScene1105SymbolDie : public StaticSprite {
+public:
+ SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y);
+ void hide();
+protected:
+ uint _dieIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void loadSymbolSprite();
+};
+
+class AsScene1105TeddyBear : public AnimatedSprite {
+public:
+ AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene);
+ void show();
+ void hide();
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene1105OpenButton : public StaticSprite {
+public:
+ SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ bool _isClicked;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1109 : public Klaymen {
+public:
+ KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1100_SPRITES_H */
diff --git a/engines/neverhood/modules/module1200.cpp b/engines/neverhood/modules/module1200.cpp
index 3be3635645..975545091d 100644
--- a/engines/neverhood/modules/module1200.cpp
+++ b/engines/neverhood/modules/module1200.cpp
@@ -21,12 +21,13 @@
*/
#include "neverhood/modules/module1200.h"
+#include "neverhood/modules/module1200_sprites.h"
namespace Neverhood {
Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
SetMessageHandler(&Module1200::handleMessage);
if (which < 0)
@@ -45,7 +46,7 @@ Module1200::~Module1200() {
}
void Module1200::createScene(int sceneNum, int which) {
- debug("Module1200::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1200::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -92,566 +93,10 @@ void Module1200::updateScene() {
}
}
-// Scene1201
-
static const uint32 kScene1201InitArray[] = {
1, 0, 2, 4, 5, 3, 6, 7, 8, 10, 9, 11, 13, 14, 12, 16, 17, 15
};
-static const NPoint kScene1201PointArray[] = {
- {218, 193}, {410, 225}, {368, 277},
- {194, 227}, {366, 174}, {458, 224},
- {242, 228}, {512, 228}, {458, 277},
- {217, 233}, {458, 173}, {410, 276},
- {203, 280}, {371, 226}, {508, 279},
- {230, 273}, {410, 171}, {493, 174}
-};
-
-static const uint32 kScene1201TntFileHashList1[] = {
- 0x2098212D, 0x1600437E, 0x1600437E,
- 0x00A840E3, 0x1A1830F6, 0x1A1830F6,
- 0x00212062, 0x384010B6, 0x384010B6,
- 0x07A01080, 0xD80C2837, 0xD80C2837,
- 0x03A22092, 0xD8802CB6, 0xD8802CB6,
- 0x03A93831, 0xDA460476, 0xDA460476
-};
-
-static const uint32 kScene1201TntFileHashList2[] = {
- 0x3040C676, 0x10914448, 0x10914448,
- 0x3448A066, 0x1288C049, 0x1288C049,
- 0x78C0E026, 0x3098D05A, 0x3098D05A,
- 0x304890E6, 0x1284E048, 0x1284E048,
- 0xB140A1E6, 0x5088A068, 0x5088A068,
- 0x74C4C866, 0x3192C059, 0x3192C059
-};
-
-SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2)
- : StaticSprite(vm, 900) {
-
- int16 x = kScene1201PointArray[pointIndex].x;
- int16 y = kScene1201PointArray[pointIndex].y;
- if (x < 300)
- loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50);
- else
- loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y);
- 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 {
- setVisible(false);
- SetMessageHandler(NULL);
- }
-}
-
-uint32 AsScene1201Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setSubVar(VA_HAS_TAPE, _nameHash, 1);
- setVisible(false);
- SetMessageHandler(NULL);
- break;
- }
- return messageResult;
-}
-
-AsScene1201TntManRope::AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging)
- : AnimatedSprite(vm, 1200) {
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1201TntManRope::handleMessage);
- createSurface(10, 34, 149);
- _x = 202;
- _y = -32;
- if (isDummyHanging) {
- startAnimation(0x928F0C10, 15, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else {
- startAnimation(0x928F0C10, 0, -1);
- _newStickFrameIndex = 0;
- }
-}
-
-uint32 AsScene1201TntManRope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x02060018)
- playSound(0, 0x47900E06);
- break;
- case 0x2006:
- startAnimation(0x928F0C10, 1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- break;
- }
- return messageResult;
-}
-
-AsScene1201RightDoor::AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen)
- : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0) {
-
- createSurface1(0xD088AC30, 100);
- _x = 320;
- _y = 240;
- SetUpdateHandler(&AsScene1201RightDoor::update);
- SetMessageHandler(&AsScene1201RightDoor::handleMessage);
- _newStickFrameIndex = STICK_LAST_FRAME;
- if (isOpen) {
- startAnimation(0xD088AC30, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- _countdown = 25;
- } else {
- stopAnimation();
- setVisible(false);
- }
-}
-
-void AsScene1201RightDoor::update() {
- if (_countdown != 0 && (--_countdown == 0))
- stCloseDoor();
- AnimatedSprite::update();
-}
-
-uint32 AsScene1201RightDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- case 0x4829:
- stOpenDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene1201RightDoor::stOpenDoor() {
- startAnimation(0xD088AC30, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- setVisible(true);
- playSound(0, calcHash("fxDoorOpen20"));
-}
-
-void AsScene1201RightDoor::stCloseDoor() {
- startAnimation(0xD088AC30, -1, -1);
- _playBackwards = true;
- setVisible(true);
- playSound(0, calcHash("fxDoorClose20"));
- NextState(&AsScene1201RightDoor::stCloseDoorDone);
-}
-
-void AsScene1201RightDoor::stCloseDoorDone() {
- stopAnimation();
- setVisible(false);
-}
-
-AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200) {
-
- createSurface(1200, 69, 98);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1201KlaymenHead::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- setVisible(false);
-}
-
-uint32 AsScene1201KlaymenHead::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2006:
- _x = 436;
- _y = 339;
- startAnimation(0xA060C599, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isComingDown)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asTntManRope(asTntManRope),
- _isMoving(false) {
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1201TntMan::handleMessage);
- createSurface(990, 106, 181);
- _x = 201;
- if (isComingDown) {
- _y = 297;
- stComingDown();
- } else {
- _y = 334;
- stStanding();
- }
-}
-
-AsScene1201TntMan::~AsScene1201TntMan() {
- _vm->_soundMan->deleteSoundGroup(0x01D00560);
-}
-
-uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x092870C0)
- sendMessage(_asTntManRope, 0x2006, 0);
- else if (param.asInteger() == 0x11CA0144)
- playSound(0, 0x51800A04);
- break;
- case 0x1011:
- sendMessage(_parentScene, 0x2002, 0);
- messageResult = 1;
- break;
- case 0x480B:
- if (!_isMoving) {
- _sprite = (Sprite*)sender;
- stMoving();
- }
- break;
- }
- return messageResult;
-
-}
-
-uint32 AsScene1201TntMan::hmComingDown(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = AsScene1201TntMan::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1201TntMan::suMoving() {
- _x = _sprite->getX() + 100;
-}
-
-void AsScene1201TntMan::stStanding() {
- startAnimation(0x654913D0, 0, -1);
- SetMessageHandler(&AsScene1201TntMan::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsScene1201TntMan::stComingDown() {
- startAnimation(0x356803D0, 0, -1);
- SetMessageHandler(&AsScene1201TntMan::hmComingDown);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- NextState(&AsScene1201TntMan::stStanding);
-}
-
-void AsScene1201TntMan::stMoving() {
- _vm->_soundMan->addSound(0x01D00560, 0x4B044624);
- _vm->_soundMan->playSoundLooping(0x4B044624);
- _isMoving = true;
- startAnimation(0x85084190, 0, -1);
- SetMessageHandler(&AsScene1201TntMan::handleMessage);
- SetSpriteUpdate(&AsScene1201TntMan::suMoving);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
-AsScene1201TntManFlame::AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan)
- : AnimatedSprite(vm, 1200), _asTntMan(asTntMan) {
-
- createSurface1(0x828C0411, 995);
- SetUpdateHandler(&AsScene1201TntManFlame::update);
- SetMessageHandler(&Sprite::handleMessage);
- SetSpriteUpdate(&AsScene1201TntManFlame::suUpdate);
- startAnimation(0x828C0411, 0, -1);
- setVisible(false);
-}
-
-AsScene1201TntManFlame::~AsScene1201TntManFlame() {
- _vm->_soundMan->deleteSoundGroup(0x041080A4);
-}
-
-void AsScene1201TntManFlame::update() {
- AnimatedSprite::update();
- if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) {
- setVisible(true);
- SetUpdateHandler(&AnimatedSprite::update);
- _vm->_soundMan->addSound(0x041080A4, 0x460A1050);
- _vm->_soundMan->playSoundLooping(0x460A1050);
- }
-}
-
-void AsScene1201TntManFlame::suUpdate() {
- _x = _asTntMan->getX() - 18;
- _y = _asTntMan->getY() - 158;
-}
-
-AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) {
-
- createSurface(1100, 57, 60);
- SetUpdateHandler(&AsScene1201Match::update);
- SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- switch (getGlobalVar(V_MATCH_STATUS)) {
- case 0:
- _x = 521;
- _y = 112;
- _status = 0;
- stIdleOnDoorFrame();
- break;
- case 1:
- _x = 521;
- _y = 112;
- _status = 2;
- stOnDoorFrameAboutToMove();
- loadSound(0, 0xD00230CD);
- break;
- case 2:
- setDoDeltaX(1);
- _x = 403;
- _y = 337;
- _status = 0;
- stIdleOnFloor();
- break;
- }
-}
-
-void AsScene1201Match::update() {
- if (_countdown != 0 && (--_countdown == 0))
- gotoNextState();
- updateAnim();
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 AsScene1201Match::hmOnDoorFrameAboutToMove(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x86668011)
- playSound(0);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1201Match::hmOnDoorFrameMoving(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1201Match::hmIdle(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x2001, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setVisible(false);
- setGlobalVar(V_MATCH_STATUS, 3);
- break;
- }
- return messageResult;
-}
-
-void AsScene1201Match::stOnDoorFrameMoving() {
- startAnimation(0x00842374, 0, -1);
- SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving);
- if (_status == 0) {
- NextState(&AsScene1201Match::stFallingFromDoorFrame);
- } else {
- NextState(&AsScene1201Match::stOnDoorFrameAboutToMove);
- }
-}
-
-void AsScene1201Match::stFallingFromDoorFrame() {
- setGlobalVar(V_MATCH_STATUS, 2);
- _x -= 199;
- _y += 119;
- startAnimation(0x018D0240, 0, -1);
- SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving);
- NextState(&AsScene1201Match::stIdleOnFloor);
-}
-
-void AsScene1201Match::stOnDoorFrameAboutToMove() {
- startAnimation(0x00842374, 0, -1);
- SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove);
- _newStickFrameIndex = 0;
- if (_status != 0) {
- _countdown = 36;
- _status--;
- NextState(&AsScene1201Match::stOnDoorFrameMoving);
- }
-}
-
-void AsScene1201Match::stIdleOnDoorFrame() {
- startAnimation(0x00842374, 0, -1);
- SetMessageHandler(&AsScene1201Match::hmIdle);
- _newStickFrameIndex = 0;
-}
-
-void AsScene1201Match::stIdleOnFloor() {
- setDoDeltaX(1);
- _x = 403;
- _y = 337;
- startAnimation(0x00842374, 0, -1);
- SetMessageHandler(&AsScene1201Match::hmIdle);
- _newStickFrameIndex = 0;
-}
-
-AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen)
- : 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);
- _x = 540;
- _y = 320;
- stWaiting();
-}
-
-void AsScene1201Creature::update() {
- bool oldKlaymenTooClose = _klaymenTooClose;
- _klaymenTooClose = _klaymen->getX() >= 385;
- if (_klaymenTooClose != oldKlaymenTooClose)
- stWaiting();
- if (_countdown != 0 && (--_countdown == 0))
- gotoNextState();
- updateAnim();
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 AsScene1201Creature::hmWaiting(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x02060018)
- playSound(0, 0xCD298116);
- break;
- case 0x2004:
- GotoState(&AsScene1201Creature::stStartReachForTntDummy);
- break;
- case 0x2006:
- GotoState(&AsScene1201Creature::stPincerSnapKlaymen);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1201Creature::hmPincerSnap(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = hmWaiting(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1201Creature::hmPincerSnapKlaymen(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x02060018) {
- playSound(0, 0xCD298116);
- sendMessage(_parentScene, 0x4814, 0);
- sendMessage(_klaymen, 0x4814, 0);
- }
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1201Creature::stWaiting() {
- startAnimation(0x08081513, 0, -1);
- SetMessageHandler(&AsScene1201Creature::hmWaiting);
- NextState(&AsScene1201Creature::stPincerSnap);
- _countdown = 36;
-}
-
-void AsScene1201Creature::stPincerSnap() {
- if (!_klaymenTooClose) {
- startAnimation(0xCA287133, 0, -1);
- SetMessageHandler(&AsScene1201Creature::hmPincerSnap);
- NextState(&AsScene1201Creature::stWaiting);
- }
-}
-
-void AsScene1201Creature::stStartReachForTntDummy() {
- startAnimation(0x08081513, 0, -1);
- SetMessageHandler(&AsScene1201Creature::hmWaiting);
- NextState(&AsScene1201Creature::stReachForTntDummy);
- _countdown = 48;
-}
-
-void AsScene1201Creature::stReachForTntDummy() {
- startAnimation(0x5A201453, 0, -1);
- SetMessageHandler(&AsScene1201Creature::hmWaiting);
- _countdown = 0;
-}
-
-void AsScene1201Creature::stPincerSnapKlaymen() {
- startAnimation(0xCA287133, 0, -1);
- SetMessageHandler(&AsScene1201Creature::hmPincerSnapKlaymen);
- NextState(&AsScene1201Creature::stWaiting);
- _countdown = 0;
-}
-
-AsScene1201LeftDoor::AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen)
- : AnimatedSprite(vm, 1100), _klaymen(klaymen) {
-
- _x = 320;
- _y = 240;
- createSurface(800, 55, 199);
- if (_klaymen->getX() < 100) {
- startAnimation(0x508A111B, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- playSound(0, calcHash("fxDoorOpen03"));
- } else {
- startAnimation(0x508A111B, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- }
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1201LeftDoor::handleMessage);
-}
-
-uint32 AsScene1201LeftDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4809:
- stCloseDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene1201LeftDoor::stCloseDoor() {
- startAnimation(0x508A111B, -1, -1);
- _playBackwards = true;
- _newStickFrameIndex = 0;
-}
-
Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _creatureExploded(false), _asMatch(NULL), _asTntMan(NULL),
_asCreature(NULL), _asTntManRope(NULL), _asLeftDoor(NULL), _asRightDoor(NULL), _asTape(NULL) {
@@ -664,7 +109,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 +117,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 +180,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 +201,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 +228,10 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
setRectList(0x004AEE58);
} else {
setRectList(0x004AEDC8);
- }
-
+ }
+
} else {
-
+
insertStaticSprite(0x8E8A1981, 900);
uint32 tntIndex = 0;
@@ -795,7 +240,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 +256,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
setRectList(0x004AEE18);
else
setRectList(0x004AED88);
-
+
}
tempSprite = insertStaticSprite(0x63D400BC, 900);
@@ -875,7 +320,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,102 +348,17 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam &param, Entit
break;
case 0x8000:
sendMessage(_asKlaymenHead, 0x2006, 0);
- break;
+ break;
}
return messageResult;
}
-// Scene1202
-
static const uint32 kScene1202Table[] = {
1, 2, 0, 4, 5, 3, 7, 8, 6, 10, 11, 9, 13, 14, 12, 16, 17, 15
};
-static const NPoint kScene1202Points[] = {
- {203, 140}, {316, 212}, {277, 264},
- {176, 196}, {275, 159}, {366, 212},
- {230, 195}, {412, 212}, {368, 263},
- {204, 192}, {365, 164}, {316, 262},
- {191, 255}, {280, 213}, {406, 266},
- {214, 254}, {316, 158}, {402, 161}
-};
-
-static const uint32 kScene1202FileHashes[] = {
- 0x1AC00B8, 0x1AC14B8, 0x1AC14B8,
- 0x1AC30B8, 0x1AC14B8, 0x1AC14B8,
- 0x1AC00B8, 0x1AC14B8, 0x1AC14B8,
- 0x1AC90B8, 0x1AC18B8, 0x1AC18B8,
- 0x1AC30B8, 0x1AC14B8, 0x1AC14B8,
- 0x1AC50B8, 0x1AC14B8, 0x1AC14B8
-};
-
-AsScene1202TntItem::AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int itemIndex)
- : AnimatedSprite(vm, 900), _parentScene(parentScene), _itemIndex(itemIndex) {
-
- int positionIndex;
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1202TntItem::hmShowIdle);
- positionIndex = getSubVar(VA_TNT_POSITIONS, _itemIndex);
- createSurface(900, 37, 67);
- _x = kScene1202Points[positionIndex].x;
- _y = kScene1202Points[positionIndex].y;
- stShowIdle();
-}
-
-uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x2000, _itemIndex);
- messageResult = 1;
- break;
- case 0x2001:
- _newPosition = (int)param.asInteger();
- stChangePositionFadeOut();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1202TntItem::hmChangePosition(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1202TntItem::stShowIdle() {
- startAnimation(kScene1202FileHashes[_itemIndex], 0, -1);
- SetMessageHandler(&AsScene1202TntItem::hmShowIdle);
- _newStickFrameIndex = 0;
-}
-
-void AsScene1202TntItem::stChangePositionFadeOut() {
- startAnimation(kScene1202FileHashes[_itemIndex], 0, -1);
- SetMessageHandler(&AsScene1202TntItem::hmChangePosition);
- NextState(&AsScene1202TntItem::stChangePositionFadeIn);
-}
-
-void AsScene1202TntItem::stChangePositionFadeIn() {
- _x = kScene1202Points[_newPosition].x;
- _y = kScene1202Points[_newPosition].y;
- startAnimation(kScene1202FileHashes[_itemIndex], 6, -1);
- _playBackwards = true;
- SetMessageHandler(&AsScene1202TntItem::hmChangePosition);
- NextState(&AsScene1202TntItem::stChangePositionDone);
-}
-
-void AsScene1202TntItem::stChangePositionDone() {
- sendMessage(_parentScene, 0x2002, _itemIndex);
- stShowIdle();
-}
-
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 +453,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/module1200.h b/engines/neverhood/modules/module1200.h
index c97dc98986..d9d4dd11f2 100644
--- a/engines/neverhood/modules/module1200.h
+++ b/engines/neverhood/modules/module1200.h
@@ -29,8 +29,6 @@
namespace Neverhood {
-// Module1200
-
class Module1200 : public Module {
public:
Module1200(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -41,123 +39,7 @@ protected:
void updateScene();
};
-// Scene1201
-
-class AsScene1201Tape : public AnimatedSprite {
-public:
- AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash);
-protected:
- Scene *_parentScene;
- uint32 _nameHash;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1201TntManRope : public AnimatedSprite {
-public:
- AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1201RightDoor : public AnimatedSprite {
-public:
- AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen);
-protected:
- Sprite *_klaymen;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stCloseDoor();
- void stCloseDoorDone();
-};
-
-class AsScene1201KlaymenHead : public AnimatedSprite {
-public:
- AsScene1201KlaymenHead(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene1201TntMan : public AnimatedSprite {
-public:
- AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isDown);
- virtual ~AsScene1201TntMan();
-protected:
- Scene *_parentScene;
- Sprite *_asTntManRope;
- Sprite *_sprite;
- bool _isMoving;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmComingDown(int messageNum, const MessageParam &param, Entity *sender);
- void suMoving();
- void stStanding();
- void stComingDown();
- void stMoving();
-};
-
-class AsScene1201TntManFlame : public AnimatedSprite {
-public:
- AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan);
- ~AsScene1201TntManFlame();
-protected:
- Sprite *_asTntMan;
- void update();
- void suUpdate();
-};
-
-class AsScene1201Match : public AnimatedSprite {
-public:
- AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- int _countdown;
- int _status;
- void update();
- uint32 hmOnDoorFrameAboutToMove(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmOnDoorFrameMoving(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmIdle(int messageNum, const MessageParam &param, Entity *sender);
- void stOnDoorFrameMoving();
- void stFallingFromDoorFrame();
- void stOnDoorFrameAboutToMove();
- void stIdleOnDoorFrame();
- void stIdleOnFloor();
-};
-
-class AsScene1201Creature : public AnimatedSprite {
-public:
- AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen);
-protected:
- Scene *_parentScene;
- Sprite *_klaymen;
- int _countdown;
- bool _klaymenTooClose;
- void update();
- uint32 hmWaiting(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmPincerSnap(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmPincerSnapKlaymen(int messageNum, const MessageParam &param, Entity *sender);
- void stWaiting();
- void stPincerSnap();
- void stStartReachForTntDummy();
- void stReachForTntDummy();
- void stPincerSnapKlaymen();
-};
-
-class AsScene1201LeftDoor : public AnimatedSprite {
-public:
- AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen);
-protected:
- Sprite *_klaymen;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stCloseDoor();
-};
-
-class SsScene1201Tnt : public StaticSprite {
-public:
- SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2);
-protected:
- uint32 _elemIndex;
-};
+class AsScene1201TntMan;
class Scene1201 : public Scene {
public:
@@ -177,22 +59,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1202
-
-class AsScene1202TntItem : public AnimatedSprite {
-public:
- AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index);
-protected:
- Scene *_parentScene;
- int _itemIndex, _newPosition;
- uint32 hmShowIdle(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmChangePosition(int messageNum, const MessageParam &param, Entity *sender);
- void stShowIdle();
- void stChangePositionFadeOut();
- void stChangePositionFadeIn();
- void stChangePositionDone();
-};
-
class Scene1202 : public Scene {
public:
Scene1202(NeverhoodEngine *vm, Module *parentModule);
diff --git a/engines/neverhood/modules/module1200_sprites.cpp b/engines/neverhood/modules/module1200_sprites.cpp
new file mode 100644
index 0000000000..da38924d9a
--- /dev/null
+++ b/engines/neverhood/modules/module1200_sprites.cpp
@@ -0,0 +1,810 @@
+/* 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 "neverhood/modules/module1200_sprites.h"
+
+namespace Neverhood {
+
+static const uint32 kScene1201TntFileHashList1[] = {
+ 0x2098212D, 0x1600437E, 0x1600437E,
+ 0x00A840E3, 0x1A1830F6, 0x1A1830F6,
+ 0x00212062, 0x384010B6, 0x384010B6,
+ 0x07A01080, 0xD80C2837, 0xD80C2837,
+ 0x03A22092, 0xD8802CB6, 0xD8802CB6,
+ 0x03A93831, 0xDA460476, 0xDA460476
+};
+
+static const uint32 kScene1201TntFileHashList2[] = {
+ 0x3040C676, 0x10914448, 0x10914448,
+ 0x3448A066, 0x1288C049, 0x1288C049,
+ 0x78C0E026, 0x3098D05A, 0x3098D05A,
+ 0x304890E6, 0x1284E048, 0x1284E048,
+ 0xB140A1E6, 0x5088A068, 0x5088A068,
+ 0x74C4C866, 0x3192C059, 0x3192C059
+};
+
+SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2)
+ : StaticSprite(vm, 900) {
+
+ int16 x = kScene1201PointArray[pointIndex].x;
+ int16 y = kScene1201PointArray[pointIndex].y;
+ if (x < 300)
+ loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50);
+ else
+ 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 {
+ setVisible(false);
+ SetMessageHandler(NULL);
+ }
+}
+
+uint32 AsScene1201Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setSubVar(VA_HAS_TAPE, _nameHash, 1);
+ setVisible(false);
+ SetMessageHandler(NULL);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1201TntManRope::AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging)
+ : AnimatedSprite(vm, 1200) {
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1201TntManRope::handleMessage);
+ createSurface(10, 34, 149);
+ _x = 202;
+ _y = -32;
+ if (isDummyHanging) {
+ startAnimation(0x928F0C10, 15, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else {
+ startAnimation(0x928F0C10, 0, -1);
+ _newStickFrameIndex = 0;
+ }
+}
+
+uint32 AsScene1201TntManRope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x02060018)
+ playSound(0, 0x47900E06);
+ break;
+ case 0x2006:
+ startAnimation(0x928F0C10, 1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1201RightDoor::AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen)
+ : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0) {
+
+ createSurface1(0xD088AC30, 100);
+ _x = 320;
+ _y = 240;
+ SetUpdateHandler(&AsScene1201RightDoor::update);
+ SetMessageHandler(&AsScene1201RightDoor::handleMessage);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ if (isOpen) {
+ startAnimation(0xD088AC30, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ _countdown = 25;
+ } else {
+ stopAnimation();
+ setVisible(false);
+ }
+}
+
+void AsScene1201RightDoor::update() {
+ if (_countdown != 0 && (--_countdown == 0))
+ stCloseDoor();
+ AnimatedSprite::update();
+}
+
+uint32 AsScene1201RightDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4829:
+ stOpenDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1201RightDoor::stOpenDoor() {
+ startAnimation(0xD088AC30, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ setVisible(true);
+ playSound(0, calcHash("fxDoorOpen20"));
+}
+
+void AsScene1201RightDoor::stCloseDoor() {
+ startAnimation(0xD088AC30, -1, -1);
+ _playBackwards = true;
+ setVisible(true);
+ playSound(0, calcHash("fxDoorClose20"));
+ NextState(&AsScene1201RightDoor::stCloseDoorDone);
+}
+
+void AsScene1201RightDoor::stCloseDoorDone() {
+ stopAnimation();
+ setVisible(false);
+}
+
+AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200) {
+
+ createSurface(1200, 69, 98);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1201KlaymenHead::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ setVisible(false);
+}
+
+uint32 AsScene1201KlaymenHead::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2006:
+ _x = 436;
+ _y = 339;
+ startAnimation(0xA060C599, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isComingDown)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asTntManRope(asTntManRope),
+ _isMoving(false) {
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1201TntMan::handleMessage);
+ createSurface(990, 106, 181);
+ _x = 201;
+ if (isComingDown) {
+ _y = 297;
+ stComingDown();
+ } else {
+ _y = 334;
+ stStanding();
+ }
+}
+
+AsScene1201TntMan::~AsScene1201TntMan() {
+ _vm->_soundMan->deleteSoundGroup(0x01D00560);
+}
+
+uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x092870C0)
+ sendMessage(_asTntManRope, 0x2006, 0);
+ else if (param.asInteger() == 0x11CA0144)
+ playSound(0, 0x51800A04);
+ break;
+ case 0x1011:
+ sendMessage(_parentScene, 0x2002, 0);
+ messageResult = 1;
+ break;
+ case 0x480B:
+ if (!_isMoving) {
+ _sprite = (Sprite*)sender;
+ stMoving();
+ }
+ break;
+ }
+ return messageResult;
+
+}
+
+uint32 AsScene1201TntMan::hmComingDown(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = AsScene1201TntMan::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1201TntMan::suMoving() {
+ _x = _sprite->getX() + 100;
+}
+
+void AsScene1201TntMan::stStanding() {
+ startAnimation(0x654913D0, 0, -1);
+ SetMessageHandler(&AsScene1201TntMan::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsScene1201TntMan::stComingDown() {
+ startAnimation(0x356803D0, 0, -1);
+ SetMessageHandler(&AsScene1201TntMan::hmComingDown);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ NextState(&AsScene1201TntMan::stStanding);
+}
+
+void AsScene1201TntMan::stMoving() {
+ _vm->_soundMan->addSound(0x01D00560, 0x4B044624);
+ _vm->_soundMan->playSoundLooping(0x4B044624);
+ _isMoving = true;
+ startAnimation(0x85084190, 0, -1);
+ SetMessageHandler(&AsScene1201TntMan::handleMessage);
+ SetSpriteUpdate(&AsScene1201TntMan::suMoving);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+AsScene1201TntManFlame::AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan)
+ : AnimatedSprite(vm, 1200), _asTntMan(asTntMan) {
+
+ createSurface1(0x828C0411, 995);
+ SetUpdateHandler(&AsScene1201TntManFlame::update);
+ SetMessageHandler(&Sprite::handleMessage);
+ SetSpriteUpdate(&AsScene1201TntManFlame::suUpdate);
+ startAnimation(0x828C0411, 0, -1);
+ setVisible(false);
+}
+
+AsScene1201TntManFlame::~AsScene1201TntManFlame() {
+ _vm->_soundMan->deleteSoundGroup(0x041080A4);
+}
+
+void AsScene1201TntManFlame::update() {
+ AnimatedSprite::update();
+ if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) {
+ setVisible(true);
+ SetUpdateHandler(&AnimatedSprite::update);
+ _vm->_soundMan->addSound(0x041080A4, 0x460A1050);
+ _vm->_soundMan->playSoundLooping(0x460A1050);
+ }
+}
+
+void AsScene1201TntManFlame::suUpdate() {
+ _x = _asTntMan->getX() - 18;
+ _y = _asTntMan->getY() - 158;
+}
+
+AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) {
+
+ createSurface(1100, 57, 60);
+ SetUpdateHandler(&AsScene1201Match::update);
+ SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ switch (getGlobalVar(V_MATCH_STATUS)) {
+ case 0:
+ _x = 521;
+ _y = 112;
+ _status = 0;
+ stIdleOnDoorFrame();
+ break;
+ case 1:
+ _x = 521;
+ _y = 112;
+ _status = 2;
+ stOnDoorFrameAboutToMove();
+ loadSound(0, 0xD00230CD);
+ break;
+ case 2:
+ setDoDeltaX(1);
+ _x = 403;
+ _y = 337;
+ _status = 0;
+ stIdleOnFloor();
+ break;
+ }
+}
+
+void AsScene1201Match::update() {
+ if (_countdown != 0 && (--_countdown == 0))
+ gotoNextState();
+ updateAnim();
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 AsScene1201Match::hmOnDoorFrameAboutToMove(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x86668011)
+ playSound(0);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1201Match::hmOnDoorFrameMoving(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1201Match::hmIdle(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x2001, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setVisible(false);
+ setGlobalVar(V_MATCH_STATUS, 3);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1201Match::stOnDoorFrameMoving() {
+ startAnimation(0x00842374, 0, -1);
+ SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving);
+ if (_status == 0) {
+ NextState(&AsScene1201Match::stFallingFromDoorFrame);
+ } else {
+ NextState(&AsScene1201Match::stOnDoorFrameAboutToMove);
+ }
+}
+
+void AsScene1201Match::stFallingFromDoorFrame() {
+ setGlobalVar(V_MATCH_STATUS, 2);
+ _x -= 199;
+ _y += 119;
+ startAnimation(0x018D0240, 0, -1);
+ SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving);
+ NextState(&AsScene1201Match::stIdleOnFloor);
+}
+
+void AsScene1201Match::stOnDoorFrameAboutToMove() {
+ startAnimation(0x00842374, 0, -1);
+ SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove);
+ _newStickFrameIndex = 0;
+ if (_status != 0) {
+ _countdown = 36;
+ _status--;
+ NextState(&AsScene1201Match::stOnDoorFrameMoving);
+ }
+}
+
+void AsScene1201Match::stIdleOnDoorFrame() {
+ startAnimation(0x00842374, 0, -1);
+ SetMessageHandler(&AsScene1201Match::hmIdle);
+ _newStickFrameIndex = 0;
+}
+
+void AsScene1201Match::stIdleOnFloor() {
+ setDoDeltaX(1);
+ _x = 403;
+ _y = 337;
+ startAnimation(0x00842374, 0, -1);
+ SetMessageHandler(&AsScene1201Match::hmIdle);
+ _newStickFrameIndex = 0;
+}
+
+AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen)
+ : 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);
+ _x = 540;
+ _y = 320;
+ stWaiting();
+}
+
+void AsScene1201Creature::update() {
+ bool oldKlaymenTooClose = _klaymenTooClose;
+ _klaymenTooClose = _klaymen->getX() >= 385;
+ if (_klaymenTooClose != oldKlaymenTooClose)
+ stWaiting();
+ if (_countdown != 0 && (--_countdown == 0))
+ gotoNextState();
+ updateAnim();
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 AsScene1201Creature::hmWaiting(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x02060018)
+ playSound(0, 0xCD298116);
+ break;
+ case 0x2004:
+ GotoState(&AsScene1201Creature::stStartReachForTntDummy);
+ break;
+ case 0x2006:
+ GotoState(&AsScene1201Creature::stPincerSnapKlaymen);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1201Creature::hmPincerSnap(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmWaiting(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1201Creature::hmPincerSnapKlaymen(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x02060018) {
+ playSound(0, 0xCD298116);
+ sendMessage(_parentScene, 0x4814, 0);
+ sendMessage(_klaymen, 0x4814, 0);
+ }
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1201Creature::stWaiting() {
+ startAnimation(0x08081513, 0, -1);
+ SetMessageHandler(&AsScene1201Creature::hmWaiting);
+ NextState(&AsScene1201Creature::stPincerSnap);
+ _countdown = 36;
+}
+
+void AsScene1201Creature::stPincerSnap() {
+ if (!_klaymenTooClose) {
+ startAnimation(0xCA287133, 0, -1);
+ SetMessageHandler(&AsScene1201Creature::hmPincerSnap);
+ NextState(&AsScene1201Creature::stWaiting);
+ }
+}
+
+void AsScene1201Creature::stStartReachForTntDummy() {
+ startAnimation(0x08081513, 0, -1);
+ SetMessageHandler(&AsScene1201Creature::hmWaiting);
+ NextState(&AsScene1201Creature::stReachForTntDummy);
+ _countdown = 48;
+}
+
+void AsScene1201Creature::stReachForTntDummy() {
+ startAnimation(0x5A201453, 0, -1);
+ SetMessageHandler(&AsScene1201Creature::hmWaiting);
+ _countdown = 0;
+}
+
+void AsScene1201Creature::stPincerSnapKlaymen() {
+ startAnimation(0xCA287133, 0, -1);
+ SetMessageHandler(&AsScene1201Creature::hmPincerSnapKlaymen);
+ NextState(&AsScene1201Creature::stWaiting);
+ _countdown = 0;
+}
+
+AsScene1201LeftDoor::AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen)
+ : AnimatedSprite(vm, 1100), _klaymen(klaymen) {
+
+ _x = 320;
+ _y = 240;
+ createSurface(800, 55, 199);
+ if (_klaymen->getX() < 100) {
+ startAnimation(0x508A111B, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ playSound(0, calcHash("fxDoorOpen03"));
+ } else {
+ startAnimation(0x508A111B, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ }
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1201LeftDoor::handleMessage);
+}
+
+uint32 AsScene1201LeftDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4809:
+ stCloseDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1201LeftDoor::stCloseDoor() {
+ startAnimation(0x508A111B, -1, -1);
+ _playBackwards = true;
+ _newStickFrameIndex = 0;
+}
+
+static const NPoint kScene1202Points[] = {
+ {203, 140}, {316, 212}, {277, 264},
+ {176, 196}, {275, 159}, {366, 212},
+ {230, 195}, {412, 212}, {368, 263},
+ {204, 192}, {365, 164}, {316, 262},
+ {191, 255}, {280, 213}, {406, 266},
+ {214, 254}, {316, 158}, {402, 161}
+};
+
+static const uint32 kScene1202FileHashes[] = {
+ 0x1AC00B8, 0x1AC14B8, 0x1AC14B8,
+ 0x1AC30B8, 0x1AC14B8, 0x1AC14B8,
+ 0x1AC00B8, 0x1AC14B8, 0x1AC14B8,
+ 0x1AC90B8, 0x1AC18B8, 0x1AC18B8,
+ 0x1AC30B8, 0x1AC14B8, 0x1AC14B8,
+ 0x1AC50B8, 0x1AC14B8, 0x1AC14B8
+};
+
+AsScene1202TntItem::AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int itemIndex)
+ : AnimatedSprite(vm, 900), _parentScene(parentScene), _itemIndex(itemIndex) {
+
+ int positionIndex;
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1202TntItem::hmShowIdle);
+ positionIndex = getSubVar(VA_TNT_POSITIONS, _itemIndex);
+ createSurface(900, 37, 67);
+ _x = kScene1202Points[positionIndex].x;
+ _y = kScene1202Points[positionIndex].y;
+ stShowIdle();
+}
+
+uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x2000, _itemIndex);
+ messageResult = 1;
+ break;
+ case 0x2001:
+ _newPosition = (int)param.asInteger();
+ stChangePositionFadeOut();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1202TntItem::hmChangePosition(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1202TntItem::stShowIdle() {
+ startAnimation(kScene1202FileHashes[_itemIndex], 0, -1);
+ SetMessageHandler(&AsScene1202TntItem::hmShowIdle);
+ _newStickFrameIndex = 0;
+}
+
+void AsScene1202TntItem::stChangePositionFadeOut() {
+ startAnimation(kScene1202FileHashes[_itemIndex], 0, -1);
+ SetMessageHandler(&AsScene1202TntItem::hmChangePosition);
+ NextState(&AsScene1202TntItem::stChangePositionFadeIn);
+}
+
+void AsScene1202TntItem::stChangePositionFadeIn() {
+ _x = kScene1202Points[_newPosition].x;
+ _y = kScene1202Points[_newPosition].y;
+ startAnimation(kScene1202FileHashes[_itemIndex], 6, -1);
+ _playBackwards = true;
+ SetMessageHandler(&AsScene1202TntItem::hmChangePosition);
+ NextState(&AsScene1202TntItem::stChangePositionDone);
+}
+
+void AsScene1202TntItem::stChangePositionDone() {
+ sendMessage(_parentScene, 0x2002, _itemIndex);
+ stShowIdle();
+}
+
+static const KlaymenIdleTableItem klaymenIdleTable1201[] = {
+ {1, kIdleSpinHead},
+ {1, kIdleChest},
+ {1, kIdleHeadOff},
+};
+
+KmScene1201::KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ setKlaymenIdleTable(klaymenIdleTable1201, ARRAYSIZE(klaymenIdleTable1201));
+ _doYHitIncr = true;
+}
+
+uint32 KmScene1201::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ GotoState(&Klaymen::stMoveObject);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4813:
+ GotoState(&KmScene1201::stFetchMatch);
+ break;
+ case 0x4814:
+ GotoState(&KmScene1201::stTumbleHeadless);
+ break;
+ case 0x4815:
+ GotoState(&KmScene1201::stCloseEyes);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+void KmScene1201::stTumbleHeadless() {
+ if (!stStartActionFromIdle(AnimationCallback(&KmScene1201::stTumbleHeadless))) {
+ _busyStatus = 1;
+ _acceptInput = false;
+ setDoDeltaX(0);
+ startAnimation(0x2821C590, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1201::hmTumbleHeadless);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ NextState(&Klaymen::stTryStandIdle);
+ sendMessage(_parentScene, 0x8000, 0);
+ playSound(0, 0x62E0A356);
+ }
+}
+
+void KmScene1201::stCloseEyes() {
+ if (!stStartActionFromIdle(AnimationCallback(&KmScene1201::stCloseEyes))) {
+ _busyStatus = 1;
+ _acceptInput = false;
+ startAnimation(0x5420E254, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&Klaymen::hmLowLevel);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+uint32 KmScene1201::hmMatch(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x51281850) {
+ setGlobalVar(V_TNT_DUMMY_FUSE_LIT, 1);
+ } else if (param.asInteger() == 0x43000538) {
+ playSound(0, 0x21043059);
+ } else if (param.asInteger() == 0x02B20220) {
+ playSound(0, 0xC5408620);
+ } else if (param.asInteger() == 0x0A720138) {
+ playSound(0, 0xD4C08010);
+ } else if (param.asInteger() == 0xB613A180) {
+ playSound(0, 0x44051000);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene1201::stFetchMatch() {
+ if (!stStartAction(AnimationCallback(&KmScene1201::stFetchMatch))) {
+ _busyStatus = 0;
+ _acceptInput = false;
+ setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
+ startAnimation(0x9CAA0218, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1201::hmMatch);
+ SetSpriteUpdate(NULL);
+ NextState(&KmScene1201::stLightMatch);
+ }
+}
+
+void KmScene1201::stLightMatch() {
+ _busyStatus = 1;
+ _acceptInput = false;
+ setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
+ startAnimation(0x1222A513, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene1201::hmMatch);
+ SetSpriteUpdate(NULL);
+}
+
+uint32 KmScene1201::hmTumbleHeadless(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x000F0082) {
+ playSound(0, 0x74E2810F);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1200_sprites.h b/engines/neverhood/modules/module1200_sprites.h
new file mode 100644
index 0000000000..ef1ec40ced
--- /dev/null
+++ b/engines/neverhood/modules/module1200_sprites.h
@@ -0,0 +1,187 @@
+/* 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 NEVERHOOD_MODULES_MODULE1200_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1200_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+// Used for both the scene sprites and the scene itself (for clipping)
+static const NPoint kScene1201PointArray[] = {
+ {218, 193}, {410, 225}, {368, 277},
+ {194, 227}, {366, 174}, {458, 224},
+ {242, 228}, {512, 228}, {458, 277},
+ {217, 233}, {458, 173}, {410, 276},
+ {203, 280}, {371, 226}, {508, 279},
+ {230, 273}, {410, 171}, {493, 174}
+};
+
+class AsScene1201Tape : public AnimatedSprite {
+public:
+ AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash);
+protected:
+ Scene *_parentScene;
+ uint32 _nameHash;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1201TntManRope : public AnimatedSprite {
+public:
+ AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1201RightDoor : public AnimatedSprite {
+public:
+ AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen);
+protected:
+ Sprite *_klaymen;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stCloseDoor();
+ void stCloseDoorDone();
+};
+
+class AsScene1201KlaymenHead : public AnimatedSprite {
+public:
+ AsScene1201KlaymenHead(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1201TntMan : public AnimatedSprite {
+public:
+ AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isDown);
+ virtual ~AsScene1201TntMan();
+protected:
+ Scene *_parentScene;
+ Sprite *_asTntManRope;
+ Sprite *_sprite;
+ bool _isMoving;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmComingDown(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoving();
+ void stStanding();
+ void stComingDown();
+ void stMoving();
+};
+
+class AsScene1201TntManFlame : public AnimatedSprite {
+public:
+ AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan);
+ ~AsScene1201TntManFlame();
+protected:
+ Sprite *_asTntMan;
+ void update();
+ void suUpdate();
+};
+
+class AsScene1201Match : public AnimatedSprite {
+public:
+ AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ int _status;
+ void update();
+ uint32 hmOnDoorFrameAboutToMove(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmOnDoorFrameMoving(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmIdle(int messageNum, const MessageParam &param, Entity *sender);
+ void stOnDoorFrameMoving();
+ void stFallingFromDoorFrame();
+ void stOnDoorFrameAboutToMove();
+ void stIdleOnDoorFrame();
+ void stIdleOnFloor();
+};
+
+class AsScene1201Creature : public AnimatedSprite {
+public:
+ AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen);
+protected:
+ Scene *_parentScene;
+ Sprite *_klaymen;
+ int _countdown;
+ bool _klaymenTooClose;
+ void update();
+ uint32 hmWaiting(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmPincerSnap(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmPincerSnapKlaymen(int messageNum, const MessageParam &param, Entity *sender);
+ void stWaiting();
+ void stPincerSnap();
+ void stStartReachForTntDummy();
+ void stReachForTntDummy();
+ void stPincerSnapKlaymen();
+};
+
+class AsScene1201LeftDoor : public AnimatedSprite {
+public:
+ AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen);
+protected:
+ Sprite *_klaymen;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stCloseDoor();
+};
+
+class SsScene1201Tnt : public StaticSprite {
+public:
+ SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2);
+};
+
+class AsScene1202TntItem : public AnimatedSprite {
+public:
+ AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index);
+protected:
+ Scene *_parentScene;
+ int _itemIndex, _newPosition;
+ uint32 hmShowIdle(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmChangePosition(int messageNum, const MessageParam &param, Entity *sender);
+ void stShowIdle();
+ void stChangePositionFadeOut();
+ void stChangePositionFadeIn();
+ void stChangePositionDone();
+};
+
+class KmScene1201 : public Klaymen {
+public:
+ KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stCloseEyes();
+ void stTumbleHeadless();
+ void stFetchMatch();
+ void stLightMatch();
+
+ uint32 hmTumbleHeadless(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmMatch(int messageNum, const MessageParam &param, Entity *sender);
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1200_SPRITES_H */
diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp
index 8dbfcf616c..312fb85ae7 100644
--- a/engines/neverhood/modules/module1300.cpp
+++ b/engines/neverhood/modules/module1300.cpp
@@ -20,16 +20,15 @@
*
*/
-#include "neverhood/modules/module1300.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module1400.h"
-#include "neverhood/modules/module2200.h"
-#include "neverhood/gamemodule.h"
#include "neverhood/diskplayerscene.h"
+#include "neverhood/gamemodule.h"
#include "neverhood/menumodule.h"
-#include "neverhood/navigationscene.h"
-#include "neverhood/smackerscene.h"
+#include "neverhood/modules/module1000_sprites.h"
+#include "neverhood/modules/module1200_sprites.h"
+#include "neverhood/modules/module1300.h"
+#include "neverhood/modules/module1300_sprites.h"
+#include "neverhood/modules/module1400_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
namespace Neverhood {
@@ -45,7 +44,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 +55,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 +100,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
break;
}
}
-
+
}
Module1300::~Module1300() {
@@ -109,7 +108,7 @@ Module1300::~Module1300() {
}
void Module1300::createScene(int sceneNum, int which) {
- debug("Module1300::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1300::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 1:
@@ -218,7 +217,7 @@ void Module1300::createScene(int sceneNum, int which) {
SetUpdateHandler(&Module1300::updateScene);
_childObject->handleUpdate();
}
-
+
void Module1300::updateScene() {
if (!updateChild()) {
switch (_sceneNum) {
@@ -274,7 +273,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);
@@ -311,113 +310,6 @@ void Module1300::updateScene() {
}
}
-AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- _x = 320;
- _y = 240;
- createSurface1(0x88148150, 500);
- if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) {
- startAnimation(0x88148150, 0, -1);
- _newStickFrameIndex = 0;
- } else {
- startAnimation(0x88148150, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- }
- loadSound(0, 0x68895082);
- loadSound(1, 0x689BD0C1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1302Bridge::handleMessage);
-}
-
-uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- stLowerBridge();
- break;
- case 0x4809:
- stRaiseBridge();
- break;
- }
- return messageResult;
-}
-
-void AsScene1302Bridge::stLowerBridge() {
- startAnimation(0x88148150, 0, -1);
- playSound(1);
- NextState(&AsScene1302Bridge::cbLowerBridgeEvent);
-}
-
-void AsScene1302Bridge::stRaiseBridge() {
- startAnimation(0x88148150, 7, -1);
- _playBackwards = true;
- _newStickFrameIndex = 0;
- playSound(0);
-}
-
-void AsScene1302Bridge::cbLowerBridgeEvent() {
- sendMessage(_parentScene, 0x2032, 0);
- startAnimation(0x88148150, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
-SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm)
- : StaticSprite(vm, 0x11122122, 200) {
-
- _firstY = _y;
- if (getGlobalVar(V_FLYTRAP_RING_FENCE))
- _y += 152;
- loadSound(0, 0x7A00400C);
- loadSound(1, 0x78184098);
- SetUpdateHandler(&SsScene1302Fence::update);
- SetMessageHandler(&SsScene1302Fence::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void SsScene1302Fence::update() {
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4808:
- playSound(0);
- SetMessageHandler(NULL);
- SetSpriteUpdate(&SsScene1302Fence::suMoveDown);
- break;
- case 0x4809:
- playSound(1);
- SetMessageHandler(NULL);
- SetSpriteUpdate(&SsScene1302Fence::suMoveUp);
- break;
- }
- return messageResult;
-}
-
-void SsScene1302Fence::suMoveDown() {
- if (_y < _firstY + 152)
- _y += 8;
- else {
- SetMessageHandler(&SsScene1302Fence::handleMessage);
- SetSpriteUpdate(NULL);
- }
-}
-
-void SsScene1302Fence::suMoveUp() {
- if (_y > _firstY)
- _y -= 8;
- else {
- SetMessageHandler(&SsScene1302Fence::handleMessage);
- SetSpriteUpdate(NULL);
- }
-}
-
Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
@@ -459,7 +351,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 +405,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;
@@ -581,56 +473,8 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam &param, Entit
return messageResult;
}
-AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- createSurface(200, 128, 315);
- _x = 289;
- _y = 390;
- startAnimation(0x800278D2, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1303Balloon::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
-}
-
-uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x2000:
- stPopBalloon();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x020B0003)
- playSound(0, 0x742B0055);
- break;
- case 0x3002:
- playSound(0, 0x470007EE);
- stopAnimation();
- setVisible(false);
- SetMessageHandler(NULL);
- break;
- }
- return messageResult;
-}
-
-void AsScene1303Balloon::stPopBalloon() {
- startAnimation(0xAC004CD0, 0, -1);
- SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped);
-}
-
Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule)
- : Scene(vm, parentModule) {
+ : Scene(vm, parentModule), _asBalloon(NULL) {
SetMessageHandler(&Scene1303::handleMessage);
@@ -643,7 +487,7 @@ Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule)
_asBalloon = insertSprite<AsScene1303Balloon>(this);
addCollisionSprite(_asBalloon);
}
-
+
_sprite1 = insertStaticSprite(0xA014216B, 1100);
insertKlaymen<KmScene1303>(207, 332);
@@ -668,39 +512,16 @@ uint32 Scene1303::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-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
- SetMessageHandler(&AsScene1304Needle::handleMessage);
-}
-
-uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setGlobalVar(V_HAS_NEEDLE, 1);
- setVisible(false);
- SetMessageHandler(NULL);
- break;
- }
- return messageResult;
-}
-
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,104 +595,19 @@ Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which)
insertKlaymen<KmScene1305>(212, 441);
setMessageList(0x004B6E48);
}
-
+
}
uint32 Scene1305::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
return Scene::handleMessage(messageNum, param, sender);
}
-AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true),
- _countdown(0) {
-
- _x = 320;
- _y = 240;
- createSurface1(0x043B0270, 100);
- startAnimation(0x043B0270, 0, -1);
- _newStickFrameIndex = 0;
- loadSound(0, 0x1C100E83);
- loadSound(1, 0x1C08CEC5);
- loadSound(2, 0x5D011E87);
- SetMessageHandler(&AsScene1306Elevator::handleMessage);
-}
-
-void AsScene1306Elevator::update() {
- if (_isUp && _countdown != 0 && (--_countdown == 0))
- stGoingDown();
- AnimatedSprite::update();
- if (_currFrameIndex == 7) {
- playSound(1);
- _asElevatorDoor->setVisible(false);
- }
-}
-
-void AsScene1306Elevator::upGoingDown() {
- AnimatedSprite::update();
- if (_currFrameIndex == 5)
- _asElevatorDoor->setVisible(true);
-}
-
-uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2001:
- if (_isUp)
- _countdown = 144;
- messageResult = _isUp ? 1 : 0;
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- if (_isDown)
- stGoingUp();
- break;
- }
- return messageResult;
-}
-
-void AsScene1306Elevator::stGoingUp() {
- setVisible(true);
- _isDown = false;
- startAnimation(0x043B0270, 0, -1);
- playSound(0);
- SetUpdateHandler(&AsScene1306Elevator::update);
- NextState(&AsScene1306Elevator::cbGoingUpEvent);
-}
-
-void AsScene1306Elevator::cbGoingUpEvent() {
- sendMessage(_parentScene, 0x4808, 0);
- _isUp = true;
- _countdown = 144;
- stopAnimation();
- setVisible(false);
- SetUpdateHandler(&AsScene1306Elevator::update);
-}
-
-void AsScene1306Elevator::stGoingDown() {
- _isUp = false;
- setVisible(true);
- startAnimation(0x043B0270, -1, -1);
- _playBackwards = true;
- playSound(1);
- SetUpdateHandler(&AsScene1306Elevator::upGoingDown);
- NextState(&AsScene1306Elevator::cbGoingDownEvent);
-}
-
-void AsScene1306Elevator::cbGoingDownEvent() {
- _isDown = true;
- sendMessage(_parentScene, 0x4809, 0);
- stopAnimation();
- SetUpdateHandler(&AsScene1306Elevator::update);
-}
-
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 +685,7 @@ Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which)
}
}
-
+
Scene1306::~Scene1306() {
setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0);
}
@@ -1039,196 +775,14 @@ uint32 Scene1306::handleMessage416EB0(int messageNum, const MessageParam &param,
return 0;
}
-static const uint32 kAsScene1307KeyResourceList1[] = {
- 0x0438069C, 0x45B0023C, 0x05700217
-};
-
-static const uint32 kAsScene1307KeyResourceList2[] = {
- 0x04441334, 0x061433F0, 0x06019390
-};
-
-static const uint32 kAsScene1307KeyResourceList3[] = {
- 0x11A80030, 0x178812B1, 0x1488121C
-};
-
-static const uint32 *kAsScene1307KeyResourceLists[] = {
- kAsScene1307KeyResourceList1,
- kAsScene1307KeyResourceList2,
- kAsScene1307KeyResourceList3
-};
-
-static const int kAsScene1307KeySurfacePriorities[] = {
- 700, 500, 300, 100
-};
-
-const uint kAsScene1307KeyPointsCount = 12;
-
-static const NPoint kAsScene1307KeyPoints[] = {
- {-2, 0}, {-5, 0}, { 5, 0},
- {12, 0}, {17, 0}, {25, 0},
- {16, -2}, {10, -6}, { 0, -7},
- {-7, -3}, {-3, 4}, { 2, 2}
-};
-
-const uint kAsScene1307KeyFrameIndicesCount = 20;
-
-static const int16 kAsScene1307KeyFrameIndices[] = {
- 1, 4, 8, 11, 15, 16, 17, 17, 17, 16,
- 15, 14, 12, 10, 9, 7, 5, 3, 2, 1
-};
-
-const int kAsScene1307KeyDivValue = 200;
-const int16 kAsScene1307KeyXDelta = 70;
-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];
-
- _dataResource.load(0x22102142);
- _pointList = _dataResource.getPointArray(0xAC849240);
- pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
- _x = pt.x;
- _y = pt.y;
- createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148);
- startAnimation(fileHashes[0], 0, -1);
- loadSound(0, 0xDC4A1280);
- loadSound(1, 0xCC021233);
- loadSound(2, 0xC4C23844);
- loadSound(3, 0xC4523208);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1307Key::handleMessage);
-}
-
-uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_isClickable) {
- sendMessage(_parentScene, 0x4826, 0);
- stRemoveKey();
- messageResult = 1;
- }
- break;
- case 0x2000:
- _isClickable = param.asInteger() != 0;
- break;
- case 0x2001:
- setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger());
- stMoveKey();
- break;
- case 0x2003:
- playSound(3);
- stUnlock();
- break;
- case 0x2004:
- playSound(2);
- stInsert();
- break;
- }
- return messageResult;
-}
-
-void AsScene1307Key::suRemoveKey() {
- if (_pointIndex < kAsScene1307KeyPointsCount) {
- _x += kAsScene1307KeyPoints[_pointIndex].x;
- _y += kAsScene1307KeyPoints[_pointIndex].y;
- updateBounds();
- _pointIndex++;
- } else {
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1307Key::suInsertKey() {
- if (_pointIndex < kAsScene1307KeyPointsCount) {
- _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x;
- _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y;
- updateBounds();
- _pointIndex++;
- if (_pointIndex == 7)
- playSound(0);
- } else {
- SetSpriteUpdate(NULL);
- sendMessage(_parentScene, 0x2002, 0);
- }
-}
-
-void AsScene1307Key::suMoveKey() {
- if (_pointIndex < kAsScene1307KeyFrameIndicesCount) {
- _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex];
- _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue;
- _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue;
- updateBounds();
- _pointIndex++;
- } else {
- NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
- _x = pt.x + kAsScene1307KeyXDelta;
- _y = pt.y + kAsScene1307KeyYDelta;
- stInsertKey();
- }
-}
-
-void AsScene1307Key::stRemoveKey() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
- _pointIndex = 0;
- startAnimation(fileHashes[0], 0, -1);
- playSound(1);
- SetSpriteUpdate(&AsScene1307Key::suRemoveKey);
-}
-
-void AsScene1307Key::stInsertKey() {
- _pointIndex = 0;
- sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]);
- setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]);
- _newStickFrameIndex = STICK_LAST_FRAME;
- SetSpriteUpdate(&AsScene1307Key::suInsertKey);
-}
-
-void AsScene1307Key::stMoveKey() {
- NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
- int16 newX = pt.x + kAsScene1307KeyXDelta;
- int16 newY = pt.y + kAsScene1307KeyYDelta;
- sendMessage(_parentScene, 0x1022, 1000);
- setClipRect(0, 0, 640, 480);
- _prevX = _x;
- _prevY = _y;
- if (newX == _x && newY == _y) {
- stInsertKey();
- } else {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
- _pointIndex = 0;
- _frameIndex = 0;
- _deltaX = newX - _x;
- _deltaY = newY - _y;
- startAnimation(fileHashes[0], 0, -1);
- SetSpriteUpdate(&AsScene1307Key::suMoveKey);
- }
-}
-
-void AsScene1307Key::stUnlock() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
- startAnimation(fileHashes[1], 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
-void AsScene1307Key::stInsert() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
- startAnimation(fileHashes[2], 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule), _countdown(0), _asCurrKey(NULL),
_isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) {
Sprite *tempSprite;
-
+
_vm->gameModule()->initKeySlotsPuzzle();
-
+
_dataResource.load(0x22102142);
_keyHolePoints = _dataResource.getPointArray(0xAC849240);
@@ -1279,7 +833,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 +848,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;
}
@@ -1360,171 +914,13 @@ static const uint32 kScene1308NumberFileHashes[] = {
0x00306322
};
-AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) {
-
- setVisible(false);
- stopAnimation();
- SetMessageHandler(&AsScene1308JaggyDoor::handleMessage);
-}
-
-uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- stOpenDoor();
- break;
- case 0x4809:
- stCloseDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene1308JaggyDoor::stOpenDoor() {
- startAnimation(0xBA0AE050, 0, -1);
- setVisible(true);
- playSound(0, calcHash("fxDoorOpen38"));
- NextState(&AsScene1308JaggyDoor::stOpenDoorDone);
-}
-
-void AsScene1308JaggyDoor::stOpenDoorDone() {
- sendMessage(_parentScene, 0x2000, 0);
- stopAnimation();
- setVisible(false);
-}
-
-void AsScene1308JaggyDoor::stCloseDoor() {
- startAnimation(0xBA0AE050, -1, -1);
- _playBackwards = true;
- setVisible(true);
- playSound(0, calcHash("fxDoorClose38"));
- NextState(&AsScene1308JaggyDoor::stCloseDoorDone);
-}
-
-void AsScene1308JaggyDoor::stCloseDoorDone() {
- sendMessage(_parentScene, 0x2001, 0);
- stopAnimation();
-}
-
-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) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1308KeyboardDoor::stFallingKeys() {
- startAnimation(0x6238B191, 0, -1);
- _x = 580;
- _y = 383;
- NextState(&AsScene1308KeyboardDoor::stFallingKeysDone);
-}
-
-void AsScene1308KeyboardDoor::stFallingKeysDone() {
- sendMessage(_parentScene, 0x2004, 0);
- stopAnimation();
- setVisible(false);
-}
-
-AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) {
-
- setVisible(false);
- stopAnimation();
- Entity::_priority = 1200;
- SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage);
-}
-
-uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2002:
- stFadeIn();
- break;
- case 0x2003:
- stFadeOut();
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1308LightWallSymbols::stFadeIn() {
- startAnimation(0x80180A10, 0, -1);
- setVisible(true);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
-void AsScene1308LightWallSymbols::stFadeOut() {
- startAnimation(0x80180A10, -1, -1);
- _playBackwards = true;
- NextState(&AsScene1308LightWallSymbols::stFadeOutDone);
-}
-
-void AsScene1308LightWallSymbols::stFadeOutDone() {
- sendMessage(_parentScene, 0x2003, 0);
- stopAnimation();
- setVisible(false);
-}
-
-SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index)
- : StaticSprite(vm, fileHash, 100) {
-
- setVisible(false);
- _x = _spriteResource.getPosition().x + index * 20;
- updatePosition();
-}
-
-AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- _x = 286;
- _y = 429;
- createSurface1(0xA282C472, 100);
- startAnimation(0xA282C472, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1308Mouse::handleMessage);
-}
-
-uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x66382026)
- playSound(0, 0x0CD84468);
- else if (param.asInteger() == 0x6E28061C)
- playSound(0, 0x78C8402C);
- else if (param.asInteger() == 0x462F0410)
- playSound(0, 0x60984E28);
- break;
- }
- return messageResult;
-}
-
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 +932,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 +942,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 +1094,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());
@@ -1711,6 +1107,7 @@ Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule)
void Scene1317::update() {
if (_smackerFileHash) {
_smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame);
+ _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
_smackerFileHash = 0;
}
Scene::update();
@@ -1719,7 +1116,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) {
@@ -1730,14 +1127,15 @@ void Scene1317::upChooseKing() {
if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0))
stNoDecisionYet();
-
+
if (_smackerFileHash) {
_smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame);
+ _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
_smackerFileHash = 0;
}
Scene::update();
-
+
}
uint32 Scene1317::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1749,7 +1147,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/module1300.h b/engines/neverhood/modules/module1300.h
index 501f76304f..2f59ff16c2 100644
--- a/engines/neverhood/modules/module1300.h
+++ b/engines/neverhood/modules/module1300.h
@@ -30,8 +30,6 @@
namespace Neverhood {
-// Module1300
-
class Module1300 : public Module {
public:
Module1300(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -43,28 +41,6 @@ protected:
void updateScene();
};
-class AsScene1302Bridge : public AnimatedSprite {
-public:
- AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stLowerBridge();
- void stRaiseBridge();
- void cbLowerBridgeEvent();
-};
-
-class SsScene1302Fence : public StaticSprite {
-public:
- SsScene1302Fence(NeverhoodEngine *vm);
-protected:
- int16 _firstY;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suMoveDown();
- void suMoveUp();
-};
-
class Scene1302 : public Scene {
public:
Scene1302(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -84,16 +60,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene1303Balloon : public AnimatedSprite {
-public:
- AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmBalloonPopped(int messageNum, const MessageParam &param, Entity *sender);
- void stPopBalloon();
-};
-
class Scene1303 : public Scene {
public:
Scene1303(NeverhoodEngine *vm, Module *parentModule);
@@ -103,14 +69,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene1304Needle : public AnimatedSprite {
-public:
- AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1304 : public Scene {
public:
Scene1304(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -128,24 +86,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene1306Elevator : public AnimatedSprite {
-public:
- AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor);
-protected:
- Scene *_parentScene;
- AnimatedSprite *_asElevatorDoor;
- bool _isUp;
- bool _isDown;
- int _countdown;
- void update();
- void upGoingDown();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stGoingUp();
- void cbGoingUpEvent();
- void stGoingDown();
- void cbGoingDownEvent();
-};
-
class Scene1306 : public Scene {
public:
Scene1306(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -161,30 +101,6 @@ protected:
uint32 handleMessage416EB0(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene1307Key : public AnimatedSprite {
-public:
- AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects);
-protected:
- Scene *_parentScene;
- NPointArray *_pointList;
- uint _pointIndex;
- int _frameIndex;
- uint _keyIndex;
- NRect *_clipRects;
- bool _isClickable;
- int16 _prevX, _prevY;
- int16 _deltaX, _deltaY;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suRemoveKey();
- void suInsertKey();
- void suMoveKey();
- void stRemoveKey();
- void stInsertKey();
- void stMoveKey();
- void stUnlock();
- void stInsert();
-};
-
class Scene1307 : public Scene {
public:
Scene1307(NeverhoodEngine *vm, Module *parentModule);
@@ -202,51 +118,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene1308JaggyDoor : public AnimatedSprite {
-public:
- AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stOpenDoorDone();
- void stCloseDoor();
- void stCloseDoorDone();
-};
-
-class AsScene1308KeyboardDoor : public AnimatedSprite {
-public:
- AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stFallingKeys();
- void stFallingKeysDone();
-};
-
-class AsScene1308LightWallSymbols : public AnimatedSprite {
-public:
- AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stFadeIn();
- void stFadeOut();
- void stFadeOutDone();
-};
-
-class SsScene1308Number : public StaticSprite {
-public:
- SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index);
-};
-
-class AsScene1308Mouse : public AnimatedSprite {
-public:
- AsScene1308Mouse(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1308 : public Scene {
public:
Scene1308(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module1300_sprites.cpp b/engines/neverhood/modules/module1300_sprites.cpp
new file mode 100644
index 0000000000..a65f2363a3
--- /dev/null
+++ b/engines/neverhood/modules/module1300_sprites.cpp
@@ -0,0 +1,935 @@
+/* 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 "neverhood/modules/module1300_sprites.h"
+
+namespace Neverhood {
+
+AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ _x = 320;
+ _y = 240;
+ createSurface1(0x88148150, 500);
+ if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) {
+ startAnimation(0x88148150, 0, -1);
+ _newStickFrameIndex = 0;
+ } else {
+ startAnimation(0x88148150, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ }
+ loadSound(0, 0x68895082);
+ loadSound(1, 0x689BD0C1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1302Bridge::handleMessage);
+}
+
+uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ stLowerBridge();
+ break;
+ case 0x4809:
+ stRaiseBridge();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1302Bridge::stLowerBridge() {
+ startAnimation(0x88148150, 0, -1);
+ playSound(1);
+ NextState(&AsScene1302Bridge::cbLowerBridgeEvent);
+}
+
+void AsScene1302Bridge::stRaiseBridge() {
+ startAnimation(0x88148150, 7, -1);
+ _playBackwards = true;
+ _newStickFrameIndex = 0;
+ playSound(0);
+}
+
+void AsScene1302Bridge::cbLowerBridgeEvent() {
+ sendMessage(_parentScene, 0x2032, 0);
+ startAnimation(0x88148150, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm)
+ : StaticSprite(vm, 0x11122122, 200) {
+
+ _firstY = _y;
+ if (getGlobalVar(V_FLYTRAP_RING_FENCE))
+ _y += 152;
+ loadSound(0, 0x7A00400C);
+ loadSound(1, 0x78184098);
+ SetUpdateHandler(&SsScene1302Fence::update);
+ SetMessageHandler(&SsScene1302Fence::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void SsScene1302Fence::update() {
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4808:
+ playSound(0);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(&SsScene1302Fence::suMoveDown);
+ break;
+ case 0x4809:
+ playSound(1);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(&SsScene1302Fence::suMoveUp);
+ break;
+ }
+ return messageResult;
+}
+
+void SsScene1302Fence::suMoveDown() {
+ if (_y < _firstY + 152)
+ _y += 8;
+ else {
+ SetMessageHandler(&SsScene1302Fence::handleMessage);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void SsScene1302Fence::suMoveUp() {
+ if (_y > _firstY)
+ _y -= 8;
+ else {
+ SetMessageHandler(&SsScene1302Fence::handleMessage);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(200, 128, 315);
+ _x = 289;
+ _y = 390;
+ startAnimation(0x800278D2, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1303Balloon::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+}
+
+uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x2000:
+ stPopBalloon();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x020B0003)
+ playSound(0, 0x742B0055);
+ break;
+ case 0x3002:
+ playSound(0, 0x470007EE);
+ stopAnimation();
+ setVisible(false);
+ SetMessageHandler(NULL);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1303Balloon::stPopBalloon() {
+ startAnimation(0xAC004CD0, 0, -1);
+ SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped);
+}
+
+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
+ SetMessageHandler(&AsScene1304Needle::handleMessage);
+}
+
+uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setGlobalVar(V_HAS_NEEDLE, 1);
+ setVisible(false);
+ SetMessageHandler(NULL);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true),
+ _countdown(0) {
+
+ _x = 320;
+ _y = 240;
+ createSurface1(0x043B0270, 100);
+ startAnimation(0x043B0270, 0, -1);
+ _newStickFrameIndex = 0;
+ loadSound(0, 0x1C100E83);
+ loadSound(1, 0x1C08CEC5);
+ loadSound(2, 0x5D011E87);
+ SetMessageHandler(&AsScene1306Elevator::handleMessage);
+}
+
+void AsScene1306Elevator::update() {
+ if (_isUp && _countdown != 0 && (--_countdown == 0))
+ stGoingDown();
+ AnimatedSprite::update();
+ if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) {
+ playSound(1);
+ _asElevatorDoor->setVisible(false);
+ }
+}
+
+void AsScene1306Elevator::upGoingDown() {
+ AnimatedSprite::update();
+ if (_currFrameIndex == 5)
+ _asElevatorDoor->setVisible(true);
+}
+
+uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2001:
+ if (_isUp)
+ _countdown = 144;
+ messageResult = _isUp ? 1 : 0;
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ if (_isDown)
+ stGoingUp();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1306Elevator::stGoingUp() {
+ setVisible(true);
+ _isDown = false;
+ startAnimation(0x043B0270, 0, -1);
+ playSound(0);
+ SetUpdateHandler(&AsScene1306Elevator::update);
+ NextState(&AsScene1306Elevator::cbGoingUpEvent);
+}
+
+void AsScene1306Elevator::cbGoingUpEvent() {
+ sendMessage(_parentScene, 0x4808, 0);
+ _isUp = true;
+ _countdown = 144;
+ stopAnimation();
+ setVisible(false);
+ SetUpdateHandler(&AsScene1306Elevator::update);
+}
+
+void AsScene1306Elevator::stGoingDown() {
+ _isUp = false;
+ setVisible(true);
+ startAnimation(0x043B0270, -1, -1);
+ _playBackwards = true;
+ playSound(1);
+ SetUpdateHandler(&AsScene1306Elevator::upGoingDown);
+ NextState(&AsScene1306Elevator::cbGoingDownEvent);
+}
+
+void AsScene1306Elevator::cbGoingDownEvent() {
+ _isDown = true;
+ sendMessage(_parentScene, 0x4809, 0);
+ stopAnimation();
+ SetUpdateHandler(&AsScene1306Elevator::update);
+}
+
+static const uint32 kAsScene1307KeyResourceList1[] = {
+ 0x0438069C, 0x45B0023C, 0x05700217
+};
+
+static const uint32 kAsScene1307KeyResourceList2[] = {
+ 0x04441334, 0x061433F0, 0x06019390
+};
+
+static const uint32 kAsScene1307KeyResourceList3[] = {
+ 0x11A80030, 0x178812B1, 0x1488121C
+};
+
+static const uint32 *kAsScene1307KeyResourceLists[] = {
+ kAsScene1307KeyResourceList1,
+ kAsScene1307KeyResourceList2,
+ kAsScene1307KeyResourceList3
+};
+
+static const int kAsScene1307KeySurfacePriorities[] = {
+ 700, 500, 300, 100
+};
+
+const uint kAsScene1307KeyPointsCount = 12;
+
+static const NPoint kAsScene1307KeyPoints[] = {
+ {-2, 0}, {-5, 0}, { 5, 0},
+ {12, 0}, {17, 0}, {25, 0},
+ {16, -2}, {10, -6}, { 0, -7},
+ {-7, -3}, {-3, 4}, { 2, 2}
+};
+
+const uint kAsScene1307KeyFrameIndicesCount = 20;
+
+static const int16 kAsScene1307KeyFrameIndices[] = {
+ 1, 4, 8, 11, 15, 16, 17, 17, 17, 16,
+ 15, 14, 12, 10, 9, 7, 5, 3, 2, 1
+};
+
+const int kAsScene1307KeyDivValue = 200;
+const int16 kAsScene1307KeyXDelta = 70;
+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];
+
+ _dataResource.load(0x22102142);
+ _pointList = _dataResource.getPointArray(0xAC849240);
+ pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
+ _x = pt.x;
+ _y = pt.y;
+ createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148);
+ startAnimation(fileHashes[0], 0, -1);
+ loadSound(0, 0xDC4A1280);
+ loadSound(1, 0xCC021233);
+ loadSound(2, 0xC4C23844);
+ loadSound(3, 0xC4523208);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1307Key::handleMessage);
+}
+
+uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_isClickable) {
+ sendMessage(_parentScene, 0x4826, 0);
+ stRemoveKey();
+ messageResult = 1;
+ }
+ break;
+ case 0x2000:
+ _isClickable = param.asInteger() != 0;
+ break;
+ case 0x2001:
+ setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger());
+ stMoveKey();
+ break;
+ case 0x2003:
+ playSound(3);
+ stUnlock();
+ break;
+ case 0x2004:
+ playSound(2);
+ stInsert();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1307Key::suRemoveKey() {
+ if (_pointIndex < kAsScene1307KeyPointsCount) {
+ _x += kAsScene1307KeyPoints[_pointIndex].x;
+ _y += kAsScene1307KeyPoints[_pointIndex].y;
+ updateBounds();
+ _pointIndex++;
+ } else {
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1307Key::suInsertKey() {
+ if (_pointIndex < kAsScene1307KeyPointsCount) {
+ _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x;
+ _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y;
+ updateBounds();
+ _pointIndex++;
+ if (_pointIndex == 7)
+ playSound(0);
+ } else {
+ SetSpriteUpdate(NULL);
+ sendMessage(_parentScene, 0x2002, 0);
+ }
+}
+
+void AsScene1307Key::suMoveKey() {
+ if (_pointIndex < kAsScene1307KeyFrameIndicesCount) {
+ _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex];
+ _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue;
+ _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue;
+ updateBounds();
+ _pointIndex++;
+ } else {
+ NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
+ _x = pt.x + kAsScene1307KeyXDelta;
+ _y = pt.y + kAsScene1307KeyYDelta;
+ stInsertKey();
+ }
+}
+
+void AsScene1307Key::stRemoveKey() {
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ _pointIndex = 0;
+ startAnimation(fileHashes[0], 0, -1);
+ playSound(1);
+ SetSpriteUpdate(&AsScene1307Key::suRemoveKey);
+}
+
+void AsScene1307Key::stInsertKey() {
+ _pointIndex = 0;
+ sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]);
+ setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ SetSpriteUpdate(&AsScene1307Key::suInsertKey);
+}
+
+void AsScene1307Key::stMoveKey() {
+ NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
+ int16 newX = pt.x + kAsScene1307KeyXDelta;
+ int16 newY = pt.y + kAsScene1307KeyYDelta;
+ sendMessage(_parentScene, 0x1022, 1000);
+ setClipRect(0, 0, 640, 480);
+ _prevX = _x;
+ _prevY = _y;
+ if (newX == _x && newY == _y) {
+ stInsertKey();
+ } else {
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ _pointIndex = 0;
+ _frameIndex = 0;
+ _deltaX = newX - _x;
+ _deltaY = newY - _y;
+ startAnimation(fileHashes[0], 0, -1);
+ SetSpriteUpdate(&AsScene1307Key::suMoveKey);
+ }
+}
+
+void AsScene1307Key::stUnlock() {
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ startAnimation(fileHashes[1], 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+void AsScene1307Key::stInsert() {
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ startAnimation(fileHashes[2], 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) {
+
+ setVisible(false);
+ stopAnimation();
+ SetMessageHandler(&AsScene1308JaggyDoor::handleMessage);
+}
+
+uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ stOpenDoor();
+ break;
+ case 0x4809:
+ stCloseDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1308JaggyDoor::stOpenDoor() {
+ startAnimation(0xBA0AE050, 0, -1);
+ setVisible(true);
+ playSound(0, calcHash("fxDoorOpen38"));
+ NextState(&AsScene1308JaggyDoor::stOpenDoorDone);
+}
+
+void AsScene1308JaggyDoor::stOpenDoorDone() {
+ sendMessage(_parentScene, 0x2000, 0);
+ stopAnimation();
+ setVisible(false);
+}
+
+void AsScene1308JaggyDoor::stCloseDoor() {
+ startAnimation(0xBA0AE050, -1, -1);
+ _playBackwards = true;
+ setVisible(true);
+ playSound(0, calcHash("fxDoorClose38"));
+ NextState(&AsScene1308JaggyDoor::stCloseDoorDone);
+}
+
+void AsScene1308JaggyDoor::stCloseDoorDone() {
+ sendMessage(_parentScene, 0x2001, 0);
+ stopAnimation();
+}
+
+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) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1308KeyboardDoor::stFallingKeys() {
+ startAnimation(0x6238B191, 0, -1);
+ _x = 580;
+ _y = 383;
+ NextState(&AsScene1308KeyboardDoor::stFallingKeysDone);
+}
+
+void AsScene1308KeyboardDoor::stFallingKeysDone() {
+ sendMessage(_parentScene, 0x2004, 0);
+ stopAnimation();
+ setVisible(false);
+}
+
+AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) {
+
+ setVisible(false);
+ stopAnimation();
+ Entity::_priority = 1200;
+ SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage);
+}
+
+uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2002:
+ stFadeIn();
+ break;
+ case 0x2003:
+ stFadeOut();
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1308LightWallSymbols::stFadeIn() {
+ startAnimation(0x80180A10, 0, -1);
+ setVisible(true);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+void AsScene1308LightWallSymbols::stFadeOut() {
+ startAnimation(0x80180A10, -1, -1);
+ _playBackwards = true;
+ NextState(&AsScene1308LightWallSymbols::stFadeOutDone);
+}
+
+void AsScene1308LightWallSymbols::stFadeOutDone() {
+ sendMessage(_parentScene, 0x2003, 0);
+ stopAnimation();
+ setVisible(false);
+}
+
+SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index)
+ : StaticSprite(vm, fileHash, 100) {
+
+ setVisible(false);
+ _x = _spriteResource.getPosition().x + index * 20;
+ updatePosition();
+}
+
+AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ _x = 286;
+ _y = 429;
+ createSurface1(0xA282C472, 100);
+ startAnimation(0xA282C472, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1308Mouse::handleMessage);
+}
+
+uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x66382026)
+ playSound(0, 0x0CD84468);
+ else if (param.asInteger() == 0x6E28061C)
+ playSound(0, 0x78C8402C);
+ else if (param.asInteger() == 0x462F0410)
+ playSound(0, 0x60984E28);
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1303::KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1303::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4804:
+ GotoState(&Klaymen::stPeekWall1);
+ break;
+ case 0x483B:
+ GotoState(&Klaymen::stPeekWallReturn);
+ break;
+ case 0x483C:
+ GotoState(&Klaymen::stPeekWall2);
+ break;
+ }
+ return 0;
+}
+
+KmScene1304::KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+KmScene1305::KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ GotoState(&KmScene1305::stCrashDown);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ }
+ return 0;
+}
+
+void KmScene1305::stCrashDown() {
+ playSound(0, 0x41648271);
+ _busyStatus = 1;
+ _acceptInput = false;
+ startAnimationByHash(0x000BAB02, 0x88003000, 0);
+ SetUpdateHandler(&Klaymen::update);
+ SetSpriteUpdate(NULL);
+ SetMessageHandler(&Klaymen::hmLowLevelAnimation);
+ NextState(&KmScene1305::stCrashDownFinished);
+}
+
+void KmScene1305::stCrashDownFinished() {
+ setDoDeltaX(2);
+ stTryStandIdle();
+}
+
+KmScene1306::KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481A:
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ else
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ else
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0xEE084A04);
+ break;
+ case 0x483E:
+ teleporterDisappear(0xB86A4274);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1308::KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
+ else
+ GotoState(&Klaymen::stMoveObjectFaceObject);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stUseLever);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stInsertKey);
+ else
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x4827:
+ GotoState(&Klaymen::stReleaseLever);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1300_sprites.h b/engines/neverhood/modules/module1300_sprites.h
new file mode 100644
index 0000000000..e044d3cec8
--- /dev/null
+++ b/engines/neverhood/modules/module1300_sprites.h
@@ -0,0 +1,200 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE1300_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1300_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/smackerplayer.h"
+
+namespace Neverhood {
+
+class AsScene1302Bridge : public AnimatedSprite {
+public:
+ AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stLowerBridge();
+ void stRaiseBridge();
+ void cbLowerBridgeEvent();
+};
+
+class SsScene1302Fence : public StaticSprite {
+public:
+ SsScene1302Fence(NeverhoodEngine *vm);
+protected:
+ int16 _firstY;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoveDown();
+ void suMoveUp();
+};
+
+class AsScene1303Balloon : public AnimatedSprite {
+public:
+ AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmBalloonPopped(int messageNum, const MessageParam &param, Entity *sender);
+ void stPopBalloon();
+};
+
+class AsScene1304Needle : public AnimatedSprite {
+public:
+ AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene1306Elevator : public AnimatedSprite {
+public:
+ AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor);
+protected:
+ Scene *_parentScene;
+ AnimatedSprite *_asElevatorDoor;
+ bool _isUp;
+ bool _isDown;
+ int _countdown;
+ void update();
+ void upGoingDown();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stGoingUp();
+ void cbGoingUpEvent();
+ void stGoingDown();
+ void cbGoingDownEvent();
+};
+
+class AsScene1307Key : public AnimatedSprite {
+public:
+ AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects);
+protected:
+ Scene *_parentScene;
+ NPointArray *_pointList;
+ uint _pointIndex;
+ int _frameIndex;
+ uint _keyIndex;
+ NRect *_clipRects;
+ bool _isClickable;
+ int16 _prevX, _prevY;
+ int16 _deltaX, _deltaY;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suRemoveKey();
+ void suInsertKey();
+ void suMoveKey();
+ void stRemoveKey();
+ void stInsertKey();
+ void stMoveKey();
+ void stUnlock();
+ void stInsert();
+};
+
+class AsScene1308JaggyDoor : public AnimatedSprite {
+public:
+ AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stOpenDoorDone();
+ void stCloseDoor();
+ void stCloseDoorDone();
+};
+
+class AsScene1308KeyboardDoor : public AnimatedSprite {
+public:
+ AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stFallingKeys();
+ void stFallingKeysDone();
+};
+
+class AsScene1308LightWallSymbols : public AnimatedSprite {
+public:
+ AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stFadeIn();
+ void stFadeOut();
+ void stFadeOutDone();
+};
+
+class SsScene1308Number : public StaticSprite {
+public:
+ SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index);
+};
+
+class AsScene1308Mouse : public AnimatedSprite {
+public:
+ AsScene1308Mouse(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1303 : public Klaymen {
+public:
+ KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1304 : public Klaymen {
+public:
+ KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1305 : public Klaymen {
+public:
+ KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stCrashDown();
+ void stCrashDownFinished();
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1306 : public Klaymen {
+public:
+ KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1308 : public Klaymen {
+public:
+ KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1300_SPRITES_H */
diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp
index 4f69637ee0..2fc1052ab1 100644
--- a/engines/neverhood/modules/module1400.cpp
+++ b/engines/neverhood/modules/module1400.cpp
@@ -20,18 +20,20 @@
*
*/
-#include "neverhood/modules/module1400.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module2100.h"
-#include "neverhood/modules/module2200.h"
#include "neverhood/diskplayerscene.h"
#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1000_sprites.h"
+#include "neverhood/modules/module1200_sprites.h"
+#include "neverhood/modules/module1400.h"
+#include "neverhood/modules/module1400_sprites.h"
+#include "neverhood/modules/module2100_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
namespace Neverhood {
Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x00AD0012, 0x06333232);
_vm->_soundMan->addMusic(0x00AD0012, 0x624A220E);
@@ -47,7 +49,7 @@ Module1400::~Module1400() {
}
void Module1400::createScene(int sceneNum, int which) {
- debug("Module1400::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1400::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -135,500 +137,9 @@ void Module1400::updateScene() {
}
}
-// Scene1401
-
-AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) {
-
- createSurface(900, 152, 147);
- _x = 454;
- _y = 217;
- startAnimation(0x4C210500, 0, -1);
- SetUpdateHandler(&AsScene1401Pipe::update);
- SetMessageHandler(&AsScene1401Pipe::handleMessage);
-}
-
-AsScene1401Pipe::~AsScene1401Pipe() {
- _vm->_soundMan->deleteSoundGroup(0x01104C08);
-}
-
-void AsScene1401Pipe::update() {
- AnimatedSprite::update();
- if (_countdown1 != 0 && (--_countdown1 == 0))
- stDoneSucking();
- if (_countdown2 != 0 && (--_countdown2 == 0)) {
- _vm->_soundMan->addSound(0x01104C08, 0x4A116437);
- _vm->_soundMan->playSoundLooping(0x4A116437);
- }
-}
-
-void AsScene1401Pipe::upSuckInProjector() {
- AnimatedSprite::update();
- if (_countdown1 != 0)
- _countdown1--;
-}
-
-uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x0A8A1490)
- playSound(1, 0x6AB6666F);
- break;
- case 0x2000:
- _countdown1 = 70;
- _countdown2 = 8;
- stStartSucking();
- break;
- case 0x483A:
- stSuckInProjector();
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- if (_countdown1 != 0)
- stStartSucking();
- else
- stDoneSucking();
- SetMessageHandler(&AsScene1401Pipe::handleMessage);
- SetUpdateHandler(&AsScene1401Pipe::update);
- break;
- }
- return messageResult;
-}
-
-void AsScene1401Pipe::stStartSucking() {
- startAnimation(0x4C240100, 0, -1);
- playSound(0, 0x4A30063F);
-}
-
-void AsScene1401Pipe::stDoneSucking() {
- _vm->_soundMan->deleteSound(0x4A116437);
- playSound(0, 0x4A120435);
- startAnimation(0x4C210500, 0, -1);
-}
-
-void AsScene1401Pipe::stSuckInProjector() {
- startAnimation(0x6C210810, 0, -1);
- SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector);
- SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector);
-}
-
-AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- createSurface(100, 71, 41);
- _x = 478;
- _y = 433;
- startAnimation(0xA282C472, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1401Mouse::handleMessage);
-}
-
-uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x66382026)
- playSound(0, 0x0CD84468);
- else if (param.asInteger() == 0x6E28061C)
- playSound(0, 0x78C8402C);
- else if (param.asInteger() == 0x462F0410)
- playSound(0, 0x60984E28);
- break;
- case 0x4839:
- stSuckedIn();
- break;
- }
- return messageResult;
-}
-
-void AsScene1401Mouse::suSuckedIn() {
- AnimatedSprite::updateDeltaXY();
- if (_collisionBounds.y1 <= 150) {
- playSound(0, 0x0E32247F);
- stopAnimation();
- setVisible(false);
- SetMessageHandler(NULL);
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1401Mouse::stSuckedIn() {
- startAnimation(0x34880040, 0, -1);
- SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn);
-}
-
-AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- createSurface(200, 152, 147);
- _x = 427;
- _y = 433;
- startAnimation(0x461A1490, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1401Cheese::handleMessage);
-}
-
-uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4839:
- stSuckedIn();
- break;
- }
- return messageResult;
-}
-
-void AsScene1401Cheese::suSuckedIn() {
- AnimatedSprite::updateDeltaXY();
- if (_collisionBounds.y1 <= 150) {
- playSound(0, 0x18020439);
- stopAnimation();
- setVisible(false);
- SetMessageHandler(NULL);
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1401Cheese::stSuckedIn() {
- startAnimation(0x103B8020, 0, -1);
- SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn);
-}
-
-AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen)
- : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) {
-
- _x = 320;
- _y = 240;
- createSurface1(0x04551900, 100);
- if (isOpen) {
- startAnimation(0x04551900, -1, -1);
- _countdown = 48;
- } else {
- stopAnimation();
- setVisible(false);
- }
- _newStickFrameIndex = STICK_LAST_FRAME;
- SetUpdateHandler(&AsScene1401BackDoor::update);
- SetMessageHandler(&AsScene1401BackDoor::handleMessage);
-}
-
-void AsScene1401BackDoor::update() {
- if (_countdown != 0 && (--_countdown == 0))
- stCloseDoor();
- AnimatedSprite::update();
-}
-
-
-uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2001:
- if (_isOpen)
- _countdown = 168;
- messageResult = _isOpen ? 1 : 0;
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- _countdown = 168;
- if (!_isOpen)
- stOpenDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene1401BackDoor::stOpenDoor() {
- _isOpen = true;
- setVisible(true);
- startAnimation(0x04551900, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- playSound(0, calcHash("fxDoorOpen24"));
-}
-
-void AsScene1401BackDoor::stCloseDoor() {
- _isOpen = false;
- setVisible(true);
- startAnimation(0x04551900, -1, -1);
- playSound(0, calcHash("fxDoorClose24"));
- _playBackwards = true;
- NextState(&AsScene1401BackDoor::stCloseDoorDone);
-}
-
-void AsScene1401BackDoor::stCloseDoorDone() {
- stopAnimation();
- setVisible(false);
-}
-
-static const AsCommonProjectorItem kAsCommonProjectorItems[] = {
- {{154, 453}, 4, 2, 0, 0, 1},
- {{104, 391}, 4, -1, -1, 1, 1},
- {{ 22, 447}, 6, -1, -1, 1, 1},
- {{112, 406}, 2, -1, -1, 1, 0},
- {{262, 433}, 1, 1, 0, 0, 0}
-};
-
-AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) {
-
- _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)];
- createSurface(990, 101, 182);
- startAnimation(0x10E3042B, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsCommonProjector::handleMessage);
- _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
- _lockedInSlot = true;
- moveProjector();
- setDoDeltaX(1);
- if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex)
- stStayLockedInSlot();
- loadSound(2, 0xC8C2507C);
-}
-
-AsCommonProjector::~AsCommonProjector() {
- _vm->_soundMan->deleteSoundGroup(0x05331081);
-}
-
-uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4807:
- setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108);
- if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex)
- stStartLockedInSlot();
- else
- stIdle();
- break;
- case 0x480B:
- if (param.asInteger() != 1) {
- if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount)
- incGlobalVar(V_PROJECTOR_SLOT, 1);
- } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0)
- incGlobalVar(V_PROJECTOR_SLOT, -1);
- stMoving();
- break;
- case 0x480C:
- // Check if the projector can be moved
- if (param.asInteger() != 1)
- messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0;
- else
- messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0;
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- case 0x4839:
- stStartSuckedIn();
- break;
- }
- return messageResult;
-}
-
-uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 &&
- param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) {
- sendMessage(_parentScene, 0x4826, 1);
- } else
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4807:
- sendMessage(_parentScene, 0x4807, 0);
- stStopProjecting();
- break;
- case 0x480B:
- if (param.asInteger() != 1) {
- if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount)
- incGlobalVar(V_PROJECTOR_SLOT, 1);
- } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0)
- incGlobalVar(V_PROJECTOR_SLOT, -1);
- stTurnToFront();
- break;
- case 0x480C:
- // Check if the projector can be moved
- if (param.asInteger() != 1)
- messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0;
- else
- messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0;
- break;
- case 0x480F:
- stStartProjecting();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsCommonProjector::suMoving() {
- if (_x <= _klaymen->getX())
- _x = _klaymen->getX() - 100;
- else
- _x = _klaymen->getX() + 100;
- moveProjector();
- if (_beforeMoveX == _x) {
- if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) {
- sendMessage(_parentScene, 0x1019, 0);
- incGlobalVar(V_PROJECTOR_LOCATION, -1);
- setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount);
- } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) {
- sendMessage(_parentScene, 0x1019, 1);
- incGlobalVar(V_PROJECTOR_LOCATION, +1);
- setGlobalVar(V_PROJECTOR_SLOT, 0);
- }
- }
- Sprite::updateBounds();
-}
-
-void AsCommonProjector::moveProjector() {
-
- bool nowLockedInSlot = false;
-
- _y = _asProjectorItem->point.y;
-
- if (_asProjectorItem->index1 != -1) {
- int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x;
- if (elX - 20 < _x && elX + 20 > _x) {
- nowLockedInSlot = true;
- _y = _asProjectorItem->point.y + 10;
- }
- }
-
- if (_asProjectorItem->lockSlotIndex != -1) {
- int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x;
- if (elX - 20 < _x && elX + 20 > _x) {
- nowLockedInSlot = true;
- _y = _asProjectorItem->point.y + 10;
- }
- }
-
- if (_lockedInSlot && !nowLockedInSlot)
- _lockedInSlot = false;
- else if (!_lockedInSlot && nowLockedInSlot) {
- playSound(1, 0x5440E474);
- _lockedInSlot = true;
- }
-
-}
-
-void AsCommonProjector::stSuckedIn() {
- AnimatedSprite::updateDeltaXY();
- if (_collisionBounds.y1 <= 150) {
- sendMessage(_asPipe, 0x483A, 0);
- stopAnimation();
- setVisible(false);
- SetMessageHandler(&Sprite::handleMessage);
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsCommonProjector::stIdle() {
- startAnimation(0x10E3042B, 0, -1);
- SetMessageHandler(&AsCommonProjector::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsCommonProjector::stMoving() {
- _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
- startAnimation(0x14A10137, 0, -1);
- playSound(1, 0xEC008474);
- SetMessageHandler(&AsCommonProjector::handleMessage);
- SetSpriteUpdate(&AsCommonProjector::suMoving);
-}
-
-void AsCommonProjector::stStartLockedInSlot() {
- startAnimation(0x80C32213, 0, -1);
- SetMessageHandler(&AsCommonProjector::hmAnimation);
- SetSpriteUpdate(NULL);
- NextState(&AsCommonProjector::stStayLockedInSlot);
-}
-
-void AsCommonProjector::stStayLockedInSlot() {
- startAnimation(0xD23B207F, 0, -1);
- SetMessageHandler(&AsCommonProjector::hmLockedInSlot);
- SetSpriteUpdate(NULL);
-}
-
-void AsCommonProjector::stStartProjecting() {
- startAnimation(0x50A80517, 0, -1);
- setGlobalVar(V_PROJECTOR_ACTIVE, 1);
- playSound(0, 0xCC4A8456);
- _vm->_soundMan->addSound(0x05331081, 0xCE428854);
- _vm->_soundMan->playSoundLooping(0xCE428854);
- SetMessageHandler(&AsCommonProjector::hmAnimation);
- SetSpriteUpdate(NULL);
- NextState(&AsCommonProjector::stLockedInSlot);
-}
-
-void AsCommonProjector::stLockedInSlot() {
- sendMessage(_parentScene, 0x480F, 0);
- startAnimation(0xD833207F, 0, -1);
- SetMessageHandler(&AsCommonProjector::hmLockedInSlot);
- SetSpriteUpdate(NULL);
-}
-
-void AsCommonProjector::stStopProjecting() {
- startAnimation(0x50A94417, 0, -1);
- setGlobalVar(V_PROJECTOR_ACTIVE, 0);
- playSound(0, 0xCC4A8456);
- _vm->_soundMan->deleteSound(0xCE428854);
- SetMessageHandler(&AsCommonProjector::hmAnimation);
- SetSpriteUpdate(NULL);
- NextState(&AsCommonProjector::stStayLockedInSlot);
-}
-
-void AsCommonProjector::stTurnToFront() {
- _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
- startAnimation(0x22CB4A33, 0, -1);
- SetMessageHandler(&AsCommonProjector::hmAnimation);
- SetSpriteUpdate(&AsCommonProjector::suMoving);
- NextState(&AsCommonProjector::stMoving);
-}
-
-void AsCommonProjector::stStartSuckedIn() {
- setGlobalVar(V_PROJECTOR_LOCATION, 4);
- setGlobalVar(V_PROJECTOR_SLOT, 0);
- startAnimation(0x708D4712, 0, -1);
- playSound(2);
- SetMessageHandler(&Sprite::handleMessage);
- SetSpriteUpdate(&AsCommonProjector::stSuckedIn);
-}
-
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 +149,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 +203,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 +263,7 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam &param, Entit
setMessageList2(0x004B6658);
} else
setMessageList2(0x004B65F0);
- }
+ }
break;
case 0x482A:
_sprite1->setVisible(true);
@@ -768,77 +279,6 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-// Scene1402
-
-SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority)
- : StaticSprite(vm, fileHash, surfacePriority) {
-
- SetFilterY(&Sprite::defFilterY);
- SetUpdateHandler(&StaticSprite::updatePosition);
-}
-
-AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- createSurface(900, 347, 230);
-
- SetFilterY(&Sprite::defFilterY);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1402PuzzleBox::handleMessage);
- _x = 279;
- _y = 270;
- if (status == 2) {
- // Puzzle box after the puzzle was solved
- startAnimation(0x20060259, 0, -1);
- playSound(0, 0x419014AC);
- loadSound(1, 0x61901C29);
- NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone);
- } else if (status == 1) {
- // Puzzle box appears
- startAnimation(0x210A0213, 0, -1);
- playSound(0, 0x41809C6C);
- NextState(&AsScene1402PuzzleBox::stMoveUpDone);
- } else {
- // Puzzle box is here
- startAnimation(0x20060259, -1, -1);
- loadSound(1, 0x61901C29);
- _newStickFrameIndex = STICK_LAST_FRAME;
- }
-}
-
-uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2002:
- playSound(1);
- startAnimation(0x20060259, -1, -1);
- _playBackwards = true;
- NextState(&AsScene1402PuzzleBox::stMoveDownDone);
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1402PuzzleBox::stMoveUpDone() {
- sendMessage(_parentScene, 0x2000, 0);
- stopAnimation();
- setVisible(false);
-}
-
-void AsScene1402PuzzleBox::stMoveDownDone() {
- sendMessage(_parentScene, 0x2001, 0);
- stopAnimation();
- setVisible(false);
-}
-
-void AsScene1402PuzzleBox::stMoveDownSolvedDone() {
- sendMessage(_parentScene, 0x2003, 0);
- stopAnimation();
-}
-
Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isShaking(false), _asPuzzleBox(NULL), _asProjector(NULL) {
@@ -892,7 +332,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which)
startShaking();
}
}
-
+
if (_asPuzzleBox)
_asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2());
@@ -914,7 +354,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which)
}
_klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2());
-
+
}
void Scene1402::upShaking() {
@@ -988,237 +428,6 @@ void Scene1402::stopShaking() {
_isShaking = false;
}
-// Scene1407
-
-static const int16 kScene1407MouseFloorY[] = {
- 106, 150, 191, 230, 267, 308, 350, 395
-};
-
-static const struct {
- int16 x;
- int16 floorIndex;
- int16 sectionIndex;
- int16 nextHoleIndex;
-} kScene1407MouseHoles[] = {
- {125, 0, 0, 7},
- {452, 7, 21, 0},
- {337, 4, 11, 4},
- {286, 6, 17, 6},
- {348, 6, 17, 39},
- {536, 6, 18, 42},
- {111, 1, 3, 18},
- {203, 1, 3, 38},
- {270, 1, 3, 9},
- {197, 5, 14, 3},
- {252, 5, 14, 35},
- {297, 5, 14, 7},
- {359, 5, 14, 8},
- {422, 4, 12, 26},
- {467, 4, 12, 2},
- {539, 4, 12, 40},
- {111, 5, 13, 17},
- {211, 0, 1, 20},
- {258, 0, 1, 11},
- {322, 0, 1, 16},
- { 99, 6, 16, 31},
- {142, 6, 16, 27},
- {194, 6, 16, 12},
- {205, 2, 6, 45},
- {264, 2, 6, 10},
- { 98, 4, 10, 2},
- {152, 4, 10, 37},
- {199, 4, 10, 13},
- {258, 4, 10, 16},
- {100, 7, 19, 43},
- {168, 7, 19, 23},
- {123, 3, 8, 14},
- {181, 3, 8, 39},
- {230, 3, 8, 28},
- {292, 3, 8, 22},
- {358, 3, 8, 36},
- {505, 3, 9, 44},
- {400, 2, 7, 34},
- {454, 2, 7, 32},
- {532, 2, 7, 46},
- {484, 5, 15, 25},
- {529, 5, 15, 30},
- {251, 7, 20, 48},
- {303, 7, 20, 21},
- {360, 7, 20, 33},
- {503, 0, 2, 5},
- {459, 1, 4, 19},
- {530, 1, 4, 42},
- {111, 2, 5, 47},
- {442, 6, 18, 1}
-};
-
-static const struct {
- int16 x1, x2;
- int16 goodHoleIndex;
-} kScene1407MouseSections[] = {
- {100, 149, 0},
- {182, 351, 17},
- {430, 524, 45},
- { 89, 293, 7},
- {407, 555, 47},
- { 89, 132, 48},
- {178, 303, 23},
- {367, 551, 38},
- {105, 398, 31},
- {480, 537, 36},
- { 84, 275, 27},
- {318, 359, 2},
- {402, 560, 15},
- { 91, 132, 16},
- {179, 400, 10},
- {461, 552, 41},
- { 86, 218, 21},
- {267, 376, 4},
- {420, 560, 49},
- { 77, 188, 30},
- {237, 394, 44},
- {438, 515, 5}
-};
-
-AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) {
-
- createSurface(100, 117, 45);
- _x = 108;
- _y = 106;
- stIdleLookAtGoodHole();
- SetUpdateHandler(&AnimatedSprite::update);
-}
-
-void AsScene1407Mouse::suWalkTo() {
- int16 xdelta = _walkDestX - _x;
- if (xdelta > _deltaX)
- xdelta = _deltaX;
- else if (xdelta < -_deltaX)
- xdelta = -_deltaX;
- _deltaX = 0;
- if (_walkDestX == _x)
- sendMessage(this, 0x1019, 0);
- else {
- _x += xdelta;
- updateBounds();
- }
-}
-
-void AsScene1407Mouse::upGoThroughHole() {
- if (_countdown != 0 && (--_countdown == 0)) {
- SetUpdateHandler(&AnimatedSprite::update);
- gotoNextState();
- }
- AnimatedSprite::update();
-}
-
-uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x0001:
- {
- int16 mouseX = param.asPoint().x;
- int16 mouseY = param.asPoint().y;
- int holeIndex;
- for (holeIndex = 0; holeIndex < 50; holeIndex++) {
- int16 holeX = kScene1407MouseHoles[holeIndex].x;
- int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex];
- if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY)
- break;
- }
- if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) {
- _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex;
- _walkDestX = kScene1407MouseHoles[holeIndex].x;
- stWalkToHole();
- } else {
- if (mouseX < kScene1407MouseSections[_currSectionIndex].x1)
- _walkDestX = kScene1407MouseSections[_currSectionIndex].x1;
- else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2)
- _walkDestX = kScene1407MouseSections[_currSectionIndex].x2;
- else
- _walkDestX = mouseX;
- stWalkToDest();
- }
- }
- break;
- case 0x1019:
- gotoNextState();
- break;
- case 0x2001:
- {
- // Reset the position
- // Find the nearest hole and go through it, and exit at the first hole
- int16 distance = 640;
- int matchIndex = 50;
- for (int index = 0; index < 50; index++)
- if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex &&
- ABS(kScene1407MouseHoles[index].x - _x) < distance) {
- matchIndex = index;
- distance = ABS(kScene1407MouseHoles[index].x - _x);
- }
- if (matchIndex < 50) {
- _nextHoleIndex = 0;
- _walkDestX = kScene1407MouseHoles[matchIndex].x;
- stWalkToHole();
- }
- }
- break;
- }
- return messageResult;
-}
-
-void AsScene1407Mouse::stIdleLookAtGoodHole() {
- setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0);
- startAnimation(0x72215194, 0, -1);
- SetMessageHandler(&AsScene1407Mouse::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsScene1407Mouse::stWalkToDest() {
- if (_walkDestX != _x) {
- setDoDeltaX(_walkDestX < _x ? 1 : 0);
- startAnimation(0x22291510, 0, -1);
- SetMessageHandler(&AsScene1407Mouse::handleMessage);
- SetSpriteUpdate(&AsScene1407Mouse::suWalkTo);
- NextState(&AsScene1407Mouse::stIdleLookAtGoodHole);
- }
-}
-
-void AsScene1407Mouse::stWalkToHole() {
- setDoDeltaX(_walkDestX < _x ? 1 : 0);
- startAnimation(0x22291510, 0, -1);
- SetMessageHandler(&AsScene1407Mouse::handleMessage);
- SetSpriteUpdate(&AsScene1407Mouse::suWalkTo);
- NextState(&AsScene1407Mouse::stGoThroughHole);
-}
-
-void AsScene1407Mouse::stGoThroughHole() {
- startAnimation(0x72215194, 0, -1);
- setVisible(false);
- _countdown = 12;
- SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole);
- SetMessageHandler(NULL);
- SetSpriteUpdate(NULL);
- NextState(&AsScene1407Mouse::stArriveAtHole);
-}
-
-void AsScene1407Mouse::stArriveAtHole() {
- _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex;
- _x = kScene1407MouseHoles[_nextHoleIndex].x;
- _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex];
- if (_nextHoleIndex == 1) {
- sendMessage(_parentScene, 0x2000, 0);
- _walkDestX = 512;
- stWalkToDest();
- setVisible(true);
- } else {
- _walkDestX = _x + 14;
- stWalkToDest();
- setVisible(true);
- }
-}
-
Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule), _puzzleSolvedCountdown(0), _resetButtonCountdown(0) {
@@ -1231,7 +440,7 @@ Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule)
_asMouse = insertSprite<AsScene1407Mouse>(this);
_ssResetButton = insertStaticSprite(0x12006600, 100);
- _ssResetButton->setVisible(false);
+ _ssResetButton->setVisible(false);
}
@@ -1275,13 +484,11 @@ uint32 Scene1407::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-// Scene1403
-
Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) {
-
+
SetMessageHandler(&Scene1403::handleMessage);
-
+
setRectList(0x004B1FF8);
setBackground(0x2110A234);
setPalette(0x2110A234);
@@ -1379,14 +586,12 @@ uint32 Scene1403::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-// Scene1404
-
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);
@@ -1480,89 +685,18 @@ uint32 Scene1404::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-// Scene1405
-
-static const NPoint kAsScene1405TileItemPositions[] = {
- {100, 80}, {162, 78}, {222, 76}, {292, 76},
- {356, 82}, {422, 84}, {488, 86}, {550, 90},
- {102, 134}, {164, 132}, {224, 136}, {294, 136},
- {360, 136}, {422, 138}, {484, 144}, {548, 146},
- { 98, 196}, {160, 200}, {228, 200}, {294, 202},
- {360, 198}, {424, 200}, {482, 202}, {548, 206},
- { 98, 260}, {160, 264}, {226, 260}, {296, 262},
- {358, 260}, {424, 262}, {486, 264}, {550, 266},
- { 94, 322}, {160, 316}, {226, 316}, {296, 320},
- {358, 322}, {422, 324}, {488, 322}, {550, 322},
- { 98, 380}, {160, 376}, {226, 376}, {294, 378},
- {356, 380}, {420, 380}, {490, 378}, {552, 376}
-};
-
-AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) {
-
- loadSound(0, 0x05308101);
- setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8);
- _x = kAsScene1405TileItemPositions[_tileIndex].x;
- _y = kAsScene1405TileItemPositions[_tileIndex].y;
- createSurface1(0x844B805C, 1100);
- setVisible(false);
- if (getSubVar(VA_IS_TILE_MATCH, _tileIndex))
- _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1;
- startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1);
- _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex);
- SetUpdateHandler(&AsScene1405Tile::update);
- SetMessageHandler(&AsScene1405Tile::handleMessage);
-}
-
-void AsScene1405Tile::update() {
- updateAnim();
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0))
- show();
-}
-
-uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) {
- show();
- sendMessage(_parentScene, 0x2000, _tileIndex);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void AsScene1405Tile::show() {
- if (!_isShowing) {
- _isShowing = true;
- playSound(0);
- setVisible(true);
- }
-}
-
-void AsScene1405Tile::hide() {
- if (_isShowing) {
- _isShowing = false;
- playSound(0);
- setVisible(false);
- }
-}
-
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/module1400.h b/engines/neverhood/modules/module1400.h
index 9a592c2952..53ad7125ab 100644
--- a/engines/neverhood/modules/module1400.h
+++ b/engines/neverhood/modules/module1400.h
@@ -26,7 +26,6 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
namespace Neverhood {
@@ -40,92 +39,9 @@ protected:
void updateScene();
};
-// Scene1401
-
-class AsScene1401Pipe : public AnimatedSprite {
-public:
- AsScene1401Pipe(NeverhoodEngine *vm);
- virtual ~AsScene1401Pipe();
-protected:
- int _countdown1;
- int _countdown2;
- void update();
- void upSuckInProjector();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmSuckInProjector(int messageNum, const MessageParam &param, Entity *sender);
- void stStartSucking();
- void stDoneSucking();
- void stSuckInProjector();
-};
-
-class AsScene1401Mouse : public AnimatedSprite {
-public:
- AsScene1401Mouse(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suSuckedIn();
- void stSuckedIn();
-};
-
-class AsScene1401Cheese : public AnimatedSprite {
-public:
- AsScene1401Cheese(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suSuckedIn();
- void stSuckedIn();
-};
-
-class AsScene1401BackDoor : public AnimatedSprite {
-public:
- AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen);
-protected:
- Sprite *_klaymen;
- int _countdown;
- bool _isOpen;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stCloseDoor();
- void stCloseDoorDone();
-};
-
-struct AsCommonProjectorItem {
- NPoint point;
- int8 maxSlotCount;
- int8 lockSlotIndex;
- int8 index1;
- int8 leftBorderLeaves;
- int8 rightBorderLeaves;
-};
-
-class AsCommonProjector : public AnimatedSprite {
-public:
- AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe);
- virtual ~AsCommonProjector();
-protected:
- Scene *_parentScene;
- Sprite *_klaymen;
- Sprite *_asPipe;
- const AsCommonProjectorItem *_asProjectorItem;
- int16 _beforeMoveX;
- bool _lockedInSlot;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmLockedInSlot(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
- void suMoving();
- void moveProjector();
- void stSuckedIn();
- void stIdle();
- void stMoving();
- void stStartLockedInSlot();
- void stStayLockedInSlot();
- void stStartProjecting();
- void stLockedInSlot();
- void stStopProjecting();
- void stTurnToFront();
- void stStartSuckedIn();
-};
+class AsCommonProjector;
+class AsScene1201Tape;
+class AsScene1405Tile;
class Scene1401 : public Scene {
public:
@@ -146,24 +62,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1402
-
-class SsScene1402BridgePart : public StaticSprite {
-public:
- SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority);
-};
-
-class AsScene1402PuzzleBox : public AnimatedSprite {
-public:
- AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stMoveUpDone();
- void stMoveDownDone();
- void stMoveDownSolvedDone();
-};
-
class Scene1402 : public Scene {
public:
Scene1402(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -180,27 +78,6 @@ protected:
void stopShaking();
};
-// Scene1407
-
-class AsScene1407Mouse : public AnimatedSprite {
-public:
- AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- int16 _walkDestX;
- int16 _currSectionIndex;
- int16 _nextHoleIndex;
- int _countdown;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suWalkTo();
- void upGoThroughHole();
- void stIdleLookAtGoodHole();
- void stWalkToDest();
- void stWalkToHole();
- void stGoThroughHole();
- void stArriveAtHole();
-};
-
class Scene1407 : public Scene {
public:
Scene1407(NeverhoodEngine *vm, Module *parentModule);
@@ -213,8 +90,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1403
-
class Scene1403 : public Scene {
public:
Scene1403(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -229,8 +104,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1404
-
class Scene1404 : public Scene {
public:
Scene1404(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -243,24 +116,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene1405
-
-class Scene1405;
-
-class AsScene1405Tile : public AnimatedSprite {
-public:
- AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex);
- void show();
- void hide();
-protected:
- Scene1405 *_parentScene;
- bool _isShowing;
- uint32 _tileIndex;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1405 : public Scene {
public:
Scene1405(NeverhoodEngine *vm, Module *parentModule);
diff --git a/engines/neverhood/modules/module1400_sprites.cpp b/engines/neverhood/modules/module1400_sprites.cpp
new file mode 100644
index 0000000000..c0ab73c93d
--- /dev/null
+++ b/engines/neverhood/modules/module1400_sprites.cpp
@@ -0,0 +1,1129 @@
+/* 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 "neverhood/modules/module1400_sprites.h"
+#include "neverhood/modules/module1400.h"
+
+namespace Neverhood {
+
+AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) {
+
+ createSurface(900, 152, 147);
+ _x = 454;
+ _y = 217;
+ startAnimation(0x4C210500, 0, -1);
+ SetUpdateHandler(&AsScene1401Pipe::update);
+ SetMessageHandler(&AsScene1401Pipe::handleMessage);
+}
+
+AsScene1401Pipe::~AsScene1401Pipe() {
+ _vm->_soundMan->deleteSoundGroup(0x01104C08);
+}
+
+void AsScene1401Pipe::update() {
+ AnimatedSprite::update();
+ if (_countdown1 != 0 && (--_countdown1 == 0))
+ stDoneSucking();
+ if (_countdown2 != 0 && (--_countdown2 == 0)) {
+ _vm->_soundMan->addSound(0x01104C08, 0x4A116437);
+ _vm->_soundMan->playSoundLooping(0x4A116437);
+ }
+}
+
+void AsScene1401Pipe::upSuckInProjector() {
+ AnimatedSprite::update();
+ if (_countdown1 != 0)
+ _countdown1--;
+}
+
+uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x0A8A1490)
+ playSound(1, 0x6AB6666F);
+ break;
+ case 0x2000:
+ _countdown1 = 70;
+ _countdown2 = 8;
+ stStartSucking();
+ break;
+ case 0x483A:
+ stSuckInProjector();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ if (_countdown1 != 0)
+ stStartSucking();
+ else
+ stDoneSucking();
+ SetMessageHandler(&AsScene1401Pipe::handleMessage);
+ SetUpdateHandler(&AsScene1401Pipe::update);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1401Pipe::stStartSucking() {
+ startAnimation(0x4C240100, 0, -1);
+ playSound(0, 0x4A30063F);
+}
+
+void AsScene1401Pipe::stDoneSucking() {
+ _vm->_soundMan->deleteSound(0x4A116437);
+ playSound(0, 0x4A120435);
+ startAnimation(0x4C210500, 0, -1);
+}
+
+void AsScene1401Pipe::stSuckInProjector() {
+ startAnimation(0x6C210810, 0, -1);
+ SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector);
+ SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector);
+}
+
+AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ createSurface(100, 71, 41);
+ _x = 478;
+ _y = 433;
+ startAnimation(0xA282C472, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1401Mouse::handleMessage);
+}
+
+uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x66382026)
+ playSound(0, 0x0CD84468);
+ else if (param.asInteger() == 0x6E28061C)
+ playSound(0, 0x78C8402C);
+ else if (param.asInteger() == 0x462F0410)
+ playSound(0, 0x60984E28);
+ break;
+ case 0x4839:
+ stSuckedIn();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1401Mouse::suSuckedIn() {
+ AnimatedSprite::updateDeltaXY();
+ if (_collisionBounds.y1 <= 150) {
+ playSound(0, 0x0E32247F);
+ stopAnimation();
+ setVisible(false);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1401Mouse::stSuckedIn() {
+ startAnimation(0x34880040, 0, -1);
+ SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn);
+}
+
+AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ createSurface(200, 152, 147);
+ _x = 427;
+ _y = 433;
+ startAnimation(0x461A1490, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1401Cheese::handleMessage);
+}
+
+uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4839:
+ stSuckedIn();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1401Cheese::suSuckedIn() {
+ AnimatedSprite::updateDeltaXY();
+ if (_collisionBounds.y1 <= 150) {
+ playSound(0, 0x18020439);
+ stopAnimation();
+ setVisible(false);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1401Cheese::stSuckedIn() {
+ startAnimation(0x103B8020, 0, -1);
+ SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn);
+}
+
+AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen)
+ : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) {
+
+ _x = 320;
+ _y = 240;
+ createSurface1(0x04551900, 100);
+ if (isOpen) {
+ startAnimation(0x04551900, -1, -1);
+ _countdown = 48;
+ } else {
+ stopAnimation();
+ setVisible(false);
+ }
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ SetUpdateHandler(&AsScene1401BackDoor::update);
+ SetMessageHandler(&AsScene1401BackDoor::handleMessage);
+}
+
+void AsScene1401BackDoor::update() {
+ if (_countdown != 0 && (--_countdown == 0))
+ stCloseDoor();
+ AnimatedSprite::update();
+}
+
+
+uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2001:
+ if (_isOpen)
+ _countdown = 168;
+ messageResult = _isOpen ? 1 : 0;
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ _countdown = 168;
+ if (!_isOpen)
+ stOpenDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1401BackDoor::stOpenDoor() {
+ _isOpen = true;
+ setVisible(true);
+ startAnimation(0x04551900, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ playSound(0, calcHash("fxDoorOpen24"));
+}
+
+void AsScene1401BackDoor::stCloseDoor() {
+ _isOpen = false;
+ setVisible(true);
+ startAnimation(0x04551900, -1, -1);
+ playSound(0, calcHash("fxDoorClose24"));
+ _playBackwards = true;
+ NextState(&AsScene1401BackDoor::stCloseDoorDone);
+}
+
+void AsScene1401BackDoor::stCloseDoorDone() {
+ stopAnimation();
+ setVisible(false);
+}
+
+static const AsCommonProjectorItem kAsCommonProjectorItems[] = {
+ {{154, 453}, 4, 2, 0, 0, 1},
+ {{104, 391}, 4, -1, -1, 1, 1},
+ {{ 22, 447}, 6, -1, -1, 1, 1},
+ {{112, 406}, 2, -1, -1, 1, 0},
+ {{262, 433}, 1, 1, 0, 0, 0}
+};
+
+AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) {
+
+ _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)];
+ createSurface(990, 101, 182);
+ startAnimation(0x10E3042B, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsCommonProjector::handleMessage);
+ _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
+ _lockedInSlot = true;
+ moveProjector();
+ setDoDeltaX(1);
+ if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex)
+ stStayLockedInSlot();
+ loadSound(2, 0xC8C2507C);
+}
+
+AsCommonProjector::~AsCommonProjector() {
+ _vm->_soundMan->deleteSoundGroup(0x05331081);
+}
+
+uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4807:
+ setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108);
+ if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex)
+ stStartLockedInSlot();
+ else
+ stIdle();
+ break;
+ case 0x480B:
+ if (param.asInteger() != 1) {
+ if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount)
+ incGlobalVar(V_PROJECTOR_SLOT, 1);
+ } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0)
+ incGlobalVar(V_PROJECTOR_SLOT, -1);
+ stMoving();
+ break;
+ case 0x480C:
+ // Check if the projector can be moved
+ if (param.asInteger() != 1)
+ messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0;
+ else
+ messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0;
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ case 0x4839:
+ stStartSuckedIn();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 &&
+ param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) {
+ sendMessage(_parentScene, 0x4826, 1);
+ } else
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4807:
+ sendMessage(_parentScene, 0x4807, 0);
+ stStopProjecting();
+ break;
+ case 0x480B:
+ if (param.asInteger() != 1) {
+ if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount)
+ incGlobalVar(V_PROJECTOR_SLOT, 1);
+ } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0)
+ incGlobalVar(V_PROJECTOR_SLOT, -1);
+ stTurnToFront();
+ break;
+ case 0x480C:
+ // Check if the projector can be moved
+ if (param.asInteger() != 1)
+ messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0;
+ else
+ messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0;
+ break;
+ case 0x480F:
+ stStartProjecting();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsCommonProjector::suMoving() {
+ if (_x <= _klaymen->getX())
+ _x = _klaymen->getX() - 100;
+ else
+ _x = _klaymen->getX() + 100;
+ moveProjector();
+ if (_beforeMoveX == _x) {
+ if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) {
+ sendMessage(_parentScene, 0x1019, 0);
+ incGlobalVar(V_PROJECTOR_LOCATION, -1);
+ setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount);
+ } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) {
+ sendMessage(_parentScene, 0x1019, 1);
+ incGlobalVar(V_PROJECTOR_LOCATION, +1);
+ setGlobalVar(V_PROJECTOR_SLOT, 0);
+ }
+ }
+ Sprite::updateBounds();
+}
+
+void AsCommonProjector::moveProjector() {
+
+ bool nowLockedInSlot = false;
+
+ _y = _asProjectorItem->point.y;
+
+ if (_asProjectorItem->index1 != -1) {
+ int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x;
+ if (elX - 20 < _x && elX + 20 > _x) {
+ nowLockedInSlot = true;
+ _y = _asProjectorItem->point.y + 10;
+ }
+ }
+
+ if (_asProjectorItem->lockSlotIndex != -1) {
+ int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x;
+ if (elX - 20 < _x && elX + 20 > _x) {
+ nowLockedInSlot = true;
+ _y = _asProjectorItem->point.y + 10;
+ }
+ }
+
+ if (_lockedInSlot && !nowLockedInSlot)
+ _lockedInSlot = false;
+ else if (!_lockedInSlot && nowLockedInSlot) {
+ playSound(1, 0x5440E474);
+ _lockedInSlot = true;
+ }
+
+}
+
+void AsCommonProjector::stSuckedIn() {
+ AnimatedSprite::updateDeltaXY();
+ if (_collisionBounds.y1 <= 150) {
+ sendMessage(_asPipe, 0x483A, 0);
+ stopAnimation();
+ setVisible(false);
+ SetMessageHandler(&Sprite::handleMessage);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsCommonProjector::stIdle() {
+ startAnimation(0x10E3042B, 0, -1);
+ SetMessageHandler(&AsCommonProjector::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsCommonProjector::stMoving() {
+ _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
+ startAnimation(0x14A10137, 0, -1);
+ playSound(1, 0xEC008474);
+ SetMessageHandler(&AsCommonProjector::handleMessage);
+ SetSpriteUpdate(&AsCommonProjector::suMoving);
+}
+
+void AsCommonProjector::stStartLockedInSlot() {
+ startAnimation(0x80C32213, 0, -1);
+ SetMessageHandler(&AsCommonProjector::hmAnimation);
+ SetSpriteUpdate(NULL);
+ NextState(&AsCommonProjector::stStayLockedInSlot);
+}
+
+void AsCommonProjector::stStayLockedInSlot() {
+ startAnimation(0xD23B207F, 0, -1);
+ SetMessageHandler(&AsCommonProjector::hmLockedInSlot);
+ SetSpriteUpdate(NULL);
+}
+
+void AsCommonProjector::stStartProjecting() {
+ startAnimation(0x50A80517, 0, -1);
+ setGlobalVar(V_PROJECTOR_ACTIVE, 1);
+ playSound(0, 0xCC4A8456);
+ _vm->_soundMan->addSound(0x05331081, 0xCE428854);
+ _vm->_soundMan->playSoundLooping(0xCE428854);
+ SetMessageHandler(&AsCommonProjector::hmAnimation);
+ SetSpriteUpdate(NULL);
+ NextState(&AsCommonProjector::stLockedInSlot);
+}
+
+void AsCommonProjector::stLockedInSlot() {
+ sendMessage(_parentScene, 0x480F, 0);
+ startAnimation(0xD833207F, 0, -1);
+ SetMessageHandler(&AsCommonProjector::hmLockedInSlot);
+ SetSpriteUpdate(NULL);
+}
+
+void AsCommonProjector::stStopProjecting() {
+ startAnimation(0x50A94417, 0, -1);
+ setGlobalVar(V_PROJECTOR_ACTIVE, 0);
+ playSound(0, 0xCC4A8456);
+ _vm->_soundMan->deleteSound(0xCE428854);
+ SetMessageHandler(&AsCommonProjector::hmAnimation);
+ SetSpriteUpdate(NULL);
+ NextState(&AsCommonProjector::stStayLockedInSlot);
+}
+
+void AsCommonProjector::stTurnToFront() {
+ _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x;
+ startAnimation(0x22CB4A33, 0, -1);
+ SetMessageHandler(&AsCommonProjector::hmAnimation);
+ SetSpriteUpdate(&AsCommonProjector::suMoving);
+ NextState(&AsCommonProjector::stMoving);
+}
+
+void AsCommonProjector::stStartSuckedIn() {
+ setGlobalVar(V_PROJECTOR_LOCATION, 4);
+ setGlobalVar(V_PROJECTOR_SLOT, 0);
+ startAnimation(0x708D4712, 0, -1);
+ playSound(2);
+ SetMessageHandler(&Sprite::handleMessage);
+ SetSpriteUpdate(&AsCommonProjector::stSuckedIn);
+}
+
+SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority)
+ : StaticSprite(vm, fileHash, surfacePriority) {
+
+ SetFilterY(&Sprite::defFilterY);
+ SetUpdateHandler(&StaticSprite::updatePosition);
+}
+
+AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(900, 347, 230);
+
+ SetFilterY(&Sprite::defFilterY);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1402PuzzleBox::handleMessage);
+ _x = 279;
+ _y = 270;
+ if (status == 2) {
+ // Puzzle box after the puzzle was solved
+ startAnimation(0x20060259, 0, -1);
+ playSound(0, 0x419014AC);
+ loadSound(1, 0x61901C29);
+ NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone);
+ } else if (status == 1) {
+ // Puzzle box appears
+ startAnimation(0x210A0213, 0, -1);
+ playSound(0, 0x41809C6C);
+ NextState(&AsScene1402PuzzleBox::stMoveUpDone);
+ } else {
+ // Puzzle box is here
+ startAnimation(0x20060259, -1, -1);
+ loadSound(1, 0x61901C29);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ }
+}
+
+uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2002:
+ playSound(1);
+ startAnimation(0x20060259, -1, -1);
+ _playBackwards = true;
+ NextState(&AsScene1402PuzzleBox::stMoveDownDone);
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1402PuzzleBox::stMoveUpDone() {
+ sendMessage(_parentScene, 0x2000, 0);
+ stopAnimation();
+ setVisible(false);
+}
+
+void AsScene1402PuzzleBox::stMoveDownDone() {
+ sendMessage(_parentScene, 0x2001, 0);
+ stopAnimation();
+ setVisible(false);
+}
+
+void AsScene1402PuzzleBox::stMoveDownSolvedDone() {
+ sendMessage(_parentScene, 0x2003, 0);
+ stopAnimation();
+}
+
+static const int16 kScene1407MouseFloorY[] = {
+ 106, 150, 191, 230, 267, 308, 350, 395
+};
+
+static const struct {
+ int16 x;
+ int16 floorIndex;
+ int16 sectionIndex;
+ int16 nextHoleIndex;
+} kScene1407MouseHoles[] = {
+ {125, 0, 0, 7},
+ {452, 7, 21, 0},
+ {337, 4, 11, 4},
+ {286, 6, 17, 6},
+ {348, 6, 17, 39},
+ {536, 6, 18, 42},
+ {111, 1, 3, 18},
+ {203, 1, 3, 38},
+ {270, 1, 3, 9},
+ {197, 5, 14, 3},
+ {252, 5, 14, 35},
+ {297, 5, 14, 7},
+ {359, 5, 14, 8},
+ {422, 4, 12, 26},
+ {467, 4, 12, 2},
+ {539, 4, 12, 40},
+ {111, 5, 13, 17},
+ {211, 0, 1, 20},
+ {258, 0, 1, 11},
+ {322, 0, 1, 16},
+ { 99, 6, 16, 31},
+ {142, 6, 16, 27},
+ {194, 6, 16, 12},
+ {205, 2, 6, 45},
+ {264, 2, 6, 10},
+ { 98, 4, 10, 2},
+ {152, 4, 10, 37},
+ {199, 4, 10, 13},
+ {258, 4, 10, 16},
+ {100, 7, 19, 43},
+ {168, 7, 19, 23},
+ {123, 3, 8, 14},
+ {181, 3, 8, 39},
+ {230, 3, 8, 28},
+ {292, 3, 8, 22},
+ {358, 3, 8, 36},
+ {505, 3, 9, 44},
+ {400, 2, 7, 34},
+ {454, 2, 7, 32},
+ {532, 2, 7, 46},
+ {484, 5, 15, 25},
+ {529, 5, 15, 30},
+ {251, 7, 20, 48},
+ {303, 7, 20, 21},
+ {360, 7, 20, 33},
+ {503, 0, 2, 5},
+ {459, 1, 4, 19},
+ {530, 1, 4, 42},
+ {111, 2, 5, 47},
+ {442, 6, 18, 1}
+};
+
+static const struct {
+ int16 x1, x2;
+ int16 goodHoleIndex;
+} kScene1407MouseSections[] = {
+ {100, 149, 0},
+ {182, 351, 17},
+ {430, 524, 45},
+ { 89, 293, 7},
+ {407, 555, 47},
+ { 89, 132, 48},
+ {178, 303, 23},
+ {367, 551, 38},
+ {105, 398, 31},
+ {480, 537, 36},
+ { 84, 275, 27},
+ {318, 359, 2},
+ {402, 560, 15},
+ { 91, 132, 16},
+ {179, 400, 10},
+ {461, 552, 41},
+ { 86, 218, 21},
+ {267, 376, 4},
+ {420, 560, 49},
+ { 77, 188, 30},
+ {237, 394, 44},
+ {438, 515, 5}
+};
+
+AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) {
+
+ createSurface(100, 117, 45);
+ _x = 108;
+ _y = 106;
+ stIdleLookAtGoodHole();
+ SetUpdateHandler(&AnimatedSprite::update);
+}
+
+void AsScene1407Mouse::suWalkTo() {
+ int16 xdelta = _walkDestX - _x;
+ if (xdelta > _deltaX)
+ xdelta = _deltaX;
+ else if (xdelta < -_deltaX)
+ xdelta = -_deltaX;
+ _deltaX = 0;
+ if (_walkDestX == _x)
+ sendMessage(this, 0x1019, 0);
+ else {
+ _x += xdelta;
+ updateBounds();
+ }
+}
+
+void AsScene1407Mouse::upGoThroughHole() {
+ if (_countdown != 0 && (--_countdown == 0)) {
+ SetUpdateHandler(&AnimatedSprite::update);
+ gotoNextState();
+ }
+ AnimatedSprite::update();
+}
+
+uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x0001:
+ {
+ int16 mouseX = param.asPoint().x;
+ int16 mouseY = param.asPoint().y;
+ int holeIndex;
+ for (holeIndex = 0; holeIndex < 50; holeIndex++) {
+ int16 holeX = kScene1407MouseHoles[holeIndex].x;
+ int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex];
+ if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY)
+ break;
+ }
+ if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) {
+ _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex;
+ _walkDestX = kScene1407MouseHoles[holeIndex].x;
+ stWalkToHole();
+ } else {
+ if (mouseX < kScene1407MouseSections[_currSectionIndex].x1)
+ _walkDestX = kScene1407MouseSections[_currSectionIndex].x1;
+ else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2)
+ _walkDestX = kScene1407MouseSections[_currSectionIndex].x2;
+ else
+ _walkDestX = mouseX;
+ stWalkToDest();
+ }
+ }
+ break;
+ case 0x1019:
+ gotoNextState();
+ break;
+ case 0x2001:
+ {
+ // Reset the position
+ // Find the nearest hole and go through it, and exit at the first hole
+ int16 distance = 640;
+ int matchIndex = 50;
+ for (int index = 0; index < 50; index++)
+ if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex &&
+ ABS(kScene1407MouseHoles[index].x - _x) < distance) {
+ matchIndex = index;
+ distance = ABS(kScene1407MouseHoles[index].x - _x);
+ }
+ if (matchIndex < 50) {
+ _nextHoleIndex = 0;
+ _walkDestX = kScene1407MouseHoles[matchIndex].x;
+ stWalkToHole();
+ }
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1407Mouse::stIdleLookAtGoodHole() {
+ setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0);
+ startAnimation(0x72215194, 0, -1);
+ SetMessageHandler(&AsScene1407Mouse::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsScene1407Mouse::stWalkToDest() {
+ if (_walkDestX != _x) {
+ setDoDeltaX(_walkDestX < _x ? 1 : 0);
+ startAnimation(0x22291510, 0, -1);
+ SetMessageHandler(&AsScene1407Mouse::handleMessage);
+ SetSpriteUpdate(&AsScene1407Mouse::suWalkTo);
+ NextState(&AsScene1407Mouse::stIdleLookAtGoodHole);
+ }
+}
+
+void AsScene1407Mouse::stWalkToHole() {
+ setDoDeltaX(_walkDestX < _x ? 1 : 0);
+ startAnimation(0x22291510, 0, -1);
+ SetMessageHandler(&AsScene1407Mouse::handleMessage);
+ SetSpriteUpdate(&AsScene1407Mouse::suWalkTo);
+ NextState(&AsScene1407Mouse::stGoThroughHole);
+}
+
+void AsScene1407Mouse::stGoThroughHole() {
+ startAnimation(0x72215194, 0, -1);
+ setVisible(false);
+ _countdown = 12;
+ SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(NULL);
+ NextState(&AsScene1407Mouse::stArriveAtHole);
+}
+
+void AsScene1407Mouse::stArriveAtHole() {
+ _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex;
+ _x = kScene1407MouseHoles[_nextHoleIndex].x;
+ _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex];
+ if (_nextHoleIndex == 1) {
+ sendMessage(_parentScene, 0x2000, 0);
+ _walkDestX = 512;
+ stWalkToDest();
+ setVisible(true);
+ } else {
+ _walkDestX = _x + 14;
+ stWalkToDest();
+ setVisible(true);
+ }
+}
+
+static const NPoint kAsScene1405TileItemPositions[] = {
+ {100, 80}, {162, 78}, {222, 76}, {292, 76},
+ {356, 82}, {422, 84}, {488, 86}, {550, 90},
+ {102, 134}, {164, 132}, {224, 136}, {294, 136},
+ {360, 136}, {422, 138}, {484, 144}, {548, 146},
+ { 98, 196}, {160, 200}, {228, 200}, {294, 202},
+ {360, 198}, {424, 200}, {482, 202}, {548, 206},
+ { 98, 260}, {160, 264}, {226, 260}, {296, 262},
+ {358, 260}, {424, 262}, {486, 264}, {550, 266},
+ { 94, 322}, {160, 316}, {226, 316}, {296, 320},
+ {358, 322}, {422, 324}, {488, 322}, {550, 322},
+ { 98, 380}, {160, 376}, {226, 376}, {294, 378},
+ {356, 380}, {420, 380}, {490, 378}, {552, 376}
+};
+
+AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) {
+
+ loadSound(0, 0x05308101);
+ setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8);
+ _x = kAsScene1405TileItemPositions[_tileIndex].x;
+ _y = kAsScene1405TileItemPositions[_tileIndex].y;
+ createSurface1(0x844B805C, 1100);
+ setVisible(false);
+ if (getSubVar(VA_IS_TILE_MATCH, _tileIndex))
+ _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1;
+ startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1);
+ _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex);
+ SetUpdateHandler(&AsScene1405Tile::update);
+ SetMessageHandler(&AsScene1405Tile::handleMessage);
+}
+
+void AsScene1405Tile::update() {
+ updateAnim();
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0))
+ show();
+}
+
+uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) {
+ show();
+ sendMessage(_parentScene, 0x2000, _tileIndex);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1405Tile::show() {
+ if (!_isShowing) {
+ _isShowing = true;
+ playSound(0);
+ setVisible(true);
+ }
+}
+
+void AsScene1405Tile::hide() {
+ if (_isShowing) {
+ _isShowing = false;
+ playSound(0);
+ setVisible(false);
+ }
+}
+
+KmScene1401::KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
+ else
+ GotoState(&Klaymen::stMoveObjectFaceObject);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ }
+ return 0;
+}
+
+KmScene1402::KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ SetFilterY(&Sprite::defFilterY);
+}
+
+uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
+ else
+ GotoState(&Klaymen::stMoveObjectFaceObject);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ }
+ return 0;
+}
+
+static const KlaymenIdleTableItem klaymenIdleTable1403[] = {
+ {1, kIdleSpinHead},
+ {1, kIdleChest},
+ {1, kIdleHeadOff},
+};
+
+KmScene1403::KmScene1403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ setKlaymenIdleTable(klaymenIdleTable1403, ARRAYSIZE(klaymenIdleTable1403));
+}
+
+uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
+ else
+ GotoState(&Klaymen::stMoveObjectFaceObject);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stUseLever);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x4827:
+ GotoState(&Klaymen::stReleaseLever);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+// KmScene1404
+
+KmScene1404::KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480A:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
+ else
+ GotoState(&Klaymen::stMoveObjectFaceObject);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481A:
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1400_sprites.h b/engines/neverhood/modules/module1400_sprites.h
new file mode 100644
index 0000000000..49b91fe0cf
--- /dev/null
+++ b/engines/neverhood/modules/module1400_sprites.h
@@ -0,0 +1,198 @@
+/* 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 NEVERHOOD_MODULES_MODULE1400_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1400_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsScene1401Pipe : public AnimatedSprite {
+public:
+ AsScene1401Pipe(NeverhoodEngine *vm);
+ virtual ~AsScene1401Pipe();
+protected:
+ int _countdown1;
+ int _countdown2;
+ void update();
+ void upSuckInProjector();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmSuckInProjector(int messageNum, const MessageParam &param, Entity *sender);
+ void stStartSucking();
+ void stDoneSucking();
+ void stSuckInProjector();
+};
+
+class AsScene1401Mouse : public AnimatedSprite {
+public:
+ AsScene1401Mouse(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suSuckedIn();
+ void stSuckedIn();
+};
+
+class AsScene1401Cheese : public AnimatedSprite {
+public:
+ AsScene1401Cheese(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suSuckedIn();
+ void stSuckedIn();
+};
+
+class AsScene1401BackDoor : public AnimatedSprite {
+public:
+ AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen);
+protected:
+ Sprite *_klaymen;
+ int _countdown;
+ bool _isOpen;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stCloseDoor();
+ void stCloseDoorDone();
+};
+
+struct AsCommonProjectorItem {
+ NPoint point;
+ int8 maxSlotCount;
+ int8 lockSlotIndex;
+ int8 index1;
+ int8 leftBorderLeaves;
+ int8 rightBorderLeaves;
+};
+
+class AsCommonProjector : public AnimatedSprite {
+public:
+ AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe);
+ virtual ~AsCommonProjector();
+protected:
+ Scene *_parentScene;
+ Sprite *_klaymen;
+ Sprite *_asPipe;
+ const AsCommonProjectorItem *_asProjectorItem;
+ int16 _beforeMoveX;
+ bool _lockedInSlot;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmLockedInSlot(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoving();
+ void moveProjector();
+ void stSuckedIn();
+ void stIdle();
+ void stMoving();
+ void stStartLockedInSlot();
+ void stStayLockedInSlot();
+ void stStartProjecting();
+ void stLockedInSlot();
+ void stStopProjecting();
+ void stTurnToFront();
+ void stStartSuckedIn();
+};
+
+class SsScene1402BridgePart : public StaticSprite {
+public:
+ SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority);
+};
+
+class AsScene1402PuzzleBox : public AnimatedSprite {
+public:
+ AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stMoveUpDone();
+ void stMoveDownDone();
+ void stMoveDownSolvedDone();
+};
+
+class AsScene1407Mouse : public AnimatedSprite {
+public:
+ AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ int16 _walkDestX;
+ int16 _currSectionIndex;
+ int16 _nextHoleIndex;
+ int _countdown;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suWalkTo();
+ void upGoThroughHole();
+ void stIdleLookAtGoodHole();
+ void stWalkToDest();
+ void stWalkToHole();
+ void stGoThroughHole();
+ void stArriveAtHole();
+};
+
+class Scene1405;
+
+class AsScene1405Tile : public AnimatedSprite {
+public:
+ AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex);
+ void show();
+ void hide();
+protected:
+ Scene1405 *_parentScene;
+ bool _isShowing;
+ uint32 _tileIndex;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1401 : public Klaymen {
+public:
+ KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1402 : public Klaymen {
+public:
+ KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1403 : public Klaymen {
+public:
+ KmScene1403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene1404 : public Klaymen {
+public:
+ KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1400_SPRITES_H */
diff --git a/engines/neverhood/modules/module1500.cpp b/engines/neverhood/modules/module1500.cpp
index 2a9597b1fd..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
@@ -35,7 +35,7 @@ Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which)
}
void Module1500::createScene(int sceneNum, int which) {
- debug("Module1500::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1500::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -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 f7e3c37d84..0df7dd8925 100644
--- a/engines/neverhood/modules/module1600.cpp
+++ b/engines/neverhood/modules/module1600.cpp
@@ -20,10 +20,12 @@
*
*/
-#include "neverhood/modules/module1600.h"
#include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module1200_sprites.h"
+#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module1600_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
+#include "neverhood/modules/module3000_sprites.h"
namespace Neverhood {
@@ -34,7 +36,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)
@@ -59,7 +61,7 @@ Module1600::~Module1600() {
}
void Module1600::createScene(int sceneNum, int which) {
- debug("Module1600::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1600::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -109,7 +111,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);
@@ -183,832 +185,13 @@ 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;
- _hasAgainDestPoint = false;
- _stepError = 0;
- _hasAgainDestPointIndex = false;
- _steps = 0;
- _isBraking = false;
- _yMoveTotalSteps = 0;
- _isBusy = false;
- _isIdle = false;
- _isMoving = true;
- _rectFlag = false;
- _newDeltaXType = -1;
- _soundCounter = 0;
- _pathPoints = NULL;
- _currMoveDirection = 0;
-
- startAnimation(0xD4220027, 0, -1);
- setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
-
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-AsCommonCar::~AsCommonCar() {
- if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone))
- setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X));
-}
-
-void AsCommonCar::setPathPoints(NPointArray *pathPoints) {
- _pathPoints = pathPoints;
-}
-
-void AsCommonCar::update() {
- if (_newDeltaXType >= 0) {
- setDoDeltaX(_newDeltaXType);
- _newDeltaXType = -1;
- }
- AnimatedSprite::update();
- if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) {
- _hasAgainDestPoint = false;
- _hasAgainDestPointIndex = false;
- sendPointMessage(this, 0x2004, _againDestPoint);
- } else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) {
- _hasAgainDestPointIndex = false;
- sendMessage(this, 0x2003, _againDestPointIndex);
- }
- updateMovement();
- updateSound();
-}
-
-void AsCommonCar::upIdle() {
- update();
- if (++_idleCounter >= _idleCounterMax)
- stIdleBlink();
- updateSound();
-}
-
-uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1019:
- SetSpriteUpdate(NULL);
- break;
- case 0x2002:
- // Set the current position without moving
- _currPointIndex = param.asInteger();
- _stepError = 0;
- _x = pathPoint(_currPointIndex).x;
- _y = pathPoint(_currPointIndex).y;
- break;
- case 0x2003:
- // Move to a point by its index
- {
- int newPointIndex = param.asInteger();
- if (_yMoveTotalSteps <= 0 && !_isBusy) {
- _destX = pathPoint(newPointIndex).x;
- _destY = pathPoint(newPointIndex).y;
- if (_currPointIndex < newPointIndex) {
- moveToNextPoint();
- } else if (_currPointIndex == newPointIndex && _stepError == 0) {
- if (_currPointIndex == 0) {
- _yMoveTotalSteps = 0;
- sendMessage(_parentScene, 0x2005, 0);
- } else if (_currPointIndex == (int)_pathPoints->size()) {
- _yMoveTotalSteps = 0;
- sendMessage(_parentScene, 0x2006, 0);
- }
- } else {
- moveToPrevPoint();
- }
- } else {
- _hasAgainDestPointIndex = true;
- _againDestPointIndex = newPointIndex;
- }
- }
- break;
- case 0x2004:
- // Move to the point closest to the parameter point
- {
- int minMatchIndex = -1;
- int minMatchDistance, distance;
- NPoint pt = param.asPoint();
- if (_yMoveTotalSteps <= 0 && !_isBusy) {
- // Check if we're already exiting (or something)
- if ((pt.x <= 20 && _exitDirection == 1) ||
- (pt.x >= 620 && _exitDirection == 3) ||
- (pt.y <= 20 && _exitDirection == 2) ||
- (pt.y >= 460 && _exitDirection == 4))
- break;
- _destX = pt.x;
- _destY = pt.y;
- minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1;
- for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) {
- distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
- if (distance >= minMatchDistance)
- break;
- minMatchDistance = distance;
- minMatchIndex = i;
- }
- for (int i = _currPointIndex; i >= 0; i--) {
- distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
- if (distance >= minMatchDistance)
- break;
- minMatchDistance = distance;
- minMatchIndex = i;
- }
- if (minMatchIndex == -1) {
- if (_currPointIndex == 0)
- moveToPrevPoint();
- else
- SetSpriteUpdate(NULL);
- } else {
- if (minMatchIndex > _currPointIndex)
- moveToNextPoint();
- else
- moveToPrevPoint();
- }
- } else {
- _hasAgainDestPoint = true;
- _againDestPoint = pt;
- }
- }
- break;
- case 0x2007:
- _yMoveTotalSteps = param.asInteger();
- _steps = 0;
- _isBraking = false;
- _lastDistance = 640;
- SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
- break;
- case 0x2008:
- _yMoveTotalSteps = param.asInteger();
- _steps = 0;
- _isBraking = false;
- _lastDistance = 640;
- SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
- break;
- case 0x2009:
- stEnterCar();
- break;
- case 0x200A:
- stLeaveCar();
- break;
- case 0x200E:
- stTurnCar();
- break;
- case 0x200F:
- stCarAtHome();
- _newDeltaXType = param.asInteger();
- break;
- }
- return messageResult;
-}
-
-uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (_isBusy && param.asInteger() == 0x025424A2)
- gotoNextState();
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender) {
- switch (messageNum) {
- case 0x2009:
- stEnterCar();
- break;
- case 0x3002:
- sendMessage(_parentScene, 0x200A, 0);
- SetMessageHandler(&AsCommonCar::handleMessage);
- break;
- }
- return 0;
-}
-
-void AsCommonCar::stCarAtHome() {
- bool doDeltaX = _doDeltaX;
- SetSpriteUpdate(NULL);
- _hasAgainDestPoint = false;
- _hasAgainDestPointIndex = false;
- _isBraking = false;
- _isBusy = false;
- _isIdle = false;
- _isMoving = false;
- _rectFlag = false;
- NextState(&AsCommonCar::stLeanForwardIdle);
- startAnimation(0x35698F78, 0, -1);
- setDoDeltaX(doDeltaX ? 1 : 0);
- _currMoveDirection = 0;
- _newMoveDirection = 0;
- _steps = 0;
- _idleCounter = 0;
- _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
- SetUpdateHandler(&AsCommonCar::upIdle);
- SetMessageHandler(&AsCommonCar::handleMessage);
- FinalizeState(&AsCommonCar::evIdleDone);
-}
-
-void AsCommonCar::updateTurnMovement() {
- if (_turnMoveStatus == 1) {
- _lastDistance = 640;
- _isIdle = false;
- _isBraking = false;
- SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
- } else if (_turnMoveStatus == 2) {
- _lastDistance = 640;
- _isIdle = false;
- _isBraking = false;
- SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
- }
-}
-
-void AsCommonCar::updateMovement() {
- if (_isBraking && !_isIdle && !_isBusy) {
- gotoNextState();
- _isMoving = false;
- _isIdle = true;
- startAnimation(0x192ADD30, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stLeanForwardIdle);
- } else if (!_isBraking && _steps && _isIdle) {
- gotoNextState();
- _isIdle = false;
- startAnimation(0x9966B138, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stUpdateMoveDirection);
- } else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) {
- gotoNextState();
- _currMoveDirection = _newMoveDirection;
- stUpdateMoveDirection();
- }
-}
-
-void AsCommonCar::stEnterCar() {
- startAnimation(0xA86A9538, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stLeanForwardIdle);
-}
-
-void AsCommonCar::stLeaveCar() {
- startAnimation(0xA86A9538, -1, -1);
- _playBackwards = true;
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmLeaveCar);
-}
-
-void AsCommonCar::stLeanForwardIdle() {
- startAnimation(0x35698F78, 0, -1);
- _currMoveDirection = 0;
- _newMoveDirection = 0;
- _steps = 0;
- _idleCounter = 0;
- _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
- SetUpdateHandler(&AsCommonCar::upIdle);
- SetMessageHandler(&AsCommonCar::handleMessage);
- FinalizeState(&AsCommonCar::evIdleDone);
-}
-
-void AsCommonCar::evIdleDone() {
- SetUpdateHandler(&AsCommonCar::update);
-}
-
-void AsCommonCar::stIdleBlink() {
- startAnimation(0xB579A77C, 0, -1);
- _idleCounter = 0;
- _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stLeanForwardIdle);
-}
-
-void AsCommonCar::stUpdateMoveDirection() {
- _isMoving = true;
- if (_currMoveDirection == 1)
- startAnimation(0xD4AA03A4, 0, -1);
- else if (_currMoveDirection == 3)
- startAnimation(0xD00A1364, 0, -1);
- else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX))
- stTurnCar();
- else
- startAnimation(0xD4220027, 0, -1);
- setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0);
-}
-
-void AsCommonCar::moveToNextPoint() {
- if (_currPointIndex >= (int)_pathPoints->size() - 1) {
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2006, 0);
- } else {
- NPoint nextPt = pathPoint(_currPointIndex + 1);
- NPoint currPt = pathPoint(_currPointIndex);
- 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)
- _currMoveDirection = 4;
- else if (_currMoveDirection == 4)
- _currMoveDirection = 2;
- if (_isIdle)
- stTurnCarMoveToNextPoint();
- else
- stBrakeMoveToNextPoint();
- } else {
- if (_steps == 0) {
- gotoNextState();
- _isIdle = false;
- startAnimation(0x9966B138, 0, -1);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- SetUpdateHandler(&AsCommonCar::update);
- NextState(&AsCommonCar::stUpdateMoveDirection);
- }
- _isBraking = false;
- SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
- _lastDistance = 640;
- }
- }
-}
-
-void AsCommonCar::stBrakeMoveToNextPoint() {
- gotoNextState();
- _isBusy = true;
- _isBraking = true;
- startAnimation(0x192ADD30, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stTurnCarMoveToNextPoint);
-}
-
-void AsCommonCar::stTurnCar() {
- // Turn to left/right #1
- gotoNextState();
- _isBusy = true;
- startAnimation(0xF46A0324, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- FinalizeState(&AsCommonCar::evTurnCarDone);
- _turnMoveStatus = 0;
- updateTurnMovement();
-}
-
-void AsCommonCar::stTurnCarMoveToNextPoint() {
- // Turn to left/right #2
- gotoNextState();
- _isBusy = true;
- startAnimation(0xF46A0324, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- FinalizeState(&AsCommonCar::evTurnCarDone);
- _turnMoveStatus = 1;
- updateTurnMovement();
-}
-
-void AsCommonCar::stTurnCarMoveToPrevPoint() {
- // Turn to left/right #3
- FinalizeState(NULL);
- _isBusy = true;
- startAnimation(0xF46A0324, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- FinalizeState(&AsCommonCar::evTurnCarDone);
- _turnMoveStatus = 2;
- updateTurnMovement();
-}
-
-void AsCommonCar::moveToPrevPoint() {
- if (_currPointIndex == 0 && _stepError == 0) {
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2005, 0);
- } else {
- NPoint prevPt;
- NPoint currPt;
- if (_stepError == 0) {
- prevPt = pathPoint(_currPointIndex - 1);
- currPt = pathPoint(_currPointIndex);
- } else {
- prevPt = pathPoint(_currPointIndex);
- currPt = pathPoint(_currPointIndex + 1);
- }
- 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)
- _currMoveDirection = 4;
- else if (_currMoveDirection == 4)
- _currMoveDirection = 2;
- if (_isIdle)
- stTurnCarMoveToPrevPoint();
- else
- stBrakeMoveToPrevPoint();
- } else {
- if (_steps == 0) {
- gotoNextState();
- _isIdle = false;
- startAnimation(0x9966B138, 0, -1);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- SetUpdateHandler(&AsCommonCar::update);
- NextState(&AsCommonCar::stUpdateMoveDirection);
- }
- _isBraking = false;
- SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
- _lastDistance = 640;
- }
- }
-}
-
-void AsCommonCar::stBrakeMoveToPrevPoint() {
- FinalizeState(NULL);
- _isBusy = true;
- _isBraking = true;
- startAnimation(0x192ADD30, 0, -1);
- SetUpdateHandler(&AsCommonCar::update);
- SetMessageHandler(&AsCommonCar::hmAnimation);
- NextState(&AsCommonCar::stTurnCarMoveToPrevPoint);
-}
-
-void AsCommonCar::evTurnCarDone() {
- _isBusy = false;
- setDoDeltaX(2);
- _newMoveDirection = 0;
- stUpdateMoveDirection();
-}
-
-void AsCommonCar::suMoveToNextPoint() {
- int16 newX = _x, newY = _y;
-
- if (_currPointIndex >= (int)_pathPoints->size()) {
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2006, 0);
- return;
- }
-
- if (_isBraking) {
- if (_steps <= 0) {
- sendMessage(this, 0x1019, 0);
- return;
- } else
- _steps--;
- } else if (_steps < 11)
- _steps++;
-
- bool firstTime = true;
- _ySteps = _steps;
- int stepsCtr = _steps;
-
- while (stepsCtr > 0) {
- NPoint pt1;
- NPoint pt2 = pathPoint(_currPointIndex);
- if (_currPointIndex + 1 >= (int)_pathPoints->size())
- pt1 = pathPoint(0);
- else
- pt1 = pathPoint(_currPointIndex + 1);
- int16 deltaX = ABS(pt1.x - pt2.x);
- int16 deltaY = ABS(pt1.y - pt2.y);
- if (deltaX >= deltaY) {
- _newMoveDirection = 2;
- if (pt1.x < pt2.x)
- _newMoveDirection = 4;
- if (stepsCtr + _stepError >= deltaX) {
- stepsCtr -= deltaX;
- stepsCtr += _stepError;
- _stepError = 0;
- _currPointIndex++;
- if (_currPointIndex == (int)_pathPoints->size() - 1)
- stepsCtr = 0;
- newX = pathPoint(_currPointIndex).x;
- newY = pathPoint(_currPointIndex).y;
- } else {
- _stepError += stepsCtr;
- if (pt1.x >= pt2.x)
- newX += stepsCtr;
- else
- newX -= stepsCtr;
- if (pt1.y >= pt2.y)
- newY = pt2.y + (deltaY * _stepError) / deltaX;
- else
- newY = pt2.y - (deltaY * _stepError) / deltaX;
- stepsCtr = 0;
- }
- } else {
- _newMoveDirection = 3;
- if (pt1.y < pt2.y)
- _newMoveDirection = 1;
- if (firstTime) {
- if (pt1.y >= pt2.y)
- stepsCtr += 7;
- else {
- stepsCtr -= 4;
- if (stepsCtr < 0)
- stepsCtr = 0;
- }
- _ySteps = stepsCtr;
- }
- if (stepsCtr + _stepError >= deltaY) {
- stepsCtr -= deltaY;
- stepsCtr += _stepError;
- _stepError = 0;
- _currPointIndex++;
- if (_currPointIndex == (int)_pathPoints->size() - 1)
- stepsCtr = 0;
- newX = pathPoint(_currPointIndex).x;
- newY = pathPoint(_currPointIndex).y;
- } else {
- _stepError += stepsCtr;
- if (pt1.x >= pt2.x)
- newX = pt2.x + (deltaX * _stepError) / deltaY;
- else
- newX = pt2.x - (deltaX * _stepError) / deltaY;
- if (pt1.y >= pt2.y)
- newY += stepsCtr;
- else
- newY -= stepsCtr;
- stepsCtr = 0;
- }
- }
- firstTime = false;
- }
-
- if (_yMoveTotalSteps != 0) {
- _x = newX;
- _y = newY;
- _yMoveTotalSteps -= _ySteps;
- if (_yMoveTotalSteps <= 0) {
- _isBraking = true;
- _yMoveTotalSteps = 0;
- }
- } else {
- int distance = calcDistance(_destX, _destY, _x, _y);
- _x = newX;
- _y = newY;
- if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
- _exitDirection = 0;
- _inMainArea = true;
- } else if (_inMainArea) {
- _destX = pathPoint(_pathPoints->size() - 1).x;
- _destY = pathPoint(_pathPoints->size() - 1).y;
- _inMainArea = false;
- if (_x <= 20)
- _exitDirection = 1;
- else if (_x >= 620)
- _exitDirection = 3;
- else if (_y <= 20)
- _exitDirection = 2;
- else if (_y >= 460)
- _exitDirection = 4;
- if (_exitDirection != 0 && _isBraking) {
- _isBraking = false;
- _steps = 11;
- }
- }
- if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
- (_exitDirection == 0 && _lastDistance + 20 < distance))
- _isBraking = true;
- if (distance < _lastDistance)
- _lastDistance = distance;
- if (_currPointIndex == (int)_pathPoints->size() - 1) {
- _isBraking = true;
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2006, 0);
- }
- }
-
-}
-
-void AsCommonCar::suMoveToPrevPoint() {
- int16 newX = _x, newY = _y;
-
- if (_currPointIndex == 0 && _stepError == 0) {
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2005, 0);
- return;
- }
-
- if (_isBraking) {
- if (_steps <= 0) {
- sendMessage(this, 0x1019, 0);
- return;
- } else
- _steps--;
- } else if (_steps < 11)
- _steps++;
-
- bool firstTime = true;
- _ySteps = _steps;
- int stepsCtr = _steps;
-
- while (stepsCtr > 0) {
- if (_stepError == 0)
- _currPointIndex--;
- NPoint pt1;
- NPoint pt2 = pathPoint(_currPointIndex);
- if (_currPointIndex + 1 >= (int)_pathPoints->size())
- pt1 = pathPoint(0);
- else
- pt1 = pathPoint(_currPointIndex + 1);
- int16 deltaX = ABS(pt1.x - pt2.x);
- int16 deltaY = ABS(pt1.y - pt2.y);
- if (deltaX >= deltaY) {
- _newMoveDirection = 4;
- if (pt1.x < pt2.x)
- _newMoveDirection = 2;
- if (_stepError == 0)
- _stepError = deltaX;
- if (stepsCtr > _stepError) {
- stepsCtr -= _stepError;
- _stepError = 0;
- if (_currPointIndex == 0)
- stepsCtr = 0;
- newX = pathPoint(_currPointIndex).x;
- newY = pathPoint(_currPointIndex).y;
- } else {
- _stepError -= stepsCtr;
- if (pt1.x >= pt2.x)
- newX -= stepsCtr;
- else
- newX += stepsCtr;
- if (pt1.y >= pt2.y)
- newY = pt2.y + (deltaY * _stepError) / deltaX;
- else
- newY = pt2.y - (deltaY * _stepError) / deltaX;
- stepsCtr = 0;
- }
- } else {
- _newMoveDirection = 1;
- if (pt1.y < pt2.y)
- _newMoveDirection = 3;
- if (firstTime) {
- if (pt1.y >= pt2.y) {
- stepsCtr -= 4;
- if (stepsCtr < 0)
- stepsCtr = 0;
- } else {
- stepsCtr += 7;
- }
- _ySteps = stepsCtr;
- }
- if (_stepError == 0)
- _stepError = deltaY;
- if (stepsCtr > _stepError) {
- stepsCtr -= _stepError;
- _stepError = 0;
- if (_currPointIndex == 0)
- stepsCtr = 0;
- newX = pathPoint(_currPointIndex).x;
- newY = pathPoint(_currPointIndex).y;
- } else {
- _stepError -= stepsCtr;
- if (pt1.x >= pt2.x)
- newX = pt2.x + (deltaX * _stepError) / deltaY;
- else
- newX = pt2.x - (deltaX * _stepError) / deltaY;
- if (pt1.y >= pt2.y)
- newY -= stepsCtr;
- else
- newY += stepsCtr;
- stepsCtr = 0;
- }
- }
- firstTime = false;
- }
-
- if (_yMoveTotalSteps != 0) {
- _x = newX;
- _y = newY;
- _yMoveTotalSteps -= _ySteps;
- if (_yMoveTotalSteps <= 0) {
- _isBraking = true;
- _yMoveTotalSteps = 0;
- }
- } else {
- int distance = calcDistance(_destX, _destY, _x, _y);
- _x = newX;
- _y = newY;
- if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
- _exitDirection = 0;
- _inMainArea = true;
- } else if (_inMainArea) {
- _destX = pathPoint(0).x;
- _destY = pathPoint(0).y;
- _inMainArea = false;
- if (_x <= 20)
- _exitDirection = 1;
- else if (_x >= 620)
- _exitDirection = 3;
- else if (_y <= 20)
- _exitDirection = 2;
- else if (_y >= 460)
- _exitDirection = 4;
- if (_exitDirection != 0 && _isBraking) {
- _isBraking = false;
- _steps = 11;
- }
- }
- if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
- (_exitDirection == 0 && _lastDistance + 20 < distance))
- _isBraking = true;
- if (distance < _lastDistance)
- _lastDistance = distance;
- if (_currPointIndex == 0 && _stepError == 0) {
- _isBraking = true;
- _yMoveTotalSteps = 0;
- sendMessage(this, 0x1019, 0);
- sendMessage(_parentScene, 0x2005, 0);
- }
- }
-
-}
-
-void AsCommonCar::updateSound() {
- int maxSoundCounter = 0;
- _soundCounter++;
- if (_steps != 0 && !_isIdle) {
- if (_currMoveDirection == 1)
- maxSoundCounter = 18 - _steps;
- else if (_currMoveDirection == 3) {
- maxSoundCounter = 5 - _steps;
- if (maxSoundCounter < 1)
- maxSoundCounter = 1;
- } else
- maxSoundCounter = 14 - _steps;
- } else
- maxSoundCounter = 21;
- if (_soundCounter >= maxSoundCounter) {
- sendMessage(_parentScene, 0x200D, 0);
- _soundCounter = 0;
- }
-}
-
-AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y)
- : AnimatedSprite(vm, 0x1209E09F, 1100, x, y) {
-
- setDoDeltaX(1);
- startAnimation(0x1209E09F, 1, -1);
- _newStickFrameIndex = 1;
-}
-
-AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y)
- : AnimatedSprite(vm, 0x1209E09F, 100, x, y) {
-
- setDoDeltaX(1);
- _newStickFrameIndex = 0;
-}
-
-AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar)
- : AnimatedSprite(vm, 1100), _asCar(asCar) {
-
- createSurface1(0x60281C10, 150);
- startAnimation(0x60281C10, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- SetUpdateHandler(&AsCommonCarConnector::update);
-}
-
-void AsCommonCarConnector::update() {
- _x = _asCar->getX();
- _y = _asCar->getY();
- AnimatedSprite::update();
-}
-
-void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
- DataResource &dataResource) {
- const uint trackCount = size();
- minMatchTrackIndex = -1;
- minMatchDistance = 640;
- for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) {
- NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName);
- for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) {
- NPoint testPt = (*pointList)[pointIndex];
- int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y);
- if (distance < minMatchDistance) {
- minMatchTrackIndex = trackIndex;
- minMatchDistance = distance;
- }
- }
- }
-}
-
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 +275,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 +317,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
_carClipFlag = true;
_carStatus = 0;
}
-
+
_palette->addPalette("paKlayRed", 0, 64, 0);
-
+
}
Scene1608::~Scene1608() {
@@ -1308,7 +491,7 @@ uint32 Scene1608::hmCarAtHome(int messageNum, const MessageParam &param, Entity
}
return 0;
}
-
+
void Scene1608::updateKlaymenCliprect() {
if (_kmScene1608->getX() <= 375)
_kmScene1608->setClipRect(_clipRect1);
@@ -1321,17 +504,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 +591,5 @@ bool Scene1609::testVars() {
return true;
}
-
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1600.h b/engines/neverhood/modules/module1600.h
index 0bf44ff7b8..f08eaad8fc 100644
--- a/engines/neverhood/modules/module1600.h
+++ b/engines/neverhood/modules/module1600.h
@@ -26,12 +26,9 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module3000.h"
namespace Neverhood {
-// Module1600
-
class Module1600 : public Module {
public:
Module1600(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -42,90 +39,7 @@ protected:
void updateScene();
};
-class AsCommonCar : public AnimatedSprite {
-public:
- AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
- ~AsCommonCar();
- void setPathPoints(NPointArray *pathPoints);
-protected:
- Scene *_parentScene;
- NPointArray *_pathPoints;
- int _newMoveDirection;
- int _currMoveDirection;
- int _exitDirection;
- int _currPointIndex;
- bool _hasAgainDestPoint;
- NPoint _againDestPoint;
- bool _hasAgainDestPointIndex;
- int _againDestPointIndex;
- bool _inMainArea;
- bool _isBraking;
- bool _isBusy;
- bool _isIdle;
- bool _isMoving;
- bool _rectFlag;
- int _idleCounter;
- int _idleCounterMax;
- int _steps;
- int _stepError;
- int _lastDistance;
- int _yMoveTotalSteps;
- int _ySteps;
- int _newDeltaXType;
- int _soundCounter;
- int _turnMoveStatus;
- int16 _destX, _destY;
- NPoint pathPoint(uint index) { return (*_pathPoints)[index]; }
- void update();
- void upIdle();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender);
- void stCarAtHome();
- void updateTurnMovement();
- void updateMovement();
- void stEnterCar();
- void stLeaveCar();
- void stLeanForwardIdle();
- void evIdleDone();
- void stIdleBlink();
- void stUpdateMoveDirection();
- void stTurnCar();
- void moveToNextPoint();
- void stBrakeMoveToNextPoint();
- void stTurnCarMoveToNextPoint();
- void moveToPrevPoint();
- void stBrakeMoveToPrevPoint();
- void stTurnCarMoveToPrevPoint();
- void evTurnCarDone();
- void suMoveToNextPoint();
- void suMoveToPrevPoint();
- void updateSound();
-};
-
-class AsCommonIdleCarLower : public AnimatedSprite {
-public:
- AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y);
-};
-
-class AsCommonIdleCarFull : public AnimatedSprite {
-public:
- AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y);
-};
-
-class AsCommonCarConnector : public AnimatedSprite {
-public:
- AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar);
-protected:
- AsCommonCar *_asCar;
- void update();
-};
-
-class Tracks : public Common::Array<TrackInfo*> {
-public:
- void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
- DataResource &dataResource);
-};
+class AsCommonCar;
class Scene1608 : public Scene {
public:
@@ -161,7 +75,10 @@ protected:
void updateKlaymenCliprect();
};
+class AsScene3011Symbol;
+
class Scene1609 : public Scene {
+ friend class Console;
public:
Scene1609(NeverhoodEngine *vm, Module *parentModule);
protected:
diff --git a/engines/neverhood/modules/module1600_sprites.cpp b/engines/neverhood/modules/module1600_sprites.cpp
new file mode 100644
index 0000000000..06a00c82c0
--- /dev/null
+++ b/engines/neverhood/modules/module1600_sprites.cpp
@@ -0,0 +1,934 @@
+/* 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 "neverhood/modules/module1600_sprites.h"
+
+namespace Neverhood {
+
+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;
+ _hasAgainDestPoint = false;
+ _stepError = 0;
+ _hasAgainDestPointIndex = false;
+ _steps = 0;
+ _isBraking = false;
+ _yMoveTotalSteps = 0;
+ _isBusy = false;
+ _isIdle = false;
+ _isMoving = true;
+ _rectFlag = false;
+ _newDeltaXType = -1;
+ _soundCounter = 0;
+ _pathPoints = NULL;
+ _currMoveDirection = 0;
+
+ startAnimation(0xD4220027, 0, -1);
+ setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
+
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+AsCommonCar::~AsCommonCar() {
+ if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone))
+ setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X));
+}
+
+void AsCommonCar::setPathPoints(NPointArray *pathPoints) {
+ _pathPoints = pathPoints;
+}
+
+void AsCommonCar::update() {
+ if (_newDeltaXType >= 0) {
+ setDoDeltaX(_newDeltaXType);
+ _newDeltaXType = -1;
+ }
+ AnimatedSprite::update();
+ if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) {
+ _hasAgainDestPoint = false;
+ _hasAgainDestPointIndex = false;
+ sendPointMessage(this, 0x2004, _againDestPoint);
+ } else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) {
+ _hasAgainDestPointIndex = false;
+ sendMessage(this, 0x2003, _againDestPointIndex);
+ }
+ updateMovement();
+ updateSound();
+}
+
+void AsCommonCar::upIdle() {
+ update();
+ if (++_idleCounter >= _idleCounterMax)
+ stIdleBlink();
+ updateSound();
+}
+
+uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1019:
+ SetSpriteUpdate(NULL);
+ break;
+ case 0x2002:
+ // Set the current position without moving
+ _currPointIndex = param.asInteger();
+ _stepError = 0;
+ _x = pathPoint(_currPointIndex).x;
+ _y = pathPoint(_currPointIndex).y;
+ break;
+ case 0x2003:
+ // Move to a point by its index
+ {
+ int newPointIndex = param.asInteger();
+ if (_yMoveTotalSteps <= 0 && !_isBusy) {
+ _destX = pathPoint(newPointIndex).x;
+ _destY = pathPoint(newPointIndex).y;
+ if (_currPointIndex < newPointIndex) {
+ moveToNextPoint();
+ } else if (_currPointIndex == newPointIndex && _stepError == 0) {
+ if (_currPointIndex == 0) {
+ _yMoveTotalSteps = 0;
+ sendMessage(_parentScene, 0x2005, 0);
+ } else if (_currPointIndex == (int)_pathPoints->size()) {
+ _yMoveTotalSteps = 0;
+ sendMessage(_parentScene, 0x2006, 0);
+ }
+ } else {
+ moveToPrevPoint();
+ }
+ } else {
+ _hasAgainDestPointIndex = true;
+ _againDestPointIndex = newPointIndex;
+ }
+ }
+ break;
+ case 0x2004:
+ // Move to the point closest to the parameter point
+ {
+ int minMatchIndex = -1;
+ int minMatchDistance, distance;
+ NPoint pt = param.asPoint();
+ if (_yMoveTotalSteps <= 0 && !_isBusy) {
+ // Check if we're already exiting (or something)
+ if ((pt.x <= 20 && _exitDirection == 1) ||
+ (pt.x >= 620 && _exitDirection == 3) ||
+ (pt.y <= 20 && _exitDirection == 2) ||
+ (pt.y >= 460 && _exitDirection == 4))
+ break;
+ _destX = pt.x;
+ _destY = pt.y;
+ minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1;
+ for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) {
+ distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
+ if (distance >= minMatchDistance)
+ break;
+ minMatchDistance = distance;
+ minMatchIndex = i;
+ }
+ for (int i = _currPointIndex; i >= 0; i--) {
+ distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
+ if (distance >= minMatchDistance)
+ break;
+ minMatchDistance = distance;
+ minMatchIndex = i;
+ }
+ if (minMatchIndex == -1) {
+ if (_currPointIndex == 0)
+ moveToPrevPoint();
+ else
+ SetSpriteUpdate(NULL);
+ } else {
+ if (minMatchIndex > _currPointIndex)
+ moveToNextPoint();
+ else
+ moveToPrevPoint();
+ }
+ } else {
+ _hasAgainDestPoint = true;
+ _againDestPoint = pt;
+ }
+ }
+ break;
+ case 0x2007:
+ _yMoveTotalSteps = param.asInteger();
+ _steps = 0;
+ _isBraking = false;
+ _lastDistance = 640;
+ SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+ break;
+ case 0x2008:
+ _yMoveTotalSteps = param.asInteger();
+ _steps = 0;
+ _isBraking = false;
+ _lastDistance = 640;
+ SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+ break;
+ case 0x2009:
+ stEnterCar();
+ break;
+ case 0x200A:
+ stLeaveCar();
+ break;
+ case 0x200E:
+ stTurnCar();
+ break;
+ case 0x200F:
+ stCarAtHome();
+ _newDeltaXType = param.asInteger();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (_isBusy && param.asInteger() == 0x025424A2)
+ gotoNextState();
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender) {
+ switch (messageNum) {
+ case 0x2009:
+ stEnterCar();
+ break;
+ case 0x3002:
+ sendMessage(_parentScene, 0x200A, 0);
+ SetMessageHandler(&AsCommonCar::handleMessage);
+ break;
+ }
+ return 0;
+}
+
+void AsCommonCar::stCarAtHome() {
+ bool doDeltaX = _doDeltaX;
+ SetSpriteUpdate(NULL);
+ _hasAgainDestPoint = false;
+ _hasAgainDestPointIndex = false;
+ _isBraking = false;
+ _isBusy = false;
+ _isIdle = false;
+ _isMoving = false;
+ _rectFlag = false;
+ NextState(&AsCommonCar::stLeanForwardIdle);
+ startAnimation(0x35698F78, 0, -1);
+ setDoDeltaX(doDeltaX ? 1 : 0);
+ _currMoveDirection = 0;
+ _newMoveDirection = 0;
+ _steps = 0;
+ _idleCounter = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+ SetUpdateHandler(&AsCommonCar::upIdle);
+ SetMessageHandler(&AsCommonCar::handleMessage);
+ FinalizeState(&AsCommonCar::evIdleDone);
+}
+
+void AsCommonCar::updateTurnMovement() {
+ if (_turnMoveStatus == 1) {
+ _lastDistance = 640;
+ _isIdle = false;
+ _isBraking = false;
+ SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+ } else if (_turnMoveStatus == 2) {
+ _lastDistance = 640;
+ _isIdle = false;
+ _isBraking = false;
+ SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+ }
+}
+
+void AsCommonCar::updateMovement() {
+ if (_isBraking && !_isIdle && !_isBusy) {
+ gotoNextState();
+ _isMoving = false;
+ _isIdle = true;
+ startAnimation(0x192ADD30, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stLeanForwardIdle);
+ } else if (!_isBraking && _steps && _isIdle) {
+ gotoNextState();
+ _isIdle = false;
+ startAnimation(0x9966B138, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stUpdateMoveDirection);
+ } else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) {
+ gotoNextState();
+ _currMoveDirection = _newMoveDirection;
+ stUpdateMoveDirection();
+ }
+}
+
+void AsCommonCar::stEnterCar() {
+ startAnimation(0xA86A9538, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stLeanForwardIdle);
+}
+
+void AsCommonCar::stLeaveCar() {
+ startAnimation(0xA86A9538, -1, -1);
+ _playBackwards = true;
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmLeaveCar);
+}
+
+void AsCommonCar::stLeanForwardIdle() {
+ startAnimation(0x35698F78, 0, -1);
+ _currMoveDirection = 0;
+ _newMoveDirection = 0;
+ _steps = 0;
+ _idleCounter = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+ SetUpdateHandler(&AsCommonCar::upIdle);
+ SetMessageHandler(&AsCommonCar::handleMessage);
+ FinalizeState(&AsCommonCar::evIdleDone);
+}
+
+void AsCommonCar::evIdleDone() {
+ SetUpdateHandler(&AsCommonCar::update);
+}
+
+void AsCommonCar::stIdleBlink() {
+ startAnimation(0xB579A77C, 0, -1);
+ _idleCounter = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stLeanForwardIdle);
+}
+
+void AsCommonCar::stUpdateMoveDirection() {
+ _isMoving = true;
+ if (_currMoveDirection == 1)
+ startAnimation(0xD4AA03A4, 0, -1);
+ else if (_currMoveDirection == 3)
+ startAnimation(0xD00A1364, 0, -1);
+ else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX))
+ stTurnCar();
+ else
+ startAnimation(0xD4220027, 0, -1);
+ setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0);
+}
+
+void AsCommonCar::moveToNextPoint() {
+ if (_currPointIndex >= (int)_pathPoints->size() - 1) {
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ } else {
+ NPoint nextPt = pathPoint(_currPointIndex + 1);
+ NPoint currPt = pathPoint(_currPointIndex);
+ 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)
+ _currMoveDirection = 4;
+ else if (_currMoveDirection == 4)
+ _currMoveDirection = 2;
+ if (_isIdle)
+ stTurnCarMoveToNextPoint();
+ else
+ stBrakeMoveToNextPoint();
+ } else {
+ if (_steps == 0) {
+ gotoNextState();
+ _isIdle = false;
+ startAnimation(0x9966B138, 0, -1);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ SetUpdateHandler(&AsCommonCar::update);
+ NextState(&AsCommonCar::stUpdateMoveDirection);
+ }
+ _isBraking = false;
+ SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+ _lastDistance = 640;
+ }
+ }
+}
+
+void AsCommonCar::stBrakeMoveToNextPoint() {
+ gotoNextState();
+ _isBusy = true;
+ _isBraking = true;
+ startAnimation(0x192ADD30, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stTurnCarMoveToNextPoint);
+}
+
+void AsCommonCar::stTurnCar() {
+ // Turn to left/right #1
+ gotoNextState();
+ _isBusy = true;
+ startAnimation(0xF46A0324, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ FinalizeState(&AsCommonCar::evTurnCarDone);
+ _turnMoveStatus = 0;
+ updateTurnMovement();
+}
+
+void AsCommonCar::stTurnCarMoveToNextPoint() {
+ // Turn to left/right #2
+ gotoNextState();
+ _isBusy = true;
+ startAnimation(0xF46A0324, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ FinalizeState(&AsCommonCar::evTurnCarDone);
+ _turnMoveStatus = 1;
+ updateTurnMovement();
+}
+
+void AsCommonCar::stTurnCarMoveToPrevPoint() {
+ // Turn to left/right #3
+ FinalizeState(NULL);
+ _isBusy = true;
+ startAnimation(0xF46A0324, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ FinalizeState(&AsCommonCar::evTurnCarDone);
+ _turnMoveStatus = 2;
+ updateTurnMovement();
+}
+
+void AsCommonCar::moveToPrevPoint() {
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ } else {
+ NPoint prevPt;
+ NPoint currPt;
+ if (_stepError == 0) {
+ prevPt = pathPoint(_currPointIndex - 1);
+ currPt = pathPoint(_currPointIndex);
+ } else {
+ prevPt = pathPoint(_currPointIndex);
+ currPt = pathPoint(_currPointIndex + 1);
+ }
+ 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)
+ _currMoveDirection = 4;
+ else if (_currMoveDirection == 4)
+ _currMoveDirection = 2;
+ if (_isIdle)
+ stTurnCarMoveToPrevPoint();
+ else
+ stBrakeMoveToPrevPoint();
+ } else {
+ if (_steps == 0) {
+ gotoNextState();
+ _isIdle = false;
+ startAnimation(0x9966B138, 0, -1);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ SetUpdateHandler(&AsCommonCar::update);
+ NextState(&AsCommonCar::stUpdateMoveDirection);
+ }
+ _isBraking = false;
+ SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+ _lastDistance = 640;
+ }
+ }
+}
+
+void AsCommonCar::stBrakeMoveToPrevPoint() {
+ FinalizeState(NULL);
+ _isBusy = true;
+ _isBraking = true;
+ startAnimation(0x192ADD30, 0, -1);
+ SetUpdateHandler(&AsCommonCar::update);
+ SetMessageHandler(&AsCommonCar::hmAnimation);
+ NextState(&AsCommonCar::stTurnCarMoveToPrevPoint);
+}
+
+void AsCommonCar::evTurnCarDone() {
+ _isBusy = false;
+ setDoDeltaX(2);
+ _newMoveDirection = 0;
+ stUpdateMoveDirection();
+}
+
+void AsCommonCar::suMoveToNextPoint() {
+ int16 newX = _x, newY = _y;
+
+ if (_currPointIndex >= (int)_pathPoints->size()) {
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ return;
+ }
+
+ if (_isBraking) {
+ if (_steps <= 0) {
+ sendMessage(this, 0x1019, 0);
+ return;
+ } else
+ _steps--;
+ } else if (_steps < 11)
+ _steps++;
+
+ bool firstTime = true;
+ _ySteps = _steps;
+ int stepsCtr = _steps;
+
+ while (stepsCtr > 0) {
+ NPoint pt1;
+ NPoint pt2 = pathPoint(_currPointIndex);
+ if (_currPointIndex + 1 >= (int)_pathPoints->size())
+ pt1 = pathPoint(0);
+ else
+ pt1 = pathPoint(_currPointIndex + 1);
+ int16 deltaX = ABS(pt1.x - pt2.x);
+ int16 deltaY = ABS(pt1.y - pt2.y);
+ if (deltaX >= deltaY) {
+ _newMoveDirection = 2;
+ if (pt1.x < pt2.x)
+ _newMoveDirection = 4;
+ if (stepsCtr + _stepError >= deltaX) {
+ stepsCtr -= deltaX;
+ stepsCtr += _stepError;
+ _stepError = 0;
+ _currPointIndex++;
+ if (_currPointIndex == (int)_pathPoints->size() - 1)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError += stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX += stepsCtr;
+ else
+ newX -= stepsCtr;
+ if (pt1.y >= pt2.y)
+ newY = pt2.y + (deltaY * _stepError) / deltaX;
+ else
+ newY = pt2.y - (deltaY * _stepError) / deltaX;
+ stepsCtr = 0;
+ }
+ } else {
+ _newMoveDirection = 3;
+ if (pt1.y < pt2.y)
+ _newMoveDirection = 1;
+ if (firstTime) {
+ if (pt1.y >= pt2.y)
+ stepsCtr += 7;
+ else {
+ stepsCtr -= 4;
+ if (stepsCtr < 0)
+ stepsCtr = 0;
+ }
+ _ySteps = stepsCtr;
+ }
+ if (stepsCtr + _stepError >= deltaY) {
+ stepsCtr -= deltaY;
+ stepsCtr += _stepError;
+ _stepError = 0;
+ _currPointIndex++;
+ if (_currPointIndex == (int)_pathPoints->size() - 1)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError += stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX = pt2.x + (deltaX * _stepError) / deltaY;
+ else
+ newX = pt2.x - (deltaX * _stepError) / deltaY;
+ if (pt1.y >= pt2.y)
+ newY += stepsCtr;
+ else
+ newY -= stepsCtr;
+ stepsCtr = 0;
+ }
+ }
+ firstTime = false;
+ }
+
+ if (_yMoveTotalSteps != 0) {
+ _x = newX;
+ _y = newY;
+ _yMoveTotalSteps -= _ySteps;
+ if (_yMoveTotalSteps <= 0) {
+ _isBraking = true;
+ _yMoveTotalSteps = 0;
+ }
+ } else {
+ int distance = calcDistance(_destX, _destY, _x, _y);
+ _x = newX;
+ _y = newY;
+ if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+ _exitDirection = 0;
+ _inMainArea = true;
+ } else if (_inMainArea) {
+ _destX = pathPoint(_pathPoints->size() - 1).x;
+ _destY = pathPoint(_pathPoints->size() - 1).y;
+ _inMainArea = false;
+ if (_x <= 20)
+ _exitDirection = 1;
+ else if (_x >= 620)
+ _exitDirection = 3;
+ else if (_y <= 20)
+ _exitDirection = 2;
+ else if (_y >= 460)
+ _exitDirection = 4;
+ if (_exitDirection != 0 && _isBraking) {
+ _isBraking = false;
+ _steps = 11;
+ }
+ }
+ if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+ (_exitDirection == 0 && _lastDistance + 20 < distance))
+ _isBraking = true;
+ if (distance < _lastDistance)
+ _lastDistance = distance;
+ if (_currPointIndex == (int)_pathPoints->size() - 1) {
+ _isBraking = true;
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ }
+ }
+
+}
+
+void AsCommonCar::suMoveToPrevPoint() {
+ int16 newX = _x, newY = _y;
+
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ return;
+ }
+
+ if (_isBraking) {
+ if (_steps <= 0) {
+ sendMessage(this, 0x1019, 0);
+ return;
+ } else
+ _steps--;
+ } else if (_steps < 11)
+ _steps++;
+
+ bool firstTime = true;
+ _ySteps = _steps;
+ int stepsCtr = _steps;
+
+ while (stepsCtr > 0) {
+ if (_stepError == 0)
+ _currPointIndex--;
+ NPoint pt1;
+ NPoint pt2 = pathPoint(_currPointIndex);
+ if (_currPointIndex + 1 >= (int)_pathPoints->size())
+ pt1 = pathPoint(0);
+ else
+ pt1 = pathPoint(_currPointIndex + 1);
+ int16 deltaX = ABS(pt1.x - pt2.x);
+ int16 deltaY = ABS(pt1.y - pt2.y);
+ if (deltaX >= deltaY) {
+ _newMoveDirection = 4;
+ if (pt1.x < pt2.x)
+ _newMoveDirection = 2;
+ if (_stepError == 0)
+ _stepError = deltaX;
+ if (stepsCtr > _stepError) {
+ stepsCtr -= _stepError;
+ _stepError = 0;
+ if (_currPointIndex == 0)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError -= stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX -= stepsCtr;
+ else
+ newX += stepsCtr;
+ if (pt1.y >= pt2.y)
+ newY = pt2.y + (deltaY * _stepError) / deltaX;
+ else
+ newY = pt2.y - (deltaY * _stepError) / deltaX;
+ stepsCtr = 0;
+ }
+ } else {
+ _newMoveDirection = 1;
+ if (pt1.y < pt2.y)
+ _newMoveDirection = 3;
+ if (firstTime) {
+ if (pt1.y >= pt2.y) {
+ stepsCtr -= 4;
+ if (stepsCtr < 0)
+ stepsCtr = 0;
+ } else {
+ stepsCtr += 7;
+ }
+ _ySteps = stepsCtr;
+ }
+ if (_stepError == 0)
+ _stepError = deltaY;
+ if (stepsCtr > _stepError) {
+ stepsCtr -= _stepError;
+ _stepError = 0;
+ if (_currPointIndex == 0)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError -= stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX = pt2.x + (deltaX * _stepError) / deltaY;
+ else
+ newX = pt2.x - (deltaX * _stepError) / deltaY;
+ if (pt1.y >= pt2.y)
+ newY -= stepsCtr;
+ else
+ newY += stepsCtr;
+ stepsCtr = 0;
+ }
+ }
+ firstTime = false;
+ }
+
+ if (_yMoveTotalSteps != 0) {
+ _x = newX;
+ _y = newY;
+ _yMoveTotalSteps -= _ySteps;
+ if (_yMoveTotalSteps <= 0) {
+ _isBraking = true;
+ _yMoveTotalSteps = 0;
+ }
+ } else {
+ int distance = calcDistance(_destX, _destY, _x, _y);
+ _x = newX;
+ _y = newY;
+ if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+ _exitDirection = 0;
+ _inMainArea = true;
+ } else if (_inMainArea) {
+ _destX = pathPoint(0).x;
+ _destY = pathPoint(0).y;
+ _inMainArea = false;
+ if (_x <= 20)
+ _exitDirection = 1;
+ else if (_x >= 620)
+ _exitDirection = 3;
+ else if (_y <= 20)
+ _exitDirection = 2;
+ else if (_y >= 460)
+ _exitDirection = 4;
+ if (_exitDirection != 0 && _isBraking) {
+ _isBraking = false;
+ _steps = 11;
+ }
+ }
+ if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+ (_exitDirection == 0 && _lastDistance + 20 < distance))
+ _isBraking = true;
+ if (distance < _lastDistance)
+ _lastDistance = distance;
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _isBraking = true;
+ _yMoveTotalSteps = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ }
+ }
+
+}
+
+void AsCommonCar::updateSound() {
+ int maxSoundCounter = 0;
+ _soundCounter++;
+ if (_steps != 0 && !_isIdle) {
+ if (_currMoveDirection == 1)
+ maxSoundCounter = 18 - _steps;
+ else if (_currMoveDirection == 3) {
+ maxSoundCounter = 5 - _steps;
+ if (maxSoundCounter < 1)
+ maxSoundCounter = 1;
+ } else
+ maxSoundCounter = 14 - _steps;
+ } else
+ maxSoundCounter = 21;
+ if (_soundCounter >= maxSoundCounter) {
+ sendMessage(_parentScene, 0x200D, 0);
+ _soundCounter = 0;
+ }
+}
+
+AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y)
+ : AnimatedSprite(vm, 0x1209E09F, 1100, x, y) {
+
+ setDoDeltaX(1);
+ startAnimation(0x1209E09F, 1, -1);
+ _newStickFrameIndex = 1;
+}
+
+AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y)
+ : AnimatedSprite(vm, 0x1209E09F, 100, x, y) {
+
+ setDoDeltaX(1);
+ _newStickFrameIndex = 0;
+}
+
+AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar)
+ : AnimatedSprite(vm, 1100), _asCar(asCar) {
+
+ createSurface1(0x60281C10, 150);
+ startAnimation(0x60281C10, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ SetUpdateHandler(&AsCommonCarConnector::update);
+}
+
+void AsCommonCarConnector::update() {
+ _x = _asCar->getX();
+ _y = _asCar->getY();
+ AnimatedSprite::update();
+}
+
+void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
+ DataResource &dataResource) {
+ const uint trackCount = size();
+ minMatchTrackIndex = -1;
+ minMatchDistance = 640;
+ for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) {
+ NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName);
+ for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) {
+ NPoint testPt = (*pointList)[pointIndex];
+ int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y);
+ if (distance < minMatchDistance) {
+ minMatchTrackIndex = trackIndex;
+ minMatchDistance = distance;
+ }
+ }
+ }
+}
+
+KmScene1608::KmScene1608(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2032:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2032, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2032, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1600_sprites.h b/engines/neverhood/modules/module1600_sprites.h
new file mode 100644
index 0000000000..fa59475dad
--- /dev/null
+++ b/engines/neverhood/modules/module1600_sprites.h
@@ -0,0 +1,126 @@
+/* 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 NEVERHOOD_MODULES_MODULE1600_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1600_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsCommonCar : public AnimatedSprite {
+public:
+ AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+ ~AsCommonCar();
+ void setPathPoints(NPointArray *pathPoints);
+protected:
+ Scene *_parentScene;
+ NPointArray *_pathPoints;
+ int _newMoveDirection;
+ int _currMoveDirection;
+ int _exitDirection;
+ int _currPointIndex;
+ bool _hasAgainDestPoint;
+ NPoint _againDestPoint;
+ bool _hasAgainDestPointIndex;
+ int _againDestPointIndex;
+ bool _inMainArea;
+ bool _isBraking;
+ bool _isBusy;
+ bool _isIdle;
+ bool _isMoving;
+ bool _rectFlag;
+ int _idleCounter;
+ int _idleCounterMax;
+ int _steps;
+ int _stepError;
+ int _lastDistance;
+ int _yMoveTotalSteps;
+ int _ySteps;
+ int _newDeltaXType;
+ int _soundCounter;
+ int _turnMoveStatus;
+ int16 _destX, _destY;
+ NPoint pathPoint(uint index) { return (*_pathPoints)[index]; }
+ void update();
+ void upIdle();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender);
+ void stCarAtHome();
+ void updateTurnMovement();
+ void updateMovement();
+ void stEnterCar();
+ void stLeaveCar();
+ void stLeanForwardIdle();
+ void evIdleDone();
+ void stIdleBlink();
+ void stUpdateMoveDirection();
+ void stTurnCar();
+ void moveToNextPoint();
+ void stBrakeMoveToNextPoint();
+ void stTurnCarMoveToNextPoint();
+ void moveToPrevPoint();
+ void stBrakeMoveToPrevPoint();
+ void stTurnCarMoveToPrevPoint();
+ void evTurnCarDone();
+ void suMoveToNextPoint();
+ void suMoveToPrevPoint();
+ void updateSound();
+};
+
+class AsCommonIdleCarLower : public AnimatedSprite {
+public:
+ AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class AsCommonIdleCarFull : public AnimatedSprite {
+public:
+ AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class AsCommonCarConnector : public AnimatedSprite {
+public:
+ AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar);
+protected:
+ AsCommonCar *_asCar;
+ void update();
+};
+
+class Tracks : public Common::Array<TrackInfo*> {
+public:
+ void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
+ DataResource &dataResource);
+};
+
+class KmScene1608 : public Klaymen {
+public:
+ KmScene1608(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1600_SPRITES_H */
diff --git a/engines/neverhood/modules/module1700.cpp b/engines/neverhood/modules/module1700.cpp
index 3a6d1f80cb..e3a5fc3663 100644
--- a/engines/neverhood/modules/module1700.cpp
+++ b/engines/neverhood/modules/module1700.cpp
@@ -20,8 +20,9 @@
*
*/
-#include "neverhood/modules/module1700.h"
#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1700.h"
+#include "neverhood/modules/module1700_sprites.h"
namespace Neverhood {
@@ -36,7 +37,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);
@@ -58,7 +59,7 @@ Module1700::~Module1700() {
}
void Module1700::createScene(int sceneNum, int which) {
- debug("Module1700::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1700::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -125,8 +126,6 @@ void Module1700::updateScene() {
}
}
}
-
-// Scene1705
static const uint32 kScene1705FileHashes[] = {
0x910EA801, 0x920EA801, 0x940EA801,
@@ -135,52 +134,11 @@ static const uint32 kScene1705FileHashes[] = {
0xD10EA801, 0x110EA801, 0x910EA800
};
-SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex)
- : StaticSprite(vm, fileHash, 100) {
-
- _x = _spriteResource.getPosition().x + symbolIndex * 30;
- _y = _spriteResource.getPosition().y + 160;
- updatePosition();
-}
-
-SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash)
- : StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) {
-
- if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) {
- SetMessageHandler(&SsScene1705Tape::handleMessage);
- } else {
- setVisible(false);
- SetMessageHandler(NULL);
- }
- _collisionBoundsOffset = _drawOffset;
- _collisionBoundsOffset.x -= 4;
- _collisionBoundsOffset.y -= 8;
- _collisionBoundsOffset.width += 8;
- _collisionBoundsOffset.height += 16;
- Sprite::updateBounds();
-}
-
-uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setSubVar(VA_HAS_TAPE, _tapeIndex, 1);
- setVisible(false);
- SetMessageHandler(NULL);
- break;
- }
- return messageResult;
-}
-
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 +229,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..09daff2acf 100644
--- a/engines/neverhood/modules/module1700.h
+++ b/engines/neverhood/modules/module1700.h
@@ -26,7 +26,6 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/smackerscene.h"
namespace Neverhood {
@@ -40,22 +39,6 @@ protected:
void updateScene();
};
-// Scene1705
-
-class SsScene1705WallSymbol : public StaticSprite {
-public:
- SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex);
-};
-
-class SsScene1705Tape : public StaticSprite {
-public:
- SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash);
-protected:
- Scene *_parentScene;
- uint32 _tapeIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene1705 : public Scene {
public:
Scene1705(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module1700_sprites.cpp b/engines/neverhood/modules/module1700_sprites.cpp
new file mode 100644
index 0000000000..6274e5a8cc
--- /dev/null
+++ b/engines/neverhood/modules/module1700_sprites.cpp
@@ -0,0 +1,156 @@
+/* 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 "neverhood/modules/module1700_sprites.h"
+
+namespace Neverhood {
+
+SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex)
+ : StaticSprite(vm, fileHash, 100) {
+
+ _x = _spriteResource.getPosition().x + symbolIndex * 30;
+ _y = _spriteResource.getPosition().y + 160;
+ updatePosition();
+}
+
+SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash)
+ : StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) {
+
+ if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) {
+ SetMessageHandler(&SsScene1705Tape::handleMessage);
+ } else {
+ setVisible(false);
+ SetMessageHandler(NULL);
+ }
+ _collisionBoundsOffset = _drawOffset;
+ _collisionBoundsOffset.x -= 4;
+ _collisionBoundsOffset.y -= 8;
+ _collisionBoundsOffset.width += 8;
+ _collisionBoundsOffset.height += 16;
+ Sprite::updateBounds();
+}
+
+uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setSubVar(VA_HAS_TAPE, _tapeIndex, 1);
+ setVisible(false);
+ SetMessageHandler(NULL);
+ break;
+ }
+ return messageResult;
+}
+
+KmScene1705::KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4803:
+ GotoState(&Klaymen::stFallSkipJump);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter) {
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ }
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0x5E0A4905);
+ break;
+ case 0x483E:
+ teleporterDisappear(0xD86E4477);
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1700_sprites.h b/engines/neverhood/modules/module1700_sprites.h
new file mode 100644
index 0000000000..4117de01d9
--- /dev/null
+++ b/engines/neverhood/modules/module1700_sprites.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE1700_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1700_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class SsScene1705WallSymbol : public StaticSprite {
+public:
+ SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex);
+};
+
+class SsScene1705Tape : public StaticSprite {
+public:
+ SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash);
+protected:
+ Scene *_parentScene;
+ uint32 _tapeIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1705 : public Klaymen {
+public:
+ KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1700_SPRITES_H */
diff --git a/engines/neverhood/modules/module1800.cpp b/engines/neverhood/modules/module1800.cpp
index 2a6057f9c8..282292a516 100644
--- a/engines/neverhood/modules/module1800.cpp
+++ b/engines/neverhood/modules/module1800.cpp
@@ -20,9 +20,10 @@
*
*/
-#include "neverhood/modules/module1800.h"
-#include "neverhood/navigationscene.h"
+#include "neverhood/diskplayerscene.h"
#include "neverhood/menumodule.h"
+#include "neverhood/navigationscene.h"
+#include "neverhood/modules/module1800.h"
namespace Neverhood {
@@ -38,7 +39,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);
@@ -61,7 +62,7 @@ Module1800::~Module1800() {
void Module1800::createScene(int sceneNum, int which) {
static const byte kNavigationTypes00[] = {1, 0, 2, 0};
static const byte kNavigationTypes01[] = {5};
- debug("Module1800::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1800::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -177,5 +178,5 @@ void Module1800::updateScene() {
}
}
}
-
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1900.cpp b/engines/neverhood/modules/module1900.cpp
index 1a9ffa127b..a920893755 100644
--- a/engines/neverhood/modules/module1900.cpp
+++ b/engines/neverhood/modules/module1900.cpp
@@ -21,7 +21,7 @@
*/
#include "neverhood/modules/module1900.h"
-#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1900_sprites.h"
namespace Neverhood {
@@ -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
@@ -52,7 +52,7 @@ Module1900::~Module1900() {
}
void Module1900::createScene(int sceneNum, int which) {
- debug("Module1900::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module1900::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -84,11 +84,9 @@ void Module1900::updateScene() {
}
}
-// Scene1901
-
Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite;
setRectList(0x004B34C8);
@@ -98,7 +96,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)) {
@@ -126,399 +124,10 @@ Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
}
-static const NPoint kAsScene1907SymbolGroundPositions[] = {
- {160, 310}, { 90, 340}, {210, 335},
- {210, 380}, {310, 340}, {290, 400},
- {400, 375}, {370, 435}, {475, 415}
-};
-
-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}
-};
-
-static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
- {275, 136}, {244, 156}, {238, 183},
- {221, 207}, {199, 228}, {168, 262},
- {145, 285}, {123, 307}, {103, 331}
-};
-
-static const uint32 kAsScene1907SymbolFileHashes[] = {
- 0x006A1034, 0x006A1010, 0x006A1814,
- 0x006A1016, 0x006A0014, 0x002A1014,
- 0x00EA1014, 0x206A1014, 0x046A1414
-};
-
-bool AsScene1907Symbol::_plugInFailed = false;
-int AsScene1907Symbol::_plugInTryCount = 0;
-
-AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex)
- : AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) {
-
- _plugInFailed = false;
- _plugInTryCount = 0;
-
- if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
- _isPluggedIn = true;
- _currPositionIndex = elementIndex;
- if (!getGlobalVar(V_STAIRS_DOWN)) {
- _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
- _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
- } else {
- _x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x;
- _y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y;
- }
- createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else {
- _isPluggedIn = false;
- _currPositionIndex = positionIndex;
- loadSound(0, 0x74231924);
- loadSound(1, 0x36691914);
- loadSound(2, 0x5421D806);
- _parentScene->setPositionFree(_currPositionIndex, false);
- _x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x;
- _y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y;
- createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
- _newStickFrameIndex = 0;
- }
- _collisionBoundsOffset.set(0, 0, 80, 80);
- Sprite::updateBounds();
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
-
-}
-
-void AsScene1907Symbol::update() {
- updateAnim();
- handleSpriteUpdate();
- updatePosition();
- if (_plugInFailed && _plugInTryCount == 0)
- _plugInFailed = false;
-}
-
-uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (!_isPluggedIn && !_plugInFailed) {
- tryToPlugIn();
- messageResult = 1;
- } else
- messageResult = 0;
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1907Symbol::suTryToPlugIn() {
- _currStep++;
- _x -= _deltaX;
- _y -= _deltaY;
- if (_currStep == 16) {
- _x -= _smallDeltaX;
- _y -= _smallDeltaY;
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1907Symbol::suFallOff() {
- if (_fallOffDelay != 0) {
- _fallOffDelay--;
- } else {
- _y += _yAccel;
- _yAccel += 8;
- if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
- _y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y;
- stFallOffHitGround();
- }
- }
-}
-
-void AsScene1907Symbol::suFallOffHitGround() {
-
- if (_x == _someX - _xBreak)
- _x -= _smallDeltaX;
- else
- _x -= _deltaX;
-
- if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
- _y -= _someY;
- }
-
- if (_currStep < 8) {
- _y -= _yAccel;
- _yAccel -= 4;
- if (_yAccel < 0)
- _yAccel = 0;
- } else if (_currStep < 15) {
- _y += _yAccel;
- _yAccel += 4;
- } else {
- _y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
- cbFallOffHitGroundEvent();
- }
-
- _currStep++;
-}
-
-void AsScene1907Symbol::suMoveDown() {
- _y += _yIncr;
- if (_yIncr < 11)
- _yIncr++;
- if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) {
- _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
- _isMoving = false;
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1907Symbol::suMoveUp() {
- _y -= _yIncr;
- if (getGlobalVar(V_WALL_BROKEN)) {
- if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y)
- _yIncr--;
- else
- _yIncr++;
- } else
- _yIncr = 2;
- if (_yIncr > 9)
- _yIncr = 9;
- else if (_yIncr < 1)
- _yIncr = 1;
- if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
- _y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y;
- _isMoving = false;
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene1907Symbol::tryToPlugIn() {
- _isPluggedIn = true;
- _plugInTryCount++;
- _newPositionIndex = _parentScene->getNextPosition();
- _parentScene->setPositionFree(_currPositionIndex, true);
- sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex);
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
- SetUpdateHandler(&AsScene1907Symbol::update);
- SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn);
- SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn);
- _currStep = 0;
- _deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16;
- _smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x;
- _deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16;
- _smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y;
- if (_elementIndex == _newPositionIndex) {
- NextState(&AsScene1907Symbol::stPlugIn);
- } else {
- _plugInFailed = true;
- NextState(&AsScene1907Symbol::stPlugInFail);
- }
-}
-
-void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) {
- _isPluggedIn = false;
- _newPositionIndex = newPositionIndex;
- _fallOffDelay = fallOffDelay;
- _parentScene->setPositionFree(_newPositionIndex, false);
- _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
- _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
- _someX = _x;
- _someY = _y;
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0);
- _playBackwards = true;
- _newStickFrameIndex = STICK_LAST_FRAME;
- _currStep = 0;
- _yAccel = 1;
- SetUpdateHandler(&AsScene1907Symbol::update);
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
- SetSpriteUpdate(&AsScene1907Symbol::suFallOff);
-}
-
-void AsScene1907Symbol::stFallOffHitGround() {
- playSound(1);
- sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex);
- Entity::_priority = 1000 - _newPositionIndex;
- _parentScene->removeCollisionSprite(this);
- _parentScene->addCollisionSprite(this);
- SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround);
- NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent);
- _newStickFrameIndex = 0;
- _currStep = 0;
- _yAccel = 30;
- _deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15;
- _xBreak = _deltaX * 15;
- _smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak;
- _someY = 0;
- if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y)
- _someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
-}
-
-void AsScene1907Symbol::cbFallOffHitGroundEvent() {
- _currPositionIndex = _newPositionIndex;
- if (_plugInTryCount > 0)
- _plugInTryCount--;
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
- SetSpriteUpdate(NULL);
- updateBounds();
- playSound(2);
-}
-
-void AsScene1907Symbol::stPlugIn() {
- playSound(0);
- _currPositionIndex = _newPositionIndex;
- stopAnimation();
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
- SetSpriteUpdate(NULL);
- if (_elementIndex == 8)
- sendMessage(_parentScene, 0x2001, 0);
-}
-
-void AsScene1907Symbol::stPlugInFail() {
- _currPositionIndex = _newPositionIndex;
- stopAnimation();
- _parentScene->plugInFailed();
-}
-
-void AsScene1907Symbol::moveUp() {
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
- stopAnimation();
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
- SetSpriteUpdate(&AsScene1907Symbol::suMoveUp);
- _yIncr = 1;
- _isMoving = true;
-}
-
-void AsScene1907Symbol::moveDown() {
- startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
- stopAnimation();
- SetMessageHandler(&AsScene1907Symbol::handleMessage);
- SetSpriteUpdate(&AsScene1907Symbol::suMoveDown);
- _yIncr = 4;
- _isMoving = true;
-}
-
-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);
- SetUpdateHandler(&SsScene1907UpDownButton::update);
- SetMessageHandler(&SsScene1907UpDownButton::handleMessage);
- if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
- if (getGlobalVar(V_STAIRS_DOWN))
- setToDownPosition();
- else
- setToUpPosition();
- }
-}
-
-void SsScene1907UpDownButton::update() {
- updatePosition();
- if (_countdown1 != 0 && (--_countdown1 == 0)) {
- setVisible(false);
- sendMessage(_parentScene, 0x2000, 0);
- }
-}
-
-uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
- setVisible(true);
- _countdown1 = 4;
- updatePosition();
- playSound(0);
- }
- messageResult = 1;
- }
- return messageResult;
-}
-
-void SsScene1907UpDownButton::setToUpPosition() {
- _y = _spriteResource.getPosition().y;
- updateBounds();
- updatePosition();
-}
-
-void SsScene1907UpDownButton::setToDownPosition() {
- _y = _spriteResource.getPosition().y + 174;
- updateBounds();
- updatePosition();
-}
-
-AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1400) {
-
- createSurface1(0x110A1061, 1500);
- _x = 320;
- _y = 240;
- startAnimation(0x110A1061, 0, -1);
- _newStickFrameIndex = 0;
- setVisible(false);
- _needRefresh = true;
- AnimatedSprite::updatePosition();
- SetUpdateHandler(&AsScene1907WaterHint::update);
- SetMessageHandler(&Sprite::handleMessage);
-}
-
-void AsScene1907WaterHint::update() {
- updateAnim();
- updatePosition();
-}
-
-uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene1907WaterHint::show() {
- setVisible(true);
- startAnimation(0x110A1061, 0, -1);
- SetMessageHandler(&AsScene1907WaterHint::hmShowing);
- NextState(&AsScene1907WaterHint::hide);
-}
-
-void AsScene1907WaterHint::hide() {
- stopAnimation();
- setVisible(false);
- 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 +138,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 +151,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 +161,7 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
void Scene1907::update() {
Scene::update();
-
+
if (_hasPlugInFailed) {
int fallOffDelay = 0;
_hasPlugInFailed = false;
@@ -619,7 +228,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/module1900.h b/engines/neverhood/modules/module1900.h
index abb5eb1d87..d785c6f506 100644
--- a/engines/neverhood/modules/module1900.h
+++ b/engines/neverhood/modules/module1900.h
@@ -26,7 +26,6 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
namespace Neverhood {
@@ -41,80 +40,14 @@ protected:
void updateScene();
};
-// Scene1901
-
class Scene1901 : public Scene {
public:
Scene1901(NeverhoodEngine *vm, Module *parentModule, int which);
};
-// Scene1907
-
-class Scene1907;
-
-class AsScene1907Symbol : public AnimatedSprite {
-public:
- AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex);
- void moveUp();
- void moveDown();
- void fallOff(int newPositionIndex, int fallOffDelay);
- bool isPluggedIn() { return _isPluggedIn; }
- bool isMoving() { return _isMoving; }
-protected:
- Scene1907 *_parentScene;
- int _elementIndex;
- int _currPositionIndex;
- int _newPositionIndex;
- bool _isPluggedIn;
- bool _isMoving;
- int _someX, _someY;
- int _xBreak;
- int _currStep;
- int _yAccel;
- int _yIncr;
- int _fallOffDelay;
- int _deltaX, _smallDeltaX;
- int _deltaY, _smallDeltaY;
- // Dumb, change if possible
- static bool _plugInFailed;
- static int _plugInTryCount;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender);
- void suTryToPlugIn();
- void suFallOff();
- void suFallOffHitGround();
- void suMoveDown();
- void suMoveUp();
- void tryToPlugIn();
- void stFallOffHitGround();
- void cbFallOffHitGroundEvent();
- void stPlugIn();
- void stPlugInFail();
-};
-
-class AsScene1907WaterHint : public AnimatedSprite {
-public:
- AsScene1907WaterHint(NeverhoodEngine *vm);
- void show();
-protected:
- void update();
- uint32 hmShowing(int messageNum, const MessageParam &param, Entity *sender);
- void hide();
-};
-
-class SsScene1907UpDownButton : public StaticSprite {
-public:
- SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol);
- void setToUpPosition();
- void setToDownPosition();
-protected:
- Scene1907 *_parentScene;
- AsScene1907Symbol *_asScene1907Symbol;
- int _countdown1;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class AsScene1907Symbol;
+class SsScene1907UpDownButton;
+class AsScene1907WaterHint;
class Scene1907 : public Scene {
public:
diff --git a/engines/neverhood/modules/module1900_sprites.cpp b/engines/neverhood/modules/module1900_sprites.cpp
new file mode 100644
index 0000000000..09c0b132d5
--- /dev/null
+++ b/engines/neverhood/modules/module1900_sprites.cpp
@@ -0,0 +1,456 @@
+/* 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 "neverhood/modules/module1900.h"
+#include "neverhood/modules/module1900_sprites.h"
+
+namespace Neverhood {
+
+static const NPoint kAsScene1907SymbolGroundPositions[] = {
+ {160, 310}, { 90, 340}, {210, 335},
+ {210, 380}, {310, 340}, {290, 400},
+ {400, 375}, {370, 435}, {475, 415}
+};
+
+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}
+};
+
+static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
+ {275, 136}, {244, 156}, {238, 183},
+ {221, 207}, {199, 228}, {168, 262},
+ {145, 285}, {123, 307}, {103, 331}
+};
+
+static const uint32 kAsScene1907SymbolFileHashes[] = {
+ 0x006A1034, 0x006A1010, 0x006A1814,
+ 0x006A1016, 0x006A0014, 0x002A1014,
+ 0x00EA1014, 0x206A1014, 0x046A1414
+};
+
+bool AsScene1907Symbol::_plugInFailed = false;
+int AsScene1907Symbol::_plugInTryCount = 0;
+
+AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex)
+ : AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) {
+
+ _plugInFailed = false;
+ _plugInTryCount = 0;
+
+ if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+ _isPluggedIn = true;
+ _currPositionIndex = elementIndex;
+ if (!getGlobalVar(V_STAIRS_DOWN)) {
+ _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+ } else {
+ _x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y;
+ }
+ createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else {
+ _isPluggedIn = false;
+ _currPositionIndex = positionIndex;
+ loadSound(0, 0x74231924);
+ loadSound(1, 0x36691914);
+ loadSound(2, 0x5421D806);
+ _parentScene->setPositionFree(_currPositionIndex, false);
+ _x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y;
+ createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ _newStickFrameIndex = 0;
+ }
+ _collisionBoundsOffset.set(0, 0, 80, 80);
+ Sprite::updateBounds();
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+
+}
+
+void AsScene1907Symbol::update() {
+ updateAnim();
+ handleSpriteUpdate();
+ updatePosition();
+ if (_plugInFailed && _plugInTryCount == 0)
+ _plugInFailed = false;
+}
+
+uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isPluggedIn && !_plugInFailed) {
+ tryToPlugIn();
+ messageResult = 1;
+ } else
+ messageResult = 0;
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1907Symbol::suTryToPlugIn() {
+ _currStep++;
+ _x -= _deltaX;
+ _y -= _deltaY;
+ if (_currStep == 16) {
+ _x -= _smallDeltaX;
+ _y -= _smallDeltaY;
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1907Symbol::suFallOff() {
+ if (_fallOffDelay != 0) {
+ _fallOffDelay--;
+ } else {
+ _y += _yAccel;
+ _yAccel += 8;
+ if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+ _y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y;
+ stFallOffHitGround();
+ }
+ }
+}
+
+void AsScene1907Symbol::suFallOffHitGround() {
+
+ if (_x == _someX - _xBreak)
+ _x -= _smallDeltaX;
+ else
+ _x -= _deltaX;
+
+ if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+ _y -= _someY;
+ }
+
+ if (_currStep < 8) {
+ _y -= _yAccel;
+ _yAccel -= 4;
+ if (_yAccel < 0)
+ _yAccel = 0;
+ } else if (_currStep < 15) {
+ _y += _yAccel;
+ _yAccel += 4;
+ } else {
+ _y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+ cbFallOffHitGroundEvent();
+ }
+
+ _currStep++;
+}
+
+void AsScene1907Symbol::suMoveDown() {
+ _y += _yIncr;
+ if (_yIncr < 11)
+ _yIncr++;
+ if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) {
+ _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
+ _isMoving = false;
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1907Symbol::suMoveUp() {
+ _y -= _yIncr;
+ if (getGlobalVar(V_WALL_BROKEN)) {
+ if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y)
+ _yIncr--;
+ else
+ _yIncr++;
+ } else
+ _yIncr = 2;
+ if (_yIncr > 9)
+ _yIncr = 9;
+ else if (_yIncr < 1)
+ _yIncr = 1;
+ if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
+ _y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y;
+ _isMoving = false;
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene1907Symbol::tryToPlugIn() {
+ _isPluggedIn = true;
+ _plugInTryCount++;
+ _newPositionIndex = _parentScene->getNextPosition();
+ _parentScene->setPositionFree(_currPositionIndex, true);
+ sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex);
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ SetUpdateHandler(&AsScene1907Symbol::update);
+ SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn);
+ SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn);
+ _currStep = 0;
+ _deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16;
+ _smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x;
+ _deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16;
+ _smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y;
+ if (_elementIndex == _newPositionIndex) {
+ NextState(&AsScene1907Symbol::stPlugIn);
+ } else {
+ _plugInFailed = true;
+ NextState(&AsScene1907Symbol::stPlugInFail);
+ }
+}
+
+void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) {
+ _isPluggedIn = false;
+ _newPositionIndex = newPositionIndex;
+ _fallOffDelay = fallOffDelay;
+ _parentScene->setPositionFree(_newPositionIndex, false);
+ _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+ _someX = _x;
+ _someY = _y;
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0);
+ _playBackwards = true;
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ _currStep = 0;
+ _yAccel = 1;
+ SetUpdateHandler(&AsScene1907Symbol::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteUpdate(&AsScene1907Symbol::suFallOff);
+}
+
+void AsScene1907Symbol::stFallOffHitGround() {
+ playSound(1);
+ sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex);
+ Entity::_priority = 1000 - _newPositionIndex;
+ _parentScene->removeCollisionSprite(this);
+ _parentScene->addCollisionSprite(this);
+ SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround);
+ NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent);
+ _newStickFrameIndex = 0;
+ _currStep = 0;
+ _yAccel = 30;
+ _deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15;
+ _xBreak = _deltaX * 15;
+ _smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak;
+ _someY = 0;
+ if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y)
+ _someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+}
+
+void AsScene1907Symbol::cbFallOffHitGroundEvent() {
+ _currPositionIndex = _newPositionIndex;
+ if (_plugInTryCount > 0)
+ _plugInTryCount--;
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteUpdate(NULL);
+ updateBounds();
+ playSound(2);
+}
+
+void AsScene1907Symbol::stPlugIn() {
+ playSound(0);
+ _currPositionIndex = _newPositionIndex;
+ stopAnimation();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteUpdate(NULL);
+ if (_elementIndex == 8)
+ sendMessage(_parentScene, 0x2001, 0);
+}
+
+void AsScene1907Symbol::stPlugInFail() {
+ _currPositionIndex = _newPositionIndex;
+ stopAnimation();
+ _parentScene->plugInFailed();
+}
+
+void AsScene1907Symbol::moveUp() {
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+ stopAnimation();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteUpdate(&AsScene1907Symbol::suMoveUp);
+ _yIncr = 1;
+ _isMoving = true;
+}
+
+void AsScene1907Symbol::moveDown() {
+ startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+ stopAnimation();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteUpdate(&AsScene1907Symbol::suMoveDown);
+ _yIncr = 4;
+ _isMoving = true;
+}
+
+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);
+ SetUpdateHandler(&SsScene1907UpDownButton::update);
+ SetMessageHandler(&SsScene1907UpDownButton::handleMessage);
+ if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+ if (getGlobalVar(V_STAIRS_DOWN))
+ setToDownPosition();
+ else
+ setToUpPosition();
+ }
+}
+
+void SsScene1907UpDownButton::update() {
+ updatePosition();
+ if (_countdown1 != 0 && (--_countdown1 == 0)) {
+ setVisible(false);
+ sendMessage(_parentScene, 0x2000, 0);
+ }
+}
+
+uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+ setVisible(true);
+ _countdown1 = 4;
+ updatePosition();
+ playSound(0);
+ }
+ messageResult = 1;
+ }
+ return messageResult;
+}
+
+void SsScene1907UpDownButton::setToUpPosition() {
+ _y = _spriteResource.getPosition().y;
+ updateBounds();
+ updatePosition();
+}
+
+void SsScene1907UpDownButton::setToDownPosition() {
+ _y = _spriteResource.getPosition().y + 174;
+ updateBounds();
+ updatePosition();
+}
+
+AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1400) {
+
+ createSurface1(0x110A1061, 1500);
+ _x = 320;
+ _y = 240;
+ startAnimation(0x110A1061, 0, -1);
+ _newStickFrameIndex = 0;
+ setVisible(false);
+ _needRefresh = true;
+ AnimatedSprite::updatePosition();
+ SetUpdateHandler(&AsScene1907WaterHint::update);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+void AsScene1907WaterHint::update() {
+ updateAnim();
+ updatePosition();
+}
+
+uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1907WaterHint::show() {
+ setVisible(true);
+ startAnimation(0x110A1061, 0, -1);
+ SetMessageHandler(&AsScene1907WaterHint::hmShowing);
+ NextState(&AsScene1907WaterHint::hide);
+}
+
+void AsScene1907WaterHint::hide() {
+ stopAnimation();
+ setVisible(false);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+KmScene1901::KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1900_sprites.h b/engines/neverhood/modules/module1900_sprites.h
new file mode 100644
index 0000000000..7e57b11618
--- /dev/null
+++ b/engines/neverhood/modules/module1900_sprites.h
@@ -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.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE1900_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1900_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class Scene1907;
+
+class AsScene1907Symbol : public AnimatedSprite {
+public:
+ AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex);
+ void moveUp();
+ void moveDown();
+ void fallOff(int newPositionIndex, int fallOffDelay);
+ bool isPluggedIn() { return _isPluggedIn; }
+ bool isMoving() { return _isMoving; }
+protected:
+ Scene1907 *_parentScene;
+ int _elementIndex;
+ int _currPositionIndex;
+ int _newPositionIndex;
+ bool _isPluggedIn;
+ bool _isMoving;
+ int _someX, _someY;
+ int _xBreak;
+ int _currStep;
+ int _yAccel;
+ int _yIncr;
+ int _fallOffDelay;
+ int _deltaX, _smallDeltaX;
+ int _deltaY, _smallDeltaY;
+ // Dumb, change if possible
+ static bool _plugInFailed;
+ static int _plugInTryCount;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender);
+ void suTryToPlugIn();
+ void suFallOff();
+ void suFallOffHitGround();
+ void suMoveDown();
+ void suMoveUp();
+ void tryToPlugIn();
+ void stFallOffHitGround();
+ void cbFallOffHitGroundEvent();
+ void stPlugIn();
+ void stPlugInFail();
+};
+
+class AsScene1907WaterHint : public AnimatedSprite {
+public:
+ AsScene1907WaterHint(NeverhoodEngine *vm);
+ void show();
+protected:
+ void update();
+ uint32 hmShowing(int messageNum, const MessageParam &param, Entity *sender);
+ void hide();
+};
+
+class SsScene1907UpDownButton : public StaticSprite {
+public:
+ SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol);
+ void setToUpPosition();
+ void setToDownPosition();
+protected:
+ Scene1907 *_parentScene;
+ AsScene1907Symbol *_asScene1907Symbol;
+ int _countdown1;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene1901 : public Klaymen {
+public:
+ KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1900_SPRITES_H */
diff --git a/engines/neverhood/modules/module2000.cpp b/engines/neverhood/modules/module2000.cpp
index 5039da1b01..3364f60f8b 100644
--- a/engines/neverhood/modules/module2000.cpp
+++ b/engines/neverhood/modules/module2000.cpp
@@ -21,14 +21,13 @@
*/
#include "neverhood/modules/module2000.h"
-#include "neverhood/gamemodule.h"
-#include "neverhood/navigationscene.h"
+#include "neverhood/modules/module2000_sprites.h"
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)
@@ -43,7 +42,7 @@ Module2000::~Module2000() {
}
void Module2000::createScene(int sceneNum, int which) {
- debug("Module2000::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2000::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -137,9 +136,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 +152,7 @@ uint32 Scene2001::handleMessage(int messageNum, const MessageParam &param, Entit
setRectList(0x004B3670);
_klaymen->setKlaymenIdleTable1();
}
- }
+ }
return 0;
}
diff --git a/engines/neverhood/modules/module2000.h b/engines/neverhood/modules/module2000.h
index fa62f9a70e..8dc72c57dc 100644
--- a/engines/neverhood/modules/module2000.h
+++ b/engines/neverhood/modules/module2000.h
@@ -26,7 +26,6 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
namespace Neverhood {
@@ -41,8 +40,6 @@ protected:
void updateScene();
};
-// Scene2001
-
class Scene2001 : public Scene {
public:
Scene2001(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2000_sprites.cpp b/engines/neverhood/modules/module2000_sprites.cpp
new file mode 100644
index 0000000000..c9c1481aa7
--- /dev/null
+++ b/engines/neverhood/modules/module2000_sprites.cpp
@@ -0,0 +1,92 @@
+/* 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 "neverhood/modules/module2000_sprites.h"
+
+namespace Neverhood {
+
+KmScene2001::KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stWalkingFirst);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0xBE68CC54);
+ break;
+ case 0x483E:
+ teleporterDisappear(0x18AB4ED4);
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2000_sprites.h b/engines/neverhood/modules/module2000_sprites.h
new file mode 100644
index 0000000000..ca84aa73ca
--- /dev/null
+++ b/engines/neverhood/modules/module2000_sprites.h
@@ -0,0 +1,41 @@
+/* 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 NEVERHOOD_MODULES_MODULE2000_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2000_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class KmScene2001 : public Klaymen {
+public:
+ KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2000_SPRITES_H */
diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp
index 0d7f3dd22a..db7258b066 100644
--- a/engines/neverhood/modules/module2100.cpp
+++ b/engines/neverhood/modules/module2100.cpp
@@ -20,9 +20,9 @@
*
*/
+#include "neverhood/modules/module1200_sprites.h"
#include "neverhood/modules/module2100.h"
-#include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1200.h"
+#include "neverhood/modules/module2100_sprites.h"
namespace Neverhood {
@@ -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)
@@ -47,7 +47,7 @@ Module2100::~Module2100() {
}
void Module2100::createScene(int sceneNum, int which) {
- debug("Module2100::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2100::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -74,133 +74,14 @@ void Module2100::updateScene() {
}
}
-// Scene2101
-
-AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen)
- : AnimatedSprite(vm, 1100) {
-
- createSurface(100, 328, 347);
- _x = 320;
- _y = 240;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2101Door::handleMessage);
- if (isOpen) {
- startAnimation(0x0C202B9C, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else
- setVisible(false);
-}
-
-uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- stOpenDoor();
- break;
- case 0x4809:
- stCloseDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene2101Door::stOpenDoor() {
- startAnimation(0x0C202B9C, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- setVisible(true);
- playSound(0, calcHash("fxDoorOpen32"));
-}
-
-void AsScene2101Door::stCloseDoor() {
- startAnimation(0xC222A8D4, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- setVisible(true);
- playSound(0, calcHash("fxDoorClose32"));
- NextState(&AsScene2101Door::stCloseDoorDone);
-}
-
-void AsScene2101Door::stCloseDoorDone() {
- stopAnimation();
- setVisible(false);
-}
-
-AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
- : AnimatedSprite(vm, 1400), _klaymen(klaymen) {
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
- createSurface(1200, 88, 165);
- setVisible(false);
-}
-
-uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2001:
- _x = _klaymen->getX();
- _y = _klaymen->getY() - 132;
- startAnimation(0x0422255A, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
-SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
- : StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0),
- _fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) {
-
- SetUpdateHandler(&SsCommonFloorButton::update);
- SetMessageHandler(&SsCommonFloorButton::handleMessage);
- if (_soundFileHash == 0)
- _soundFileHash = 0x44141000;
- createSurface(1010, 61, 30);
- if (_fileHash1)
- loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
- else
- setVisible(false);
-}
-
-void SsCommonFloorButton::update() {
- if (_countdown != 0 && (--_countdown == 0)) {
- sendMessage(_parentScene, 0x1022, 1010);
- if (_fileHash1)
- loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
- else
- setVisible(false);
- }
-}
-
-uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x480B:
- sendMessage(_parentScene, 0x480B, 0);
- setVisible(true);
- sendMessage(_parentScene, 0x1022, 990);
- loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition);
- _countdown = 16;
- playSound(0, _soundFileHash);
- break;
- }
- return messageResult;
-}
-
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 +91,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 +137,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..c5256434d9 100644
--- a/engines/neverhood/modules/module2100.h
+++ b/engines/neverhood/modules/module2100.h
@@ -40,38 +40,6 @@ protected:
void updateScene();
};
-// Scene1901
-
-class AsScene2101Door : public AnimatedSprite {
-public:
- AsScene2101Door(NeverhoodEngine *vm, bool isOpen);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stCloseDoor();
- void stCloseDoorDone();
-};
-
-class AsScene2101HitByDoorEffect : public AnimatedSprite {
-public:
- AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen);
-protected:
- Sprite *_klaymen;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsCommonFloorButton : public StaticSprite {
-public:
- SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
-protected:
- Scene *_parentScene;
- uint32 _soundFileHash;
- uint32 _fileHash1, _fileHash2;
- int16 _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2101 : public Scene {
public:
Scene2101(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2100_sprites.cpp b/engines/neverhood/modules/module2100_sprites.cpp
new file mode 100644
index 0000000000..707ebe342f
--- /dev/null
+++ b/engines/neverhood/modules/module2100_sprites.cpp
@@ -0,0 +1,260 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "neverhood/modules/module2100_sprites.h"
+
+namespace Neverhood {
+
+AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen)
+ : AnimatedSprite(vm, 1100) {
+
+ createSurface(100, 328, 347);
+ _x = 320;
+ _y = 240;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2101Door::handleMessage);
+ if (isOpen) {
+ startAnimation(0x0C202B9C, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else
+ setVisible(false);
+}
+
+uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ stOpenDoor();
+ break;
+ case 0x4809:
+ stCloseDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2101Door::stOpenDoor() {
+ startAnimation(0x0C202B9C, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ setVisible(true);
+ playSound(0, calcHash("fxDoorOpen32"));
+}
+
+void AsScene2101Door::stCloseDoor() {
+ startAnimation(0xC222A8D4, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ setVisible(true);
+ playSound(0, calcHash("fxDoorClose32"));
+ NextState(&AsScene2101Door::stCloseDoorDone);
+}
+
+void AsScene2101Door::stCloseDoorDone() {
+ stopAnimation();
+ setVisible(false);
+}
+
+AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
+ : AnimatedSprite(vm, 1400), _klaymen(klaymen) {
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
+ createSurface(1200, 88, 165);
+ setVisible(false);
+}
+
+uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2001:
+ _x = _klaymen->getX();
+ _y = _klaymen->getY() - 132;
+ startAnimation(0x0422255A, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
+ : StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0),
+ _fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) {
+
+ SetUpdateHandler(&SsCommonFloorButton::update);
+ SetMessageHandler(&SsCommonFloorButton::handleMessage);
+ if (_soundFileHash == 0)
+ _soundFileHash = 0x44141000;
+ createSurface(1010, 61, 30);
+ if (_fileHash1)
+ loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+ else
+ setVisible(false);
+}
+
+void SsCommonFloorButton::update() {
+ if (_countdown != 0 && (--_countdown == 0)) {
+ sendMessage(_parentScene, 0x1022, 1010);
+ if (_fileHash1)
+ loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+ else
+ setVisible(false);
+ }
+}
+
+uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x480B:
+ sendMessage(_parentScene, 0x480B, 0);
+ setVisible(true);
+ sendMessage(_parentScene, 0x1022, 990);
+ loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition);
+ _countdown = 16;
+ playSound(0, _soundFileHash);
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2101::KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4811:
+ GotoState(&KmScene2101::stHitByDoor);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0xFF290E30);
+ break;
+ case 0x483E:
+ teleporterDisappear(0x9A28CA1C);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 KmScene2101::hmHitByDoor(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ int16 speedUpFrameIndex;
+ switch (messageNum) {
+ case 0x1008:
+ speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
+ if (_currFrameIndex < speedUpFrameIndex) {
+ startAnimation(0x35AA8059, speedUpFrameIndex, -1);
+ _y = 438;
+ }
+ messageResult = 0;
+ break;
+ case 0x100D:
+ if (param.asInteger() == 0x1A1A0785) {
+ playSound(0, 0x40F0A342);
+ } else if (param.asInteger() == 0x60428026) {
+ playSound(0, 0x40608A59);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene2101::stHitByDoor() {
+ _busyStatus = 1;
+ _acceptInput = false;
+ startAnimation(0x35AA8059, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2101::hmHitByDoor);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ playSound(0, 0x402E82D4);
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2100_sprites.h b/engines/neverhood/modules/module2100_sprites.h
new file mode 100644
index 0000000000..85a6b9f27d
--- /dev/null
+++ b/engines/neverhood/modules/module2100_sprites.h
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE2100_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2100_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsScene2101Door : public AnimatedSprite {
+public:
+ AsScene2101Door(NeverhoodEngine *vm, bool isOpen);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stCloseDoor();
+ void stCloseDoorDone();
+};
+
+class AsScene2101HitByDoorEffect : public AnimatedSprite {
+public:
+ AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen);
+protected:
+ Sprite *_klaymen;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsCommonFloorButton : public StaticSprite {
+public:
+ SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
+protected:
+ Scene *_parentScene;
+ uint32 _soundFileHash;
+ uint32 _fileHash1, _fileHash2;
+ int16 _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene2101 : public Klaymen {
+public:
+ KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+
+ void stHitByDoor();
+ uint32 hmHitByDoor(int messageNum, const MessageParam &param, Entity *sender);
+
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2100_SPRITES_H */
diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp
index b8da0f64ff..eecddf904c 100644
--- a/engines/neverhood/modules/module2200.cpp
+++ b/engines/neverhood/modules/module2200.cpp
@@ -20,20 +20,21 @@
*
*/
-#include "neverhood/modules/module2200.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/gamemodule.h"
+#include "common/config-manager.h"
+
#include "neverhood/diskplayerscene.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1000_sprites.h"
+#include "neverhood/modules/module1200_sprites.h"
+#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2200_sprites.h"
namespace Neverhood {
Module2200::Module2200(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
- debug("Create Module2200(%d)", which);
- _vm->_soundMan->addMusic(0x11391412, 0x601C908C);
+ _vm->_soundMan->addMusic(0x11391412, 0x601C908C);
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
@@ -47,11 +48,24 @@ Module2200::~Module2200() {
}
void Module2200::createScene(int sceneNum, int which) {
- debug("Module2200::createScene(%d, %d)", sceneNum, which);
+ if (sceneNum == 46 && ConfMan.getBool("skiphallofrecordsscenes")) {
+ // Skip the whole Hall of Records storyboard scenes,
+ // and teleport to the last scene
+ sceneNum = 41;
+ }
+
+ if (sceneNum == 40 && ConfMan.getBool("skiphallofrecordsscenes")) {
+ // Skip the whole Hall of Records storyboard scenes,
+ // and teleport back to the first scene
+ sceneNum = 5;
+ }
+
+ debug(1, "Module2200::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
_vm->gameState().sceneNum = 0;
+ _vm->_soundMan->startMusic(0x601C908C, 0, 2);
_childObject = new Scene2201(_vm, this, which);
break;
case 1:
@@ -441,100 +455,11 @@ void Module2200::updateScene() {
}
#undef HallOfRecordsSceneLink
-
+
void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId) {
_childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId);
}
-// Scene2201
-
-AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- _x = 403;
- _y = 259;
- createSurface(100, 233, 96);
- startAnimation(0x8600866, 0, -1);
- SetUpdateHandler(&AnimatedSprite::update);
-}
-
-AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen)
- : AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) {
-
- _x = 408;
- _y = 290;
- createSurface(900, 63, 266);
- SetUpdateHandler(&AsScene2201Door::update);
- SetMessageHandler(&AsScene2201Door::handleMessage);
- if (_isOpen) {
- startAnimation(0xE2CB0412, -1, -1);
- _countdown = 48;
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else {
- startAnimation(0xE2CB0412, 0, -1);
- _newStickFrameIndex = 0;
- _ssDoorLight->setVisible(false);
- }
-}
-
-void AsScene2201Door::update() {
- if (_countdown != 0 && _isOpen && (--_countdown == 0))
- stCloseDoor();
- AnimatedSprite::update();
-}
-
-uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x11001090) {
- if (_isOpen)
- _ssDoorLight->setVisible(true);
- } else if (param.asInteger() == 0x11283090) {
- if (!_isOpen)
- _ssDoorLight->setVisible(false);
- }
- break;
- case 0x2000:
- if (_isOpen)
- _countdown = 144;
- messageResult = _isOpen ? 1 : 0;
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- _countdown = 144;
- if (!_isOpen)
- stOpenDoor();
- break;
- }
- return messageResult;
-}
-
-void AsScene2201Door::stOpenDoor() {
- _isOpen = true;
- startAnimation(0xE2CB0412, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- playSound(0, calcHash("fxDoorOpen33"));
-}
-
-void AsScene2201Door::stCloseDoor() {
- _isOpen = false;
- startAnimation(0xE2CB0412, -1, -1);
- _playBackwards = true;
- _newStickFrameIndex = 0;
- playSound(0, calcHash("fxDoorClose33"));
-}
-
-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);
-}
-
Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isSoundPlaying(false) {
@@ -544,7 +469,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene2201::handleMessage);
SetUpdateHandler(&Scene2201::update);
-
+
loadDataResource(0x04104242);
loadHitRectList();
setBackground(0x40008208);
@@ -552,9 +477,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));
@@ -563,10 +488,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);
@@ -603,7 +528,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
setMessageList(0x004B8120);
_asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, true);
}
-
+
insertSprite<AsScene2201CeilingFan>();
_vm->_soundMan->addSound(0x04106220, 0x81212040);
@@ -662,214 +587,6 @@ uint32 Scene2201::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-static const NPoint kSsScene2202PuzzleCubePoints[] = {
- {196, 105}, {323, 102}, {445, 106},
- {192, 216}, {319, 220}, {446, 216},
- {188, 320}, {319, 319}, {443, 322}
-};
-
-static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = {
- 0xA500800C, 0x2182910C, 0x2323980C,
- 0x23049084, 0x21008080, 0x2303900C,
- 0x6120980C, 0x2504D808
-};
-
-static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = {
- 0x0AAD8080, 0x0A290291, 0x0A2BA398,
- 0x822B8490, 0x86298080, 0x0A2B8390,
- 0x0A69A098, 0x0E2D84D8
-};
-
-SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol)
- : StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) {
-
- int surfacePriority;
-
- SetUpdateHandler(&SsScene2202PuzzleCube::update);
- SetMessageHandler(&SsScene2202PuzzleCube::handleMessage);
- if (_cubePosition >= 0 && _cubePosition <= 2)
- surfacePriority = 100;
- else if (_cubePosition >= 3 && _cubePosition <= 5)
- surfacePriority = 300;
- else
- surfacePriority = 500;
- loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0,
- kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y);
- loadSound(0, 0x40958621);
- loadSound(1, 0x51108241);
-}
-
-void SsScene2202PuzzleCube::update() {
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED))
- sendMessage(_parentScene, 0x2000, _cubePosition);
- messageResult = 1;
- break;
- case 0x2001:
- _isMoving = true;
- moveCube(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-void SsScene2202PuzzleCube::suMoveCubeX() {
-
- bool done = false;
-
- if (_counterDirection) {
- if (_counter > 2)
- _counter -= 2;
- } else {
- if (_counter < 20)
- _counter += 2;
- }
-
- for (int16 i = 0; i < _counter; i++) {
- _x += _xIncr;
- _errValue += _yDelta;
- if (_errValue >= _xDelta) {
- _errValue -= _xDelta;
- _y += _yIncr;
- }
- if (_x == _newX && _y == _newY) {
- done = true;
- break;
- }
- if (_x == _xFlagPos)
- _counterDirection = true;
- }
-
- if (done)
- stopMoving();
-
- updateBounds();
-
-}
-
-void SsScene2202PuzzleCube::suMoveCubeY() {
-
- bool done = false;
-
- if (_counterDirection) {
- if (_counter > 2)
- _counter -= 2;
- } else {
- if (_counter < 20)
- _counter += 2;
- }
-
- for (int16 i = 0; i < _counter; i++) {
- _y += _yIncr;
- _errValue += _xDelta;
- if (_errValue >= _yDelta) {
- _errValue -= _yDelta;
- _x += _xIncr;
- }
- if (_x == _newX && _y == _newY) {
- done = true;
- break;
- }
- if (_x == _xFlagPos)
- _counterDirection = true;
- }
-
- if (done)
- stopMoving();
-
- updateBounds();
-
-}
-
-void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
-
- loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset);
-
- setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1);
- setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol);
-
- _cubePosition = newCubePosition;
- _errValue = 0;
- _counterDirection = false;
- _counter = 0;
- _newX = kSsScene2202PuzzleCubePoints[newCubePosition].x;
- _newY = kSsScene2202PuzzleCubePoints[newCubePosition].y;
-
- if (_x == _newX && _y == _newY)
- return;
-
- if (_x <= _newX) {
- if (_y <= _newY) {
- _xDelta = _newX - _x;
- _yDelta = _newY - _y;
- _xIncr = 1;
- _yIncr = 1;
- } else {
- _xDelta = _newX - _x;
- _yDelta = _y - _newY;
- _xIncr = 1;
- _yIncr = -1;
- }
- } else {
- if (_y <= _newY) {
- _xDelta = _x - _newX;
- _yDelta = _newY - _y;
- _xIncr = -1;
- _yIncr = 1;
- } else {
- _xDelta = _x - _newX;
- _yDelta = _y - _newY;
- _xIncr = -1;
- _yIncr = -1;
- }
- }
-
- if (_xDelta > _yDelta) {
- SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX);
- if (_xIncr > 0) {
- if (_newX - _x >= 180)
- _xFlagPos = _newX - 90;
- else
- _xFlagPos = _x + _newX / 2;
- } else {
- if (_x - _newX >= 180)
- _xFlagPos = _x + 90;
- else
- _xFlagPos = _x / 2 + _newX;
- }
- playSound(0);
- } else {
- SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY);
- if (_yIncr > 0) {
- if (_newY - _y >= 180)
- _xFlagPos = _newY - 90;
- else
- _xFlagPos = _y + _newY / 2;
- } else {
- if (_y - _newY >= 180)
- _xFlagPos = _y + 90;
- else
- _xFlagPos = _y / 2 + _newY;
- }
- playSound(1);
- }
-
-}
-
-void SsScene2202PuzzleCube::stopMoving() {
- loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset);
- SetSpriteUpdate(NULL);
- _isMoving = false;
- sendMessage(_parentScene, 0x2002, _cubePosition);
-}
-
Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isSolved(false), _leaveScene(false), _isCubeMoving(false),
_ssMovingCube(NULL), _ssDoneMovingCube(NULL) {
@@ -939,7 +656,7 @@ void Scene2202::update() {
_isSolved = true;
}
}
-
+
}
uint32 Scene2202::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -981,7 +698,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 &&
@@ -991,100 +708,6 @@ bool Scene2202::testIsSolved() {
getSubVar(VA_CUBE_POSITIONS, 8) == 7;
}
-static const uint32 kAsCommonKeyFileHashes[] = {
- 0x2450D850, 0x0C9CE8D0, 0x2C58A152
-};
-
-AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y)
- : AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) {
-
- if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) {
- SetMessageHandler(&AsCommonKey::handleMessage);
- } else {
- // If Klaymen already has the key or it's already inserted then don't show it
- setVisible(false);
- SetMessageHandler(NULL);
- }
-}
-
-uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setSubVar(VA_HAS_KEY, _keyIndex, 1);
- setVisible(false);
- SetMessageHandler(NULL);
- }
- return messageResult;
-}
-
-static const uint32 kAsScene2203DoorFileHashes[] = {
- 0x7868AE10, 0x1A488110
-};
-
-AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) {
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2203Door::handleMessage);
- _x = 320;
- _y = 240;
- createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900);
- if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) {
- startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else {
- startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1);
- _newStickFrameIndex = 0;
- }
-}
-
-uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
- sendMessage(_parentScene, 0x2002, 0);
- else
- sendMessage(_parentScene, 0x2001, 0);
- messageResult = 1;
- break;
- case 0x2000:
- _otherDoor = (Sprite*)param.asEntity();
- break;
- case 0x3002:
- if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
- sendMessage(_parentScene, 0x4808, 0);
- stopAnimation();
- break;
- case 0x4808:
- setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex);
- sendMessage(_otherDoor, 0x4809, 0);
- openDoor();
- break;
- case 0x4809:
- closeDoor();
- sendMessage(_parentScene, 0x2003, 0);
- break;
- }
- return messageResult;
-}
-
-void AsScene2203Door::openDoor() {
- playSound(0, 0x341014C4);
- startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1);
-}
-
-void AsScene2203Door::closeDoor() {
- startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
- _playBackwards = true;
- _newStickFrameIndex = 0;
-}
-
Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
@@ -1146,7 +769,7 @@ Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which)
_ssSmallRightDoor->setVisible(false);
_klaymen->setClipRect(_leftDoorClipRect);
}
-
+
}
Scene2203::~Scene2203() {
@@ -1197,30 +820,12 @@ uint32 Scene2203::handleMessage(int messageNum, const MessageParam &param, Entit
return messageResult;
}
-SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm)
- : StaticSprite(vm, 900) {
-
- SetMessageHandler(&SsScene2205DoorFrame::handleMessage);
- createSurface(1100, 45, 206);
- loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
-}
-
-uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
- break;
- }
- return messageResult;
-}
-
Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
SetMessageHandler(&Scene2205::handleMessage);
SetUpdateHandler(&Scene2205::update);
-
+
setHitRects(0x004B0620);
if (getGlobalVar(V_LIGHTS_ON)) {
_isLightOn = true;
@@ -1263,11 +868,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)) {
@@ -1325,142 +930,14 @@ static const int16 kScene2206XPositions[] = {
384, 480, 572
};
-static const uint32 kScene2206MessageIds1[] = {
- 0x004B8998, 0x004B89B8, 0x004B89D8
-};
-
-static const uint32 kScene2206MessageIds2[] = {
- 0x004B89F8, 0x004B8A20, 0x004B8A48
-};
-
-static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = {
- -24, -28, -18, 6, 9, -8
-};
-
-static const int16 kAsScene2206DoorSpikesXDeltasClose[] = {
- -8, 7, 11, 26, 13, 14
-};
-
-AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash)
- : StaticSprite(vm, fileHash, 200) {
-
- if (getGlobalVar(V_SPIKES_RETRACTED))
- _x -= 63;
- SetUpdateHandler(&AsScene2206DoorSpikes::update);
- SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsScene2206DoorSpikes::update() {
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4808:
- _deltaIndex = 0;
- playSound(0, 0x032746E0);
- SetMessageHandler(NULL);
- SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen);
- break;
- case 0x4809:
- _deltaIndex = 0;
- playSound(0, 0x002642C0);
- SetMessageHandler(NULL);
- SetSpriteUpdate(&AsScene2206DoorSpikes::suClose);
- break;
- }
- return messageResult;
-}
-
-void AsScene2206DoorSpikes::suOpen() {
- if (_deltaIndex < 6) {
- _x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex];
- _deltaIndex++;
- } else {
- SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
- SetSpriteUpdate(NULL);
- }
-}
-
-void AsScene2206DoorSpikes::suClose() {
- if (_deltaIndex < 6) {
- _x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex];
- _deltaIndex++;
- } else {
- SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
- SetSpriteUpdate(NULL);
- }
-}
-
-AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash)
- : StaticSprite(vm, fileHash, 50) {
-
- SetUpdateHandler(&AsScene2206Platform::update);
- SetMessageHandler(&AsScene2206Platform::handleMessage);
- SetSpriteUpdate(NULL);
-}
-
-void AsScene2206Platform::update() {
- handleSpriteUpdate();
- updatePosition();
-}
-
-uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4803:
- _yDelta = 0;
- SetMessageHandler(NULL);
- SetSpriteUpdate(&AsScene2206Platform::suMoveDown);
- break;
- }
- return messageResult;
-}
-
-void AsScene2206Platform::suMoveDown() {
- _yDelta++;
- _y += _yDelta;
-}
-
-SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash)
- : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) {
-
- if (getGlobalVar(V_HAS_TEST_TUBE)) {
- setVisible(false);
- SetMessageHandler(NULL);
- } else
- SetMessageHandler(&SsScene2206TestTube::handleMessage);
- _collisionBoundsOffset = _drawOffset;
- updateBounds();
-}
-
-uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x4806:
- setGlobalVar(V_HAS_TEST_TUBE, 1);
- setVisible(false);
- SetMessageHandler(NULL);
- break;
- }
- return messageResult;
-}
-
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 +972,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);
@@ -1586,7 +1063,7 @@ void Scene2206::klaymenInFrontSpikes() {
}
void Scene2206::klaymenBehindSpikes() {
- if (!getGlobalVar(V_LIGHTS_ON)) {
+ if (getGlobalVar(V_LIGHTS_ON)) {
_palette->addBasePalette(0xB103B604, 0, 65, 0);
_palette->startFadeToPalette(12);
}
@@ -1597,6 +1074,14 @@ void Scene2206::klaymenBehindSpikes() {
_klaymen->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2());
}
+static const uint32 kScene2206MessageIds1[] = {
+ 0x004B8998, 0x004B89B8, 0x004B89D8
+};
+
+static const uint32 kScene2206MessageIds2[] = {
+ 0x004B89F8, 0x004B8A20, 0x004B8A48
+};
+
void Scene2206::readClickedColumn() {
setGlobalVar(V_CLICKED_COLUMN_INDEX, (_mouseClickPos.x - 354) / 96);
if (getGlobalVar(V_CLICKED_COLUMN_INDEX) > 2)
@@ -1617,317 +1102,6 @@ static const uint32 kScene2207FileHashes[] = {
0x3BB1E12E, 0x23B1E12E, 0x13B1E12E
};
-AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) {
-
- NPoint pt;
-
- _dataResource.load(0x00524846);
- _pointArray = _dataResource.getPointArray(0x005B02B7);
- pt = _dataResource.getPoint(0x403A82B1);
- _x = pt.x;
- _y = pt.y;
- createSurface(1100, 129, 103);
- startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AsScene2207Elevator::update);
- SetMessageHandler(&AsScene2207Elevator::handleMessage);
- SetSpriteUpdate(&AsScene2207Elevator::suSetPosition);
-}
-
-AsScene2207Elevator::~AsScene2207Elevator() {
- _vm->_soundMan->deleteSoundGroup(0x02700413);
-}
-
-void AsScene2207Elevator::update() {
-
- if (_destPointIndex + _destPointIndexDelta > _pointIndex) {
- _pointIndex++;
- startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
- _newStickFrameIndex = _pointIndex;
- if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
- if (_destPointIndexDelta != 0)
- _destPointIndexDelta = 0;
- else {
- _vm->_soundMan->deleteSound(0xD3B02847);
- playSound(0, 0x53B8284A);
- }
- }
- }
-
- if (_destPointIndex + _destPointIndexDelta < _pointIndex) {
- _pointIndex--;
- if (_pointIndex == 0)
- sendMessage(_parentScene, 0x2003, 0);
- startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
- _newStickFrameIndex = _pointIndex;
- if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
- if (_destPointIndexDelta != 0)
- _destPointIndexDelta = 0;
- else {
- _vm->_soundMan->deleteSound(0xD3B02847);
- playSound(0, 0x53B8284A);
- }
- }
- }
-
- if (_pointIndex > 20 && _surface->getPriority() != 900)
- 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() {
- _x = (*_pointArray)[_pointIndex].x;
- _y = (*_pointArray)[_pointIndex].y - 60;
- updateBounds();
-}
-
-uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- moveToY(param.asInteger());
- break;
- }
- return messageResult;
-}
-
-void AsScene2207Elevator::moveToY(int16 y) {
- int16 minDistance = 480;
-
- 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)
- _destPointIndexDelta = 0;
- else if (_destPointIndex < _pointIndex)
- _destPointIndexDelta = -2;
- else
- _destPointIndexDelta = 2;
- _vm->_soundMan->addSound(0x02700413, 0xD3B02847);
- _vm->_soundMan->playSoundLooping(0xD3B02847);
- }
-
- _isMoving = true;
-
-}
-
-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);
- setDoDeltaX(doDeltaX);
- startAnimation(0x80880090, 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2207Lever::handleMessage);
-}
-
-uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x4826, 0);
- messageResult = 1;
- break;
- case 0x3002:
- gotoNextState();
- stopAnimation();
- break;
- case 0x4807:
- stLeverUp();
- break;
- case 0x480F:
- stLeverDown();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-void AsScene2207Lever::stLeverDown() {
- startAnimation(0x80880090, 1, -1);
- playSound(0, 0x40581882);
- FinalizeState(&AsScene2207Lever::stLeverDownEvent);
-}
-
-void AsScene2207Lever::stLeverDownEvent() {
- sendMessage(_parentScene, 0x480F, 0);
-}
-
-void AsScene2207Lever::stLeverUp() {
- startAnimation(0x80880090, 6, -1);
- _playBackwards = true;
- playSound(0, 0x40581882);
- FinalizeState(&AsScene2207Lever::stLeverUpEvent);
-}
-
-void AsScene2207Lever::stLeverUpEvent() {
- sendMessage(_parentScene, 0x4807, 0);
-}
-
-AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1200), _idle(true) {
-
- _x = 309;
- _y = 320;
- createSurface1(0xCCFD6090, 100);
- startAnimation(0xCCFD6090, 0, -1);
- _newStickFrameIndex = 0;
- loadSound(1, 0x40330872);
- loadSound(2, 0x72A2914A);
- loadSound(3, 0xD4226080);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage);
-}
-
-AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() {
- _vm->_soundMan->deleteSoundGroup(0x80D00820);
-}
-
-uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (!_idle) {
- if (param.asInteger() == 0x3423093) {
- _vm->_soundMan->addSound(0x80D00820, 0x12121943);
- _vm->_soundMan->playSoundLooping(0x12121943);
- } else if (param.asInteger() == 0x834AB011) {
- stopSound(0);
- stopSound(1);
- stopSound(2);
- stopSound(3);
- _vm->_soundMan->deleteSound(0x12121943);
- } else if (param.asInteger() == 0x3A980501)
- playSound(1);
- else if (param.asInteger() == 0x2A2AD498)
- playSound(2);
- else if (param.asInteger() == 0xC4980008)
- playSound(3);
- else if (param.asInteger() == 0x06B84228)
- playSound(0, 0xE0702146);
- }
- break;
- case 0x2006:
- stStartAnimation();
- break;
- case 0x2007:
- stStopAnimation();
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2207WallRobotAnimation::stStartAnimation() {
- if (!_idle) {
- NextState(NULL);
- } else {
- startAnimation(0xCCFD6090, 0, -1);
- _idle = false;
- setVisible(true);
- }
-}
-
-void AsScene2207WallRobotAnimation::stStopAnimation() {
- NextState(&AsScene2207WallRobotAnimation::cbStopAnimation);
-}
-
-void AsScene2207WallRobotAnimation::cbStopAnimation() {
- stopAnimation();
- stopSound(0);
- stopSound(1);
- stopSound(2);
- stopSound(3);
- _vm->_soundMan->deleteSound(0x12121943);
- _idle = true;
- setVisible(false);
-}
-
-AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200), _idle(true) {
-
- _x = 309;
- _y = 320;
- createSurface1(0x8CAA0099, 100);
- startAnimation(0x8CAA0099, 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage);
-}
-
-uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2006:
- stStartAnimation();
- break;
- case 0x2007:
- stStopAnimation();
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2207WallCannonAnimation::stStartAnimation() {
- if (!_idle) {
- NextState(NULL);
- } else {
- setVisible(true);
- startAnimation(0x8CAA0099, 0, -1);
- _idle = false;
- }
-}
-
-void AsScene2207WallCannonAnimation::stStopAnimation() {
- NextState(&AsScene2207WallCannonAnimation::cbStopAnimation);
-}
-
-void AsScene2207WallCannonAnimation::cbStopAnimation() {
- stopAnimation();
- setVisible(false);
- _idle = true;
-}
-
-SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index)
- : StaticSprite(vm, fileHash, 100) {
-
- _x = 330;
- _y = 246 + index * 50;
- updatePosition();
-}
-
Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule), _klaymenAtElevator(true), _elevatorSurfacePriority(0) {
@@ -1943,7 +1117,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 +1126,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 +1280,7 @@ static const uint32 kScene2208FileHashes1[] = {
0x041023CB, 0x041020CB, 0x041026CB, 0x04102ACB,
0x041032CB, 0x041002CB
};
-
+
static const uint32 kScene2208FileHashes2[] = {
0x091206C9, 0x091406C9, 0x091806C9, 0x090006C9,
0x093006C9, 0x095006C9
@@ -2122,13 +1296,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);
@@ -2141,20 +1315,20 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which)
_fontSurface = FontSurface::createFontSurface(_vm, 0x0800090C);
- _backgroundSurface = new BaseSurface(_vm, 0, 640, 480);
+ _backgroundSurface = new BaseSurface(_vm, 0, 640, 480, "background");
spriteResource.load(0x08100289, true);
_backgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0);
- _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192);
+ _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192, "top background");
spriteResource.load(!getGlobalVar(V_COLUMN_BACK_NAME)
? kScene2208FileHashes1[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6]
: getGlobalVar(V_COLUMN_BACK_NAME), true);
_topBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0);
- _bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192);
+ _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 +1339,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 +1359,7 @@ Scene2208::~Scene2208() {
void Scene2208::update() {
int16 mouseY = _vm->getMouseY();
-
+
if (mouseY < 48) {
if (_currRowIndex > 0)
_newRowIndex = _currRowIndex - 1;
@@ -2235,7 +1409,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 +1454,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 +1471,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 +1554,7 @@ void Scene2242::readClickedColumn() {
}
static const int16 kHallOfRecordsKlaymenXPos[] = {
- 68, 157, 246, 335,
+ 68, 157, 246, 335,
424, 513, 602
};
@@ -2396,7 +1570,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 +1661,7 @@ static const uint32 kScene2247MessageListIds1[] = {
Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene2247::handleMessage);
SetUpdateHandler(&Scene::update);
@@ -2524,7 +1698,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..6b414304ae 100644
--- a/engines/neverhood/modules/module2200.h
+++ b/engines/neverhood/modules/module2200.h
@@ -31,8 +31,6 @@
namespace Neverhood {
-// Module2200
-
class Module2200 : public Module {
public:
Module2200(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -44,43 +42,6 @@ protected:
void createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId);
};
-// Scene2201
-
-static const NPoint kSsScene2201PuzzleCubePoints[] = {
- {305, 305}, {321, 305}, {336, 305}, {305, 319},
- {321, 319}, {336, 319}, {305, 332}, {321, 332},
- {336, 333}
-};
-
-static const uint32 kSsScene2201PuzzleCubeFileHashes[] = {
- 0x88134A44, 0xAA124340, 0xB8124602, 0xA902464C,
- 0x890A4244, 0xA8124642, 0xB812C204, 0x381A4A4C
-};
-
-class AsScene2201CeilingFan : public AnimatedSprite {
-public:
- AsScene2201CeilingFan(NeverhoodEngine *vm);
-};
-
-class AsScene2201Door : public AnimatedSprite {
-public:
- AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen);
-protected:
- Klaymen *_klaymen;
- Sprite *_ssDoorLight;
- bool _isOpen;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stOpenDoor();
- void stCloseDoor();
-};
-
-class SsScene2201PuzzleCube : public StaticSprite {
-public:
- SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex);
-};
-
class Scene2201 : public Scene {
public:
Scene2201(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -96,30 +57,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class SsScene2202PuzzleCube : public StaticSprite {
-public:
- SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol);
-protected:
- Scene *_parentScene;
- int16 _cubeSymbol;
- int16 _cubePosition;
- int16 _newX, _newY;
- int16 _xDelta, _yDelta;
- int16 _xIncr;
- int16 _yIncr;
- int16 _errValue;
- int16 _counter;
- int16 _xFlagPos;
- bool _counterDirection;
- bool _isMoving;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suMoveCubeX();
- void suMoveCubeY();
- void moveCube(int16 newCubePosition);
- void stopMoving();
-};
-
class Scene2202 : public Scene {
public:
Scene2202(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -135,28 +72,7 @@ protected:
void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
int16 getFreeCubePosition(int16 index);
- bool testIsSolved();
-};
-
-class AsCommonKey : public AnimatedSprite {
-public:
- AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y);
-protected:
- Scene *_parentScene;
- int _keyIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2203Door : public AnimatedSprite {
-public:
- AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex);
-protected:
- Scene *_parentScene;
- Sprite *_otherDoor;
- uint _doorIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void openDoor();
- void closeDoor();
+ bool testIsSolved();
};
class Scene2203 : public Scene {
@@ -175,12 +91,7 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class SsScene2205DoorFrame : public StaticSprite {
-public:
- SsScene2205DoorFrame(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class SsCommonPressButton;
class Scene2205 : public Scene {
public:
@@ -194,35 +105,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene2206DoorSpikes : public StaticSprite {
-public:
- AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash);
-protected:
- int _deltaIndex;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suOpen();
- void suClose();
-};
-
-class AsScene2206Platform : public StaticSprite {
-public:
- AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash);
-protected:
- int16 _yDelta;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suMoveDown();
-};
-
-class SsScene2206TestTube : public StaticSprite {
-public:
- SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2206 : public Scene {
public:
Scene2206(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -241,62 +123,6 @@ protected:
void readClickedColumn();
};
-class AsScene2207Elevator : public AnimatedSprite {
-public:
- AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene);
- ~AsScene2207Elevator();
-protected:
- Scene *_parentScene;
- NPointArray *_pointArray;
- int16 _pointIndex;
- int16 _destPointIndex, _destPointIndexDelta;
- bool _isMoving;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suSetPosition();
- void moveToY(int16 y);
-};
-
-class AsScene2207Lever : public AnimatedSprite {
-public:
- AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stLeverDown();
- void stLeverDownEvent();
- void stLeverUp();
- void stLeverUpEvent();
-};
-
-class AsScene2207WallRobotAnimation : public AnimatedSprite {
-public:
- AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene);
- ~AsScene2207WallRobotAnimation();
-protected:
- bool _idle;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stStartAnimation();
- void stStopAnimation();
- void cbStopAnimation();
-};
-
-class AsScene2207WallCannonAnimation : public AnimatedSprite {
-public:
- AsScene2207WallCannonAnimation(NeverhoodEngine *vm);
-protected:
- bool _idle;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stStartAnimation();
- void stStopAnimation();
- void cbStopAnimation();
-};
-
-class SsScene2207Symbol : public StaticSprite {
-public:
- SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index);
-};
-
class Scene2207 : public Scene {
public:
Scene2207(NeverhoodEngine *vm, Module *parentModule);
diff --git a/engines/neverhood/modules/module2200_sprites.cpp b/engines/neverhood/modules/module2200_sprites.cpp
new file mode 100644
index 0000000000..30f0404cf1
--- /dev/null
+++ b/engines/neverhood/modules/module2200_sprites.cpp
@@ -0,0 +1,1429 @@
+/* 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 "neverhood/modules/module2200_sprites.h"
+
+namespace Neverhood {
+
+AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ _x = 403;
+ _y = 259;
+ createSurface(100, 233, 96);
+ startAnimation(0x8600866, 0, -1);
+ SetUpdateHandler(&AnimatedSprite::update);
+}
+
+AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen)
+ : AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) {
+
+ _x = 408;
+ _y = 290;
+ createSurface(900, 63, 266);
+ SetUpdateHandler(&AsScene2201Door::update);
+ SetMessageHandler(&AsScene2201Door::handleMessage);
+ if (_isOpen) {
+ startAnimation(0xE2CB0412, -1, -1);
+ _countdown = 48;
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else {
+ startAnimation(0xE2CB0412, 0, -1);
+ _newStickFrameIndex = 0;
+ _ssDoorLight->setVisible(false);
+ }
+}
+
+void AsScene2201Door::update() {
+ if (_countdown != 0 && _isOpen && (--_countdown == 0))
+ stCloseDoor();
+ AnimatedSprite::update();
+}
+
+uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x11001090) {
+ if (_isOpen)
+ _ssDoorLight->setVisible(true);
+ } else if (param.asInteger() == 0x11283090) {
+ if (!_isOpen)
+ _ssDoorLight->setVisible(false);
+ }
+ break;
+ case 0x2000:
+ if (_isOpen)
+ _countdown = 144;
+ messageResult = _isOpen ? 1 : 0;
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ _countdown = 144;
+ if (!_isOpen)
+ stOpenDoor();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2201Door::stOpenDoor() {
+ _isOpen = true;
+ startAnimation(0xE2CB0412, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ playSound(0, calcHash("fxDoorOpen33"));
+}
+
+void AsScene2201Door::stCloseDoor() {
+ _isOpen = false;
+ startAnimation(0xE2CB0412, -1, -1);
+ _playBackwards = true;
+ _newStickFrameIndex = 0;
+ playSound(0, calcHash("fxDoorClose33"));
+}
+
+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);
+}
+
+static const NPoint kSsScene2202PuzzleCubePoints[] = {
+ {196, 105}, {323, 102}, {445, 106},
+ {192, 216}, {319, 220}, {446, 216},
+ {188, 320}, {319, 319}, {443, 322}
+};
+
+static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = {
+ 0xA500800C, 0x2182910C, 0x2323980C,
+ 0x23049084, 0x21008080, 0x2303900C,
+ 0x6120980C, 0x2504D808
+};
+
+static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = {
+ 0x0AAD8080, 0x0A290291, 0x0A2BA398,
+ 0x822B8490, 0x86298080, 0x0A2B8390,
+ 0x0A69A098, 0x0E2D84D8
+};
+
+SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol)
+ : StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) {
+
+ int surfacePriority;
+
+ SetUpdateHandler(&SsScene2202PuzzleCube::update);
+ SetMessageHandler(&SsScene2202PuzzleCube::handleMessage);
+ if (_cubePosition >= 0 && _cubePosition <= 2)
+ surfacePriority = 100;
+ else if (_cubePosition >= 3 && _cubePosition <= 5)
+ surfacePriority = 300;
+ else
+ surfacePriority = 500;
+ debug(1, "TODO: Unused SurfacePriority: %d", surfacePriority);
+ loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0,
+ kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y);
+ loadSound(0, 0x40958621);
+ loadSound(1, 0x51108241);
+}
+
+void SsScene2202PuzzleCube::update() {
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED))
+ sendMessage(_parentScene, 0x2000, _cubePosition);
+ messageResult = 1;
+ break;
+ case 0x2001:
+ _isMoving = true;
+ moveCube(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+void SsScene2202PuzzleCube::suMoveCubeX() {
+
+ bool done = false;
+
+ if (_counterDirection) {
+ if (_counter > 2)
+ _counter -= 2;
+ } else {
+ if (_counter < 20)
+ _counter += 2;
+ }
+
+ for (int16 i = 0; i < _counter; i++) {
+ _x += _xIncr;
+ _errValue += _yDelta;
+ if (_errValue >= _xDelta) {
+ _errValue -= _xDelta;
+ _y += _yIncr;
+ }
+ if (_x == _newX && _y == _newY) {
+ done = true;
+ break;
+ }
+ if (_x == _xFlagPos)
+ _counterDirection = true;
+ }
+
+ if (done)
+ stopMoving();
+
+ updateBounds();
+
+}
+
+void SsScene2202PuzzleCube::suMoveCubeY() {
+
+ bool done = false;
+
+ if (_counterDirection) {
+ if (_counter > 2)
+ _counter -= 2;
+ } else {
+ if (_counter < 20)
+ _counter += 2;
+ }
+
+ for (int16 i = 0; i < _counter; i++) {
+ _y += _yIncr;
+ _errValue += _xDelta;
+ if (_errValue >= _yDelta) {
+ _errValue -= _yDelta;
+ _x += _xIncr;
+ }
+ if (_x == _newX && _y == _newY) {
+ done = true;
+ break;
+ }
+ if (_x == _xFlagPos)
+ _counterDirection = true;
+ }
+
+ if (done)
+ stopMoving();
+
+ updateBounds();
+
+}
+
+void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
+
+ loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset);
+
+ setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1);
+ setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol);
+
+ _cubePosition = newCubePosition;
+ _errValue = 0;
+ _counterDirection = false;
+ _counter = 0;
+ _newX = kSsScene2202PuzzleCubePoints[newCubePosition].x;
+ _newY = kSsScene2202PuzzleCubePoints[newCubePosition].y;
+
+ if (_x == _newX && _y == _newY)
+ return;
+
+ if (_x <= _newX) {
+ if (_y <= _newY) {
+ _xDelta = _newX - _x;
+ _yDelta = _newY - _y;
+ _xIncr = 1;
+ _yIncr = 1;
+ } else {
+ _xDelta = _newX - _x;
+ _yDelta = _y - _newY;
+ _xIncr = 1;
+ _yIncr = -1;
+ }
+ } else {
+ if (_y <= _newY) {
+ _xDelta = _x - _newX;
+ _yDelta = _newY - _y;
+ _xIncr = -1;
+ _yIncr = 1;
+ } else {
+ _xDelta = _x - _newX;
+ _yDelta = _y - _newY;
+ _xIncr = -1;
+ _yIncr = -1;
+ }
+ }
+
+ if (_xDelta > _yDelta) {
+ SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX);
+ if (_xIncr > 0) {
+ if (_newX - _x >= 180)
+ _xFlagPos = _newX - 90;
+ else
+ _xFlagPos = _x + _newX / 2;
+ } else {
+ if (_x - _newX >= 180)
+ _xFlagPos = _x + 90;
+ else
+ _xFlagPos = _x / 2 + _newX;
+ }
+ playSound(0);
+ } else {
+ SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY);
+ if (_yIncr > 0) {
+ if (_newY - _y >= 180)
+ _xFlagPos = _newY - 90;
+ else
+ _xFlagPos = _y + _newY / 2;
+ } else {
+ if (_y - _newY >= 180)
+ _xFlagPos = _y + 90;
+ else
+ _xFlagPos = _y / 2 + _newY;
+ }
+ playSound(1);
+ }
+
+}
+
+void SsScene2202PuzzleCube::stopMoving() {
+ loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset);
+ SetSpriteUpdate(NULL);
+ _isMoving = false;
+ sendMessage(_parentScene, 0x2002, _cubePosition);
+}
+
+static const uint32 kAsCommonKeyFileHashes[] = {
+ 0x2450D850, 0x0C9CE8D0, 0x2C58A152
+};
+
+AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y)
+ : AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) {
+
+ if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) {
+ SetMessageHandler(&AsCommonKey::handleMessage);
+ } else {
+ // If Klaymen already has the key or it's already inserted then don't show it
+ setVisible(false);
+ SetMessageHandler(NULL);
+ }
+}
+
+uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setSubVar(VA_HAS_KEY, _keyIndex, 1);
+ setVisible(false);
+ SetMessageHandler(NULL);
+ }
+ return messageResult;
+}
+
+static const uint32 kAsScene2203DoorFileHashes[] = {
+ 0x7868AE10, 0x1A488110
+};
+
+AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) {
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2203Door::handleMessage);
+ _x = 320;
+ _y = 240;
+ createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900);
+ if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) {
+ startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else {
+ startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1);
+ _newStickFrameIndex = 0;
+ }
+}
+
+uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
+ sendMessage(_parentScene, 0x2002, 0);
+ else
+ sendMessage(_parentScene, 0x2001, 0);
+ messageResult = 1;
+ break;
+ case 0x2000:
+ _otherDoor = (Sprite*)param.asEntity();
+ break;
+ case 0x3002:
+ if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
+ sendMessage(_parentScene, 0x4808, 0);
+ stopAnimation();
+ break;
+ case 0x4808:
+ setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex);
+ sendMessage(_otherDoor, 0x4809, 0);
+ openDoor();
+ break;
+ case 0x4809:
+ closeDoor();
+ sendMessage(_parentScene, 0x2003, 0);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2203Door::openDoor() {
+ playSound(0, 0x341014C4);
+ startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1);
+}
+
+void AsScene2203Door::closeDoor() {
+ startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
+ _playBackwards = true;
+ _newStickFrameIndex = 0;
+}
+
+SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm)
+ : StaticSprite(vm, 900) {
+
+ SetMessageHandler(&SsScene2205DoorFrame::handleMessage);
+ createSurface(1100, 45, 206);
+ loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
+}
+
+uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
+ break;
+ }
+ return messageResult;
+}
+
+static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = {
+ -24, -28, -18, 6, 9, -8
+};
+
+static const int16 kAsScene2206DoorSpikesXDeltasClose[] = {
+ -8, 7, 11, 26, 13, 14
+};
+
+AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash)
+ : StaticSprite(vm, fileHash, 200) {
+
+ if (getGlobalVar(V_SPIKES_RETRACTED))
+ _x -= 63;
+ SetUpdateHandler(&AsScene2206DoorSpikes::update);
+ SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsScene2206DoorSpikes::update() {
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4808:
+ _deltaIndex = 0;
+ playSound(0, 0x032746E0);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen);
+ break;
+ case 0x4809:
+ _deltaIndex = 0;
+ playSound(0, 0x002642C0);
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(&AsScene2206DoorSpikes::suClose);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2206DoorSpikes::suOpen() {
+ if (_deltaIndex < 6) {
+ _x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex];
+ _deltaIndex++;
+ } else {
+ SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void AsScene2206DoorSpikes::suClose() {
+ if (_deltaIndex < 6) {
+ _x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex];
+ _deltaIndex++;
+ } else {
+ SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash)
+ : StaticSprite(vm, fileHash, 50) {
+
+ SetUpdateHandler(&AsScene2206Platform::update);
+ SetMessageHandler(&AsScene2206Platform::handleMessage);
+ SetSpriteUpdate(NULL);
+}
+
+void AsScene2206Platform::update() {
+ handleSpriteUpdate();
+ updatePosition();
+}
+
+uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4803:
+ _yDelta = 0;
+ SetMessageHandler(NULL);
+ SetSpriteUpdate(&AsScene2206Platform::suMoveDown);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2206Platform::suMoveDown() {
+ _yDelta++;
+ _y += _yDelta;
+}
+
+SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash)
+ : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) {
+
+ if (getGlobalVar(V_HAS_TEST_TUBE)) {
+ setVisible(false);
+ SetMessageHandler(NULL);
+ } else
+ SetMessageHandler(&SsScene2206TestTube::handleMessage);
+ _collisionBoundsOffset = _drawOffset;
+ updateBounds();
+}
+
+uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x4806:
+ setGlobalVar(V_HAS_TEST_TUBE, 1);
+ setVisible(false);
+ SetMessageHandler(NULL);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) {
+
+ NPoint pt;
+
+ _dataResource.load(0x00524846);
+ _pointArray = _dataResource.getPointArray(0x005B02B7);
+ pt = _dataResource.getPoint(0x403A82B1);
+ _x = pt.x;
+ _y = pt.y;
+ createSurface(1100, 129, 103);
+ startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AsScene2207Elevator::update);
+ SetMessageHandler(&AsScene2207Elevator::handleMessage);
+ SetSpriteUpdate(&AsScene2207Elevator::suSetPosition);
+}
+
+AsScene2207Elevator::~AsScene2207Elevator() {
+ _vm->_soundMan->deleteSoundGroup(0x02700413);
+}
+
+void AsScene2207Elevator::update() {
+
+ if (_destPointIndex + _destPointIndexDelta > _pointIndex) {
+ _pointIndex++;
+ startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
+ _newStickFrameIndex = _pointIndex;
+ if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
+ if (_destPointIndexDelta != 0)
+ _destPointIndexDelta = 0;
+ else {
+ _vm->_soundMan->deleteSound(0xD3B02847);
+ playSound(0, 0x53B8284A);
+ }
+ }
+ }
+
+ if (_destPointIndex + _destPointIndexDelta < _pointIndex) {
+ _pointIndex--;
+ if (_pointIndex == 0)
+ sendMessage(_parentScene, 0x2003, 0);
+ startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
+ _newStickFrameIndex = _pointIndex;
+ if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
+ if (_destPointIndexDelta != 0)
+ _destPointIndexDelta = 0;
+ else {
+ _vm->_soundMan->deleteSound(0xD3B02847);
+ playSound(0, 0x53B8284A);
+ }
+ }
+ }
+
+ if (_pointIndex > 20 && _surface->getPriority() != 900)
+ 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() {
+ _x = (*_pointArray)[_pointIndex].x;
+ _y = (*_pointArray)[_pointIndex].y - 60;
+ updateBounds();
+}
+
+uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ moveToY(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2207Elevator::moveToY(int16 y) {
+ int16 minDistance = 480;
+
+ 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)
+ _destPointIndexDelta = 0;
+ else if (_destPointIndex < _pointIndex)
+ _destPointIndexDelta = -2;
+ else
+ _destPointIndexDelta = 2;
+ _vm->_soundMan->addSound(0x02700413, 0xD3B02847);
+ _vm->_soundMan->playSoundLooping(0xD3B02847);
+ }
+
+ _isMoving = true;
+
+}
+
+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);
+ setDoDeltaX(doDeltaX);
+ startAnimation(0x80880090, 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2207Lever::handleMessage);
+}
+
+uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x4826, 0);
+ messageResult = 1;
+ break;
+ case 0x3002:
+ gotoNextState();
+ stopAnimation();
+ break;
+ case 0x4807:
+ stLeverUp();
+ break;
+ case 0x480F:
+ stLeverDown();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2207Lever::stLeverDown() {
+ startAnimation(0x80880090, 1, -1);
+ playSound(0, 0x40581882);
+ FinalizeState(&AsScene2207Lever::stLeverDownEvent);
+}
+
+void AsScene2207Lever::stLeverDownEvent() {
+ sendMessage(_parentScene, 0x480F, 0);
+}
+
+void AsScene2207Lever::stLeverUp() {
+ startAnimation(0x80880090, 6, -1);
+ _playBackwards = true;
+ playSound(0, 0x40581882);
+ FinalizeState(&AsScene2207Lever::stLeverUpEvent);
+}
+
+void AsScene2207Lever::stLeverUpEvent() {
+ sendMessage(_parentScene, 0x4807, 0);
+}
+
+AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1200), _idle(true) {
+
+ _x = 309;
+ _y = 320;
+ createSurface1(0xCCFD6090, 100);
+ startAnimation(0xCCFD6090, 0, -1);
+ _newStickFrameIndex = 0;
+ loadSound(1, 0x40330872);
+ loadSound(2, 0x72A2914A);
+ loadSound(3, 0xD4226080);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage);
+}
+
+AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() {
+ _vm->_soundMan->deleteSoundGroup(0x80D00820);
+}
+
+uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (!_idle) {
+ if (param.asInteger() == 0x3423093) {
+ _vm->_soundMan->addSound(0x80D00820, 0x12121943);
+ _vm->_soundMan->playSoundLooping(0x12121943);
+ } else if (param.asInteger() == 0x834AB011) {
+ stopSound(0);
+ stopSound(1);
+ stopSound(2);
+ stopSound(3);
+ _vm->_soundMan->deleteSound(0x12121943);
+ } else if (param.asInteger() == 0x3A980501)
+ playSound(1);
+ else if (param.asInteger() == 0x2A2AD498)
+ playSound(2);
+ else if (param.asInteger() == 0xC4980008)
+ playSound(3);
+ else if (param.asInteger() == 0x06B84228)
+ playSound(0, 0xE0702146);
+ }
+ break;
+ case 0x2006:
+ stStartAnimation();
+ break;
+ case 0x2007:
+ stStopAnimation();
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2207WallRobotAnimation::stStartAnimation() {
+ if (!_idle) {
+ NextState(NULL);
+ } else {
+ startAnimation(0xCCFD6090, 0, -1);
+ _idle = false;
+ setVisible(true);
+ }
+}
+
+void AsScene2207WallRobotAnimation::stStopAnimation() {
+ NextState(&AsScene2207WallRobotAnimation::cbStopAnimation);
+}
+
+void AsScene2207WallRobotAnimation::cbStopAnimation() {
+ stopAnimation();
+ stopSound(0);
+ stopSound(1);
+ stopSound(2);
+ stopSound(3);
+ _vm->_soundMan->deleteSound(0x12121943);
+ _idle = true;
+ setVisible(false);
+}
+
+AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200), _idle(true) {
+
+ _x = 309;
+ _y = 320;
+ createSurface1(0x8CAA0099, 100);
+ startAnimation(0x8CAA0099, 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage);
+}
+
+uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2006:
+ stStartAnimation();
+ break;
+ case 0x2007:
+ stStopAnimation();
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2207WallCannonAnimation::stStartAnimation() {
+ if (!_idle) {
+ NextState(NULL);
+ } else {
+ setVisible(true);
+ startAnimation(0x8CAA0099, 0, -1);
+ _idle = false;
+ }
+}
+
+void AsScene2207WallCannonAnimation::stStopAnimation() {
+ NextState(&AsScene2207WallCannonAnimation::cbStopAnimation);
+}
+
+void AsScene2207WallCannonAnimation::cbStopAnimation() {
+ stopAnimation();
+ setVisible(false);
+ _idle = true;
+}
+
+SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index)
+ : StaticSprite(vm, fileHash, 100) {
+
+ _x = 330;
+ _y = 246 + index * 50;
+ updatePosition();
+}
+
+KmScene2201::KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount)
+ : Klaymen(vm, parentScene, x, y) {
+
+ _surface->setClipRects(clipRects, clipRectsCount);
+ _dataResource.load(0x04104242);
+}
+
+uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x4819:
+ GotoState(&KmScene2203::stClayDoorOpen);
+ break;
+ case 0x481A:
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+void KmScene2203::stClayDoorOpen() {
+ if (!stStartAction(AnimationCallback(&KmScene2203::stClayDoorOpen))) {
+ _busyStatus = 2;
+ _acceptInput = false;
+ startAnimation(0x5CCCB330, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2203::hmClayDoorOpen);
+ SetSpriteUpdate(&Klaymen::suUpdateDestX);
+ }
+}
+
+uint32 KmScene2203::hmClayDoorOpen(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x040D4186) {
+ sendMessage(_attachedSprite, 0x4808, 0);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2205::KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+void KmScene2205::xUpdate() {
+ setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
+}
+
+uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stStartWalkingResume);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+KmScene2206::KmScene2206(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ _walkResumeFrameIncr = 1;
+ _vm->_soundMan->addSound(0x80101800, 0xD3B02847);
+}
+
+KmScene2206::~KmScene2206() {
+ _vm->_soundMan->deleteSoundGroup(0x80101800);
+}
+
+void KmScene2206::xUpdate() {
+ setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
+}
+
+uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4803:
+ GotoState(&KmScene2206::stRidePlatformDown);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stStartWalkingResume);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+void KmScene2206::suRidePlatformDown() {
+ _platformDeltaY++;
+ _y += _platformDeltaY;
+ if (_y > 600)
+ sendMessage(this, 0x1019, 0);
+}
+
+void KmScene2206::stRidePlatformDown() {
+ if (!stStartActionFromIdle(AnimationCallback(&KmScene2206::stRidePlatformDown))) {
+ _busyStatus = 1;
+ sendMessage(_parentScene, 0x4803, 0);
+ _acceptInput = false;
+ _platformDeltaY = 0;
+ startAnimation(0x5420E254, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&Klaymen::hmLowLevel);
+ SetSpriteUpdate(&KmScene2206::suRidePlatformDown);
+ _vm->_soundMan->playSoundLooping(0xD3B02847);
+ }
+}
+
+KmScene2207::KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x2001:
+ GotoState(&Klaymen::stRidePlatform);
+ break;
+ case 0x2005:
+ suRidePlatform();
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stInteractLever);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x4827:
+ GotoState(&Klaymen::stReleaseLever);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+KmScene2242::KmScene2242(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+void KmScene2242::xUpdate() {
+ setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
+}
+
+uint32 KmScene2242::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stStartWalkingResume);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+KmHallOfRecords::KmHallOfRecords(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+ // Empty
+}
+
+void KmHallOfRecords::xUpdate() {
+ setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
+}
+
+uint32 KmHallOfRecords::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stStartWalkingResume);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+KmScene2247::KmScene2247(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+void KmScene2247::xUpdate() {
+ setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
+}
+
+uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stStartWalkingResume);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2200_sprites.h b/engines/neverhood/modules/module2200_sprites.h
new file mode 100644
index 0000000000..9aaf3b6aae
--- /dev/null
+++ b/engines/neverhood/modules/module2200_sprites.h
@@ -0,0 +1,275 @@
+/* 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 NEVERHOOD_MODULES_MODULE2200_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2200_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/graphics.h"
+
+namespace Neverhood {
+
+static const NPoint kSsScene2201PuzzleCubePoints[] = {
+ {305, 305}, {321, 305}, {336, 305}, {305, 319},
+ {321, 319}, {336, 319}, {305, 332}, {321, 332},
+ {336, 333}
+};
+
+static const uint32 kSsScene2201PuzzleCubeFileHashes[] = {
+ 0x88134A44, 0xAA124340, 0xB8124602, 0xA902464C,
+ 0x890A4244, 0xA8124642, 0xB812C204, 0x381A4A4C
+};
+
+class AsScene2201CeilingFan : public AnimatedSprite {
+public:
+ AsScene2201CeilingFan(NeverhoodEngine *vm);
+};
+
+class AsScene2201Door : public AnimatedSprite {
+public:
+ AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen);
+protected:
+ Klaymen *_klaymen;
+ Sprite *_ssDoorLight;
+ bool _isOpen;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stOpenDoor();
+ void stCloseDoor();
+};
+
+class SsScene2201PuzzleCube : public StaticSprite {
+public:
+ SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex);
+};
+
+class SsScene2202PuzzleCube : public StaticSprite {
+public:
+ SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol);
+protected:
+ Scene *_parentScene;
+ int16 _cubeSymbol;
+ int16 _cubePosition;
+ int16 _newX, _newY;
+ int16 _xDelta, _yDelta;
+ int16 _xIncr;
+ int16 _yIncr;
+ int16 _errValue;
+ int16 _counter;
+ int16 _xFlagPos;
+ bool _counterDirection;
+ bool _isMoving;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoveCubeX();
+ void suMoveCubeY();
+ void moveCube(int16 newCubePosition);
+ void stopMoving();
+};
+
+class AsCommonKey : public AnimatedSprite {
+public:
+ AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y);
+protected:
+ Scene *_parentScene;
+ int _keyIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2203Door : public AnimatedSprite {
+public:
+ AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex);
+protected:
+ Scene *_parentScene;
+ Sprite *_otherDoor;
+ uint _doorIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void openDoor();
+ void closeDoor();
+};
+
+class SsScene2205DoorFrame : public StaticSprite {
+public:
+ SsScene2205DoorFrame(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2206DoorSpikes : public StaticSprite {
+public:
+ AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash);
+protected:
+ int _deltaIndex;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suOpen();
+ void suClose();
+};
+
+class AsScene2206Platform : public StaticSprite {
+public:
+ AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash);
+protected:
+ int16 _yDelta;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoveDown();
+};
+
+class SsScene2206TestTube : public StaticSprite {
+public:
+ SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2207Elevator : public AnimatedSprite {
+public:
+ AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene);
+ ~AsScene2207Elevator();
+protected:
+ Scene *_parentScene;
+ NPointArray *_pointArray;
+ int16 _pointIndex;
+ int16 _destPointIndex, _destPointIndexDelta;
+ bool _isMoving;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suSetPosition();
+ void moveToY(int16 y);
+};
+
+class AsScene2207Lever : public AnimatedSprite {
+public:
+ AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stLeverDown();
+ void stLeverDownEvent();
+ void stLeverUp();
+ void stLeverUpEvent();
+};
+
+class AsScene2207WallRobotAnimation : public AnimatedSprite {
+public:
+ AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene);
+ ~AsScene2207WallRobotAnimation();
+protected:
+ bool _idle;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stStartAnimation();
+ void stStopAnimation();
+ void cbStopAnimation();
+};
+
+class AsScene2207WallCannonAnimation : public AnimatedSprite {
+public:
+ AsScene2207WallCannonAnimation(NeverhoodEngine *vm);
+protected:
+ bool _idle;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stStartAnimation();
+ void stStopAnimation();
+ void cbStopAnimation();
+};
+
+class SsScene2207Symbol : public StaticSprite {
+public:
+ SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index);
+};
+
+class KmScene2201 : public Klaymen {
+public:
+ KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2203 : public Klaymen {
+public:
+ KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stClayDoorOpen();
+ uint32 hmClayDoorOpen(int messageNum, const MessageParam &param, Entity *sender);
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2205 : public Klaymen {
+public:
+ KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2206 : public Klaymen {
+public:
+ KmScene2206(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+ ~KmScene2206();
+protected:
+ void stRidePlatformDown();
+ void suRidePlatformDown();
+
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2207 : public Klaymen {
+public:
+ KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2242 : public Klaymen {
+public:
+ KmScene2242(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmHallOfRecords : public Klaymen {
+public:
+ KmHallOfRecords(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2247 : public Klaymen {
+public:
+ KmScene2247(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void xUpdate();
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2200_SPRITES_H */
diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp
index 34eca14bea..689d53570f 100644
--- a/engines/neverhood/modules/module2300.cpp
+++ b/engines/neverhood/modules/module2300.cpp
@@ -20,8 +20,8 @@
*
*/
-#include "neverhood/modules/module2300.h"
#include "neverhood/navigationscene.h"
+#include "neverhood/modules/module2300.h"
namespace Neverhood {
@@ -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);
@@ -68,7 +68,7 @@ Module2300::~Module2300() {
}
void Module2300::createScene(int sceneNum, int which) {
- debug("Module2300::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2300::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -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 450812a5f3..dab39b24f6 100644
--- a/engines/neverhood/modules/module2400.cpp
+++ b/engines/neverhood/modules/module2400.cpp
@@ -20,17 +20,23 @@
*
*/
+#include "neverhood/modules/module1000_sprites.h"
+#include "neverhood/modules/module1200_sprites.h"
#include "neverhood/modules/module2400.h"
+#include "neverhood/modules/module2100_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
+#include "neverhood/modules/module2400_sprites.h"
+#include "neverhood/modules/module2800_sprites.h"
namespace Neverhood {
Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x202D1010, 0xB110382D);
if (which < 0)
- createScene(_vm->gameState().sceneNum, _vm->gameState().which);
+ createScene(_vm->gameState().sceneNum, -1);
else
createScene(0, 0);
@@ -41,7 +47,7 @@ Module2400::~Module2400() {
}
void Module2400::createScene(int sceneNum, int which) {
- debug("Module2400::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2400::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -168,205 +174,13 @@ static const uint32 kScene2401FileHashes3[] = {
};
static const NRect kScene2401Rects[] = {
- NRect(369, 331, 394, 389),
- NRect(395, 331, 419, 389),
- NRect(420, 331, 441, 389),
- NRect(442, 331, 464, 389),
- NRect(465, 331, 491, 389)
-};
-
-static const uint32 kAsScene2401WaterSpitFileHashes2[] = {
- 0x5C044690, 0x5C644690, 0x5CA44690,
- 0x5D244690, 0x5E244690
-};
-
-static const uint32 kAsScene2401WaterSpitFileHashes1[] = {
- 0xF4418408, 0xF4418808, 0xF4419008,
- 0xF441A008, 0xCD4F8411
+ { 369, 331, 394, 389 },
+ { 395, 331, 419, 389 },
+ { 420, 331, 441, 389 },
+ { 442, 331, 464, 389 },
+ { 465, 331, 491, 389 }
};
-AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200) {
-
- _x = 240;
- _y = 447;
- createSurface(100, 146, 74);
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2401WaterSpit::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
-}
-
-uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x120A0013)
- playSound(0, kAsScene2401WaterSpitFileHashes1[_soundIndex]);
- break;
- case 0x2000:
- _x = 240;
- _y = 447;
- _soundIndex = getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger());
- startAnimation(kAsScene2401WaterSpitFileHashes2[param.asInteger()], 0, -1);
- setVisible(true);
- playSound(0, 0x48640244);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
-AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200), _isWaterFlowing(false) {
-
- _x = 88;
- _y = 421;
- createSurface1(0x10203116, 100);
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2401FlowingWater::handleMessage);
-}
-
-AsScene2401FlowingWater::~AsScene2401FlowingWater() {
- _vm->_soundMan->deleteSoundGroup(0x40F11C09);
-}
-
-uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (_isWaterFlowing && param.asInteger() == 0x02421405)
- startAnimationByHash(0x10203116, 0x01084280, 0);
- break;
- case 0x2002:
- if (!_isWaterFlowing) {
- _vm->_soundMan->addSound(0x40F11C09, 0x980C1420);
- _vm->_soundMan->playSoundLooping(0x980C1420);
- startAnimation(0x10203116, 0, -1);
- setVisible(true);
- _isWaterFlowing = true;
- }
- break;
- case 0x2003:
- _vm->_soundMan->deleteSound(0x980C1420);
- _isWaterFlowing = false;
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
-AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y)
- : AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) {
-
- _x = x;
- _y = y;
- createSurface1(0xB8596884, 100);
- setVisible(false);
- SetUpdateHandler(&AsScene2401WaterFlushing::update);
- SetMessageHandler(&AsScene2401WaterFlushing::handleMessage);
-}
-
-void AsScene2401WaterFlushing::update() {
- if (_countdown != 0 && (--_countdown) == 0) {
- setDoDeltaX(_vm->_rnd->getRandomNumber(1));
- startAnimation(0xB8596884, 0, -1);
- setVisible(true);
- }
- AnimatedSprite::update();
-}
-
-uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (_flushLoopCount > 0 && param.asInteger() == 0x02421405) {
- startAnimationByHash(0xB8596884, 0x01084280, 0);
- _flushLoopCount--;
- }
- break;
- case 0x2002:
- if (param.asInteger() > 0) {
- _flushLoopCount = param.asInteger() - 1;
- _countdown = _vm->_rnd->getRandomNumber(3) + 1;
- }
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
-AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen)
- : AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) {
-
- _x = 320;
- _y = 240;
- createSurface1(0x44687810, 100);
- _newStickFrameIndex = STICK_LAST_FRAME;
- if (_isOpen) {
- stopAnimation();
- setVisible(false);
- _countdown = 48;
- } else {
- startAnimation(0x44687810, 0, -1);
- _newStickFrameIndex = 0;
- }
- SetUpdateHandler(&AsScene2401Door::update);
- SetMessageHandler(&AsScene2401Door::handleMessage);
-}
-
-void AsScene2401Door::update() {
- if (_isOpen && _countdown != 0 && (--_countdown) == 0) {
- _isOpen = false;
- setVisible(true);
- startAnimation(0x44687810, -1, -1);
- _newStickFrameIndex = 0;
- _playBackwards = true;
- playSound(0, calcHash("fxDoorClose38"));
- }
- AnimatedSprite::update();
-}
-
-uint32 AsScene2401Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2004:
- if (_isOpen)
- _countdown = 168;
- messageResult = _isOpen ? 1 : 0;
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- if (!_isOpen) {
- _countdown = 168;
- _isOpen = true;
- setVisible(true);
- startAnimation(0x44687810, 0, -1);
- playSound(0, calcHash("fxDoorOpen38"));
- NextState(&AsScene2401Door::stDoorOpenFinished);
- }
- break;
- }
- return messageResult;
-}
-
-void AsScene2401Door::stDoorOpenFinished() {
- stopAnimation();
- setVisible(false);
-}
-
Scene2401::Scene2401(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown1(0), _countdown2(0), _unkFlag(false),
_soundToggle(false), _asWaterSpitIndex(0) {
@@ -398,7 +212,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 +275,7 @@ void Scene2401::update() {
if (_countdown2 != 0 && (--_countdown2) == 0)
sendMessage(_asFlowingWater, 0x2003, 0);
-
+
Scene::update();
}
@@ -546,143 +360,6 @@ static const uint32 kScene2402FileHashes[] = {
0xD0910068, 0xD09100A8
};
-AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isOpen(isOpen), _countdown(0) {
-
- _x = 320;
- _y = 240;
- createSurface1(0x80495831, 100);
- if (_isOpen) {
- startAnimation(0x80495831, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- _countdown = 48;
- } else {
- stopAnimation();
- setVisible(false);
- }
- SetUpdateHandler(&AsScene2402Door::update);
- SetMessageHandler(&AsScene2402Door::handleMessage);
-}
-
-void AsScene2402Door::update() {
- if (_isOpen && _countdown != 0 && (--_countdown) == 0) {
- _isOpen = false;
- setVisible(true);
- startAnimation(0x80495831, -1, -1);
- _playBackwards = true;
- playSound(0, calcHash("fxDoorClose38"));
- NextState(&AsScene2402Door::stDoorClosingFinished);
- }
- AnimatedSprite::update();
-}
-
-uint32 AsScene2402Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- if (_isOpen)
- _countdown = 144;
- messageResult = _isOpen ? 1 : 0;
- break;
- case 0x3002:
- gotoNextState();
- break;
- case 0x4808:
- _countdown = 144;
- _isOpen = true;
- setVisible(true);
- startAnimation(0x80495831, 0, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
- playSound(0, calcHash("fxDoorOpen38"));
- break;
- }
- return messageResult;
-}
-
-void AsScene2402Door::stDoorClosingFinished() {
- sendMessage(_parentScene, 0x2001, 0);
- setVisible(false);
-}
-
-AsScene2402TV::AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen)
- : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown1(0), _countdown2(0) {
-
- _x = 260;
- _y = 210;
- createSurface(100, 127, 90);
- setDoDeltaX(1);
- SetMessageHandler(&Sprite::handleMessage);
- if (!getGlobalVar(V_TV_JOKE_TOLD)) {
- loadSound(0, 0x58208810);
- _countdown1 = 48;
- startAnimation(0x4919397A, 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AsScene2402TV::upWait);
- } else {
- int16 frameIndex;
- if (_klaymen->getX() > 320)
- _currFrameIndex = 29;
- frameIndex = CLIP<int16>((_klaymen->getX() - _x + 150) / 10, 0, 29);
- startAnimation(0x050A0103, frameIndex, -1);
- _newStickFrameIndex = frameIndex;
- _countdown1 = 0;
- SetUpdateHandler(&AsScene2402TV::upFocusKlaymen);
- }
-}
-
-AsScene2402TV::~AsScene2402TV() {
- _vm->_soundMan->deleteSoundGroup(0x01520123);
-}
-
-void AsScene2402TV::upWait() {
- if (_countdown1 != 0 && (--_countdown1) == 0) {
- startAnimation(0x4919397A, 0, -1);
- SetMessageHandler(&AsScene2402TV::hmJoke);
- NextState(&AsScene2402TV::stJokeFinished);
- }
- AnimatedSprite::update();
-}
-
-void AsScene2402TV::upFocusKlaymen() {
- int16 frameIndex = CLIP<int16>((_klaymen->getX() - _x + 150) / 10, 0, 29);
- if (frameIndex != _currFrameIndex) {
- if (frameIndex > _currFrameIndex)
- _currFrameIndex++;
- else if (frameIndex < _currFrameIndex)
- _currFrameIndex--;
- startAnimation(0x050A0103, _currFrameIndex, -1);
- _newStickFrameIndex = _currFrameIndex;
- if (_countdown2 == 0) {
- _vm->_soundMan->addSound(0x01520123, 0xC42D4528);
- _vm->_soundMan->playSoundLooping(0xC42D4528);
- }
- _countdown2 = 5;
- } else if (_countdown2 != 0 && (--_countdown2 == 0))
- _vm->_soundMan->deleteSound(0xC42D4528);
- AnimatedSprite::update();
-}
-
-void AsScene2402TV::stJokeFinished() {
- setGlobalVar(V_TV_JOKE_TOLD, 1);
- startAnimation(0x050A0103, 0, -1);
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AsScene2402TV::upFocusKlaymen);
-}
-
-uint32 AsScene2402TV::hmJoke(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (param.asInteger() == 0x431EA0B0)
- playSound(0);
- break;
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
Scene2402::Scene2402(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _soundToggle(false) {
@@ -698,7 +375,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 +456,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 +464,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 +476,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 +505,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 +564,7 @@ Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which)
setGlobalVar(V_KEY3_LOCATION, 2);
SetMessageHandler(&Scene2406::handleMessage);
-
+
setRectList(0x004B78C8);
insertScreenMouse(0xB03001A8);
@@ -913,7 +590,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/module2400.h b/engines/neverhood/modules/module2400.h
index b50fff91c4..61603f3e00 100644
--- a/engines/neverhood/modules/module2400.h
+++ b/engines/neverhood/modules/module2400.h
@@ -27,12 +27,6 @@
#include "neverhood/module.h"
#include "neverhood/scene.h"
#include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1100.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module2100.h"
-#include "neverhood/modules/module2200.h"
-#include "neverhood/modules/module2800.h"
#include "neverhood/diskplayerscene.h"
namespace Neverhood {
@@ -50,44 +44,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene2401WaterSpit : public AnimatedSprite {
-public:
- AsScene2401WaterSpit(NeverhoodEngine *vm);
-protected:
- int _soundIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2401FlowingWater : public AnimatedSprite {
-public:
- AsScene2401FlowingWater(NeverhoodEngine *vm);
- virtual ~AsScene2401FlowingWater();
-protected:
- bool _isWaterFlowing;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2401WaterFlushing : public AnimatedSprite {
-public:
- AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y);
-protected:
- int _countdown;
- int _flushLoopCount;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2401Door : public AnimatedSprite {
-public:
- AsScene2401Door(NeverhoodEngine *vm, bool isOpen);
-protected:
- int _countdown;
- bool _isOpen;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stDoorOpenFinished();
-};
-
class Scene2401 : public Scene {
public:
Scene2401(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -111,32 +67,6 @@ protected:
void playPipeSound(uint32 fileHash);
};
-class AsScene2402Door : public AnimatedSprite {
-public:
- AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen);
-protected:
- Scene *_parentScene;
- int _countdown;
- bool _isOpen;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void stDoorClosingFinished();
-};
-
-class AsScene2402TV : public AnimatedSprite {
-public:
- AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen);
- virtual ~AsScene2402TV();
-protected:
- Klaymen *_klaymen;
- int _countdown1;
- int _countdown2;
- void upWait();
- void upFocusKlaymen();
- void stJokeFinished();
- uint32 hmJoke(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2402 : public Scene {
public:
Scene2402(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2400_sprites.cpp b/engines/neverhood/modules/module2400_sprites.cpp
new file mode 100644
index 0000000000..bf85b0dc37
--- /dev/null
+++ b/engines/neverhood/modules/module2400_sprites.cpp
@@ -0,0 +1,741 @@
+/* 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 "neverhood/modules/module2400_sprites.h"
+
+namespace Neverhood {
+
+static const uint32 kAsScene2401WaterSpitFileHashes2[] = {
+ 0x5C044690, 0x5C644690, 0x5CA44690,
+ 0x5D244690, 0x5E244690
+};
+
+static const uint32 kAsScene2401WaterSpitFileHashes1[] = {
+ 0xF4418408, 0xF4418808, 0xF4419008,
+ 0xF441A008, 0xCD4F8411
+};
+
+AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200) {
+
+ _x = 240;
+ _y = 447;
+ createSurface(100, 146, 74);
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2401WaterSpit::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+}
+
+uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x120A0013)
+ playSound(0, kAsScene2401WaterSpitFileHashes1[_soundIndex]);
+ break;
+ case 0x2000:
+ _x = 240;
+ _y = 447;
+ _soundIndex = getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger());
+ startAnimation(kAsScene2401WaterSpitFileHashes2[param.asInteger()], 0, -1);
+ setVisible(true);
+ playSound(0, 0x48640244);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200), _isWaterFlowing(false) {
+
+ _x = 88;
+ _y = 421;
+ createSurface1(0x10203116, 100);
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2401FlowingWater::handleMessage);
+}
+
+AsScene2401FlowingWater::~AsScene2401FlowingWater() {
+ _vm->_soundMan->deleteSoundGroup(0x40F11C09);
+}
+
+uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (_isWaterFlowing && param.asInteger() == 0x02421405)
+ startAnimationByHash(0x10203116, 0x01084280, 0);
+ break;
+ case 0x2002:
+ if (!_isWaterFlowing) {
+ _vm->_soundMan->addSound(0x40F11C09, 0x980C1420);
+ _vm->_soundMan->playSoundLooping(0x980C1420);
+ startAnimation(0x10203116, 0, -1);
+ setVisible(true);
+ _isWaterFlowing = true;
+ }
+ break;
+ case 0x2003:
+ _vm->_soundMan->deleteSound(0x980C1420);
+ _isWaterFlowing = false;
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y)
+ : AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) {
+
+ _x = x;
+ _y = y;
+ createSurface1(0xB8596884, 100);
+ setVisible(false);
+ SetUpdateHandler(&AsScene2401WaterFlushing::update);
+ SetMessageHandler(&AsScene2401WaterFlushing::handleMessage);
+}
+
+void AsScene2401WaterFlushing::update() {
+ if (_countdown != 0 && (--_countdown) == 0) {
+ setDoDeltaX(_vm->_rnd->getRandomNumber(1));
+ startAnimation(0xB8596884, 0, -1);
+ setVisible(true);
+ }
+ AnimatedSprite::update();
+}
+
+uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (_flushLoopCount > 0 && param.asInteger() == 0x02421405) {
+ startAnimationByHash(0xB8596884, 0x01084280, 0);
+ _flushLoopCount--;
+ }
+ break;
+ case 0x2002:
+ if (param.asInteger() > 0) {
+ _flushLoopCount = param.asInteger() - 1;
+ _countdown = _vm->_rnd->getRandomNumber(3) + 1;
+ }
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen)
+ : AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) {
+
+ _x = 320;
+ _y = 240;
+ createSurface1(0x44687810, 100);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ if (_isOpen) {
+ stopAnimation();
+ setVisible(false);
+ _countdown = 48;
+ } else {
+ startAnimation(0x44687810, 0, -1);
+ _newStickFrameIndex = 0;
+ }
+ SetUpdateHandler(&AsScene2401Door::update);
+ SetMessageHandler(&AsScene2401Door::handleMessage);
+}
+
+void AsScene2401Door::update() {
+ if (_isOpen && _countdown != 0 && (--_countdown) == 0) {
+ _isOpen = false;
+ setVisible(true);
+ startAnimation(0x44687810, -1, -1);
+ _newStickFrameIndex = 0;
+ _playBackwards = true;
+ playSound(0, calcHash("fxDoorClose38"));
+ }
+ AnimatedSprite::update();
+}
+
+uint32 AsScene2401Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2004:
+ if (_isOpen)
+ _countdown = 168;
+ messageResult = _isOpen ? 1 : 0;
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ if (!_isOpen) {
+ _countdown = 168;
+ _isOpen = true;
+ setVisible(true);
+ startAnimation(0x44687810, 0, -1);
+ playSound(0, calcHash("fxDoorOpen38"));
+ NextState(&AsScene2401Door::stDoorOpenFinished);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2401Door::stDoorOpenFinished() {
+ stopAnimation();
+ setVisible(false);
+}
+
+AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isOpen(isOpen), _countdown(0) {
+
+ _x = 320;
+ _y = 240;
+ createSurface1(0x80495831, 100);
+ if (_isOpen) {
+ startAnimation(0x80495831, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ _countdown = 48;
+ } else {
+ stopAnimation();
+ setVisible(false);
+ }
+ SetUpdateHandler(&AsScene2402Door::update);
+ SetMessageHandler(&AsScene2402Door::handleMessage);
+}
+
+void AsScene2402Door::update() {
+ if (_isOpen && _countdown != 0 && (--_countdown) == 0) {
+ _isOpen = false;
+ setVisible(true);
+ startAnimation(0x80495831, -1, -1);
+ _playBackwards = true;
+ playSound(0, calcHash("fxDoorClose38"));
+ NextState(&AsScene2402Door::stDoorClosingFinished);
+ }
+ AnimatedSprite::update();
+}
+
+uint32 AsScene2402Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ if (_isOpen)
+ _countdown = 144;
+ messageResult = _isOpen ? 1 : 0;
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x4808:
+ _countdown = 144;
+ _isOpen = true;
+ setVisible(true);
+ startAnimation(0x80495831, 0, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ playSound(0, calcHash("fxDoorOpen38"));
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2402Door::stDoorClosingFinished() {
+ sendMessage(_parentScene, 0x2001, 0);
+ setVisible(false);
+}
+
+AsScene2402TV::AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen)
+ : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown1(0), _countdown2(0) {
+
+ _x = 260;
+ _y = 210;
+ createSurface(100, 127, 90);
+ setDoDeltaX(1);
+ SetMessageHandler(&Sprite::handleMessage);
+ if (!getGlobalVar(V_TV_JOKE_TOLD)) {
+ loadSound(0, 0x58208810);
+ _countdown1 = 48;
+ startAnimation(0x4919397A, 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AsScene2402TV::upWait);
+ } else {
+ int16 frameIndex;
+ if (_klaymen->getX() > 320)
+ _currFrameIndex = 29;
+ frameIndex = CLIP<int16>((_klaymen->getX() - _x + 150) / 10, 0, 29);
+ startAnimation(0x050A0103, frameIndex, -1);
+ _newStickFrameIndex = frameIndex;
+ _countdown1 = 0;
+ SetUpdateHandler(&AsScene2402TV::upFocusKlaymen);
+ }
+}
+
+AsScene2402TV::~AsScene2402TV() {
+ _vm->_soundMan->deleteSoundGroup(0x01520123);
+}
+
+void AsScene2402TV::upWait() {
+ if (_countdown1 != 0 && (--_countdown1) == 0) {
+ startAnimation(0x4919397A, 0, -1);
+ SetMessageHandler(&AsScene2402TV::hmJoke);
+ NextState(&AsScene2402TV::stJokeFinished);
+ }
+ AnimatedSprite::update();
+}
+
+void AsScene2402TV::upFocusKlaymen() {
+ int16 frameIndex = CLIP<int16>((_klaymen->getX() - _x + 150) / 10, 0, 29);
+ if (frameIndex != _currFrameIndex) {
+ if (frameIndex > _currFrameIndex)
+ _currFrameIndex++;
+ else if (frameIndex < _currFrameIndex)
+ _currFrameIndex--;
+ startAnimation(0x050A0103, _currFrameIndex, -1);
+ _newStickFrameIndex = _currFrameIndex;
+ if (_countdown2 == 0) {
+ _vm->_soundMan->addSound(0x01520123, 0xC42D4528);
+ _vm->_soundMan->playSoundLooping(0xC42D4528);
+ }
+ _countdown2 = 5;
+ } else if (_countdown2 != 0 && (--_countdown2 == 0))
+ _vm->_soundMan->deleteSound(0xC42D4528);
+ AnimatedSprite::update();
+}
+
+void AsScene2402TV::stJokeFinished() {
+ setGlobalVar(V_TV_JOKE_TOLD, 1);
+ startAnimation(0x050A0103, 0, -1);
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AsScene2402TV::upFocusKlaymen);
+}
+
+uint32 AsScene2402TV::hmJoke(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x431EA0B0)
+ playSound(0);
+ break;
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2401::KmScene2401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y),
+ _canSpitPipe(false), _contSpitPipe(false), _readyToSpit(false),
+ _spitPipeIndex(0), _spitDestPipeIndex(0), _spitContDestPipeIndex(0) {
+
+ // Empty
+}
+
+uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x4832:
+ GotoState(&Klaymen::stUseTube);
+ break;
+ case 0x4833:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAbout);
+ else {
+ _spitPipeIndex = sendMessage(_parentScene, 0x2000, 0);
+ GotoState(&KmScene2401::stTrySpitIntoPipe);
+ }
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+uint32 KmScene2401::hmSpit(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Klaymen::hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x16401CA6) {
+ _canSpitPipe = true;
+ if (_contSpitPipe)
+ spitIntoPipe();
+ } else if (param.asInteger() == 0xC11C0008) {
+ _canSpitPipe = false;
+ _acceptInput = false;
+ _readyToSpit = false;
+ } else if (param.asInteger() == 0x018A0001) {
+ sendMessage(_parentScene, 0x2001, _spitDestPipeIndex);
+ }
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene2401::stTrySpitIntoPipe() {
+ if (_readyToSpit) {
+ _contSpitPipe = true;
+ _spitContDestPipeIndex = _spitPipeIndex;
+ if (_canSpitPipe)
+ spitIntoPipe();
+ } else if (!stStartAction(AnimationCallback(&KmScene2401::stTrySpitIntoPipe))) {
+ _busyStatus = 2;
+ _acceptInput = true;
+ _spitDestPipeIndex = _spitPipeIndex;
+ _readyToSpit = true;
+ _canSpitPipe = false;
+ _contSpitPipe = false;
+ startAnimation(0x1808B150, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2401::hmSpit);
+ SetSpriteUpdate(NULL);
+ }
+}
+
+void KmScene2401::spitIntoPipe() {
+ _contSpitPipe = false;
+ _spitDestPipeIndex = _spitContDestPipeIndex;
+ _canSpitPipe = false;
+ _acceptInput = false;
+ startAnimation(0x1B08B553, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2401::hmSpit);
+ SetSpriteUpdate(NULL);
+ NextState(&KmScene2401::stContSpitIntoPipe);
+}
+
+void KmScene2401::stContSpitIntoPipe() {
+ _canSpitPipe = true;
+ _acceptInput = true;
+ startAnimationByHash(0x1808B150, 0x16401CA6, 0);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2401::hmSpit);
+ SetSpriteUpdate(NULL);
+}
+
+KmScene2402::KmScene2402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2402::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (!getGlobalVar(V_TV_JOKE_TOLD))
+ GotoState(&Klaymen::stStandWonderAbout);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stWalkingFirst);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2403::KmScene2403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stPullCord);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPressButton);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPressFloorButton);
+ else
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2000, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2001, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ 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);
+}
+
+uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ if (param.asInteger() != 0) {
+ _destX = param.asInteger();
+ GotoState(&Klaymen::stWalkingFirst);
+ } else
+ GotoState(&Klaymen::stPeekWall);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481A:
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2000, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2001, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2400_sprites.h b/engines/neverhood/modules/module2400_sprites.h
new file mode 100644
index 0000000000..a901eb101c
--- /dev/null
+++ b/engines/neverhood/modules/module2400_sprites.h
@@ -0,0 +1,139 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE2400_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2400_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/gamemodule.h"
+
+namespace Neverhood {
+
+class AsScene2401WaterSpit : public AnimatedSprite {
+public:
+ AsScene2401WaterSpit(NeverhoodEngine *vm);
+protected:
+ int _soundIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2401FlowingWater : public AnimatedSprite {
+public:
+ AsScene2401FlowingWater(NeverhoodEngine *vm);
+ virtual ~AsScene2401FlowingWater();
+protected:
+ bool _isWaterFlowing;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2401WaterFlushing : public AnimatedSprite {
+public:
+ AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y);
+protected:
+ int _countdown;
+ int _flushLoopCount;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2401Door : public AnimatedSprite {
+public:
+ AsScene2401Door(NeverhoodEngine *vm, bool isOpen);
+protected:
+ int _countdown;
+ bool _isOpen;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stDoorOpenFinished();
+};
+
+class AsScene2402Door : public AnimatedSprite {
+public:
+ AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ bool _isOpen;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void stDoorClosingFinished();
+};
+
+class AsScene2402TV : public AnimatedSprite {
+public:
+ AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen);
+ virtual ~AsScene2402TV();
+protected:
+ Klaymen *_klaymen;
+ int _countdown1;
+ int _countdown2;
+ void upWait();
+ void upFocusKlaymen();
+ void stJokeFinished();
+ uint32 hmJoke(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene2401 : public Klaymen {
+public:
+ KmScene2401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ bool _canSpitPipe;
+ bool _contSpitPipe;
+ bool _readyToSpit;
+ uint32 _spitPipeIndex;
+ uint32 _spitDestPipeIndex;
+ uint32 _spitContDestPipeIndex;
+
+ void spitIntoPipe();
+ void stTrySpitIntoPipe();
+ void stContSpitIntoPipe();
+ uint32 hmSpit(int messageNum, const MessageParam &param, Entity *sender);
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2402 : public Klaymen {
+public:
+ KmScene2402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2403 : public Klaymen {
+public:
+ KmScene2403(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2406 : public Klaymen {
+public:
+ KmScene2406(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2400_SPRITES_H */
diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp
index a997b5aab1..d0e60adf65 100644
--- a/engines/neverhood/modules/module2500.cpp
+++ b/engines/neverhood/modules/module2500.cpp
@@ -20,8 +20,12 @@
*
*/
+#include "neverhood/modules/module1600.h" // for Scene1608
+#include "neverhood/modules/module1600_sprites.h"
#include "neverhood/modules/module2500.h"
-#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module2500_sprites.h"
+#include "neverhood/modules/module2700.h" // for Scene2704
+#include "neverhood/modules/module2700_sprites.h"
namespace Neverhood {
@@ -29,29 +33,29 @@ static const uint32 kScene2505StaticSprites[] = {
0x4000A226, 0
};
-static const NRect kScene2505ClipRect = NRect(0, 0, 564, 480);
+static const NRect kScene2505ClipRect = { 0, 0, 564, 480 };
static const uint32 kScene2506StaticSprites[] = {
0x4027AF02, 0
};
-static const NRect kScene2506ClipRect = NRect(0, 0, 640, 441);
+static const NRect kScene2506ClipRect = { 0, 0, 640, 441 };
static const uint32 kScene2508StaticSprites1[] = {
0x2F08E610, 0xD844E6A0, 0
};
-static const NRect kScene2508ClipRect1 = NRect(0, 0, 594, 448);
+static const NRect kScene2508ClipRect1 = { 0, 0, 594, 448 };
static const uint32 kScene2508StaticSprites2[] = {
0x2F08E610, 0
};
-static const NRect kScene2508ClipRect2 = NRect(0, 0, 594, 448);
+static const NRect kScene2508ClipRect2 = { 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);
@@ -73,7 +77,7 @@ Module2500::~Module2500() {
}
void Module2500::createScene(int sceneNum, int which) {
- debug("Module2500::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2500::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -212,14 +216,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 +286,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 +304,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 +395,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 +438,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);
@@ -470,59 +474,11 @@ void Scene2501::updateKlaymenClipRect() {
_kmScene2501->setClipRect(0, 0, 640, 388);
}
-SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm)
- : StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) {
-
- loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
- setVisible(false);
- loadSound(0, 0x4600204C);
- loadSound(1, 0x408C0034);
- loadSound(2, 0x44043000);
- loadSound(3, 0x44045000);
- SetMessageHandler(&SsScene2504Button::handleMessage);
- SetUpdateHandler(&SsScene2504Button::update);
-}
-
-void SsScene2504Button::update() {
- updatePosition();
- if (_isSoundPlaying && !isSoundPlaying(0) && !isSoundPlaying(1)) {
- playSound(3);
- setVisible(false);
- _isSoundPlaying = false;
- }
- if (_countdown != 0 && (--_countdown) == 0) {
- if (getSubVar(VA_LOCKS_DISABLED, 0x01180951))
- playSound(0);
- else
- playSound(1);
- _isSoundPlaying = true;
- }
-}
-
-uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0 && !_isSoundPlaying) {
- setVisible(true);
- _countdown = 2;
- if (getSubVar(VA_LOCKS_DISABLED, 0x01180951))
- setSubVar(VA_LOCKS_DISABLED, 0x01180951, 0);
- else
- setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1);
- playSound(2);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
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/module2500.h b/engines/neverhood/modules/module2500.h
index 07db7907d5..de6226ef0c 100644
--- a/engines/neverhood/modules/module2500.h
+++ b/engines/neverhood/modules/module2500.h
@@ -26,14 +26,10 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1600.h"
-#include "neverhood/modules/module2700.h"
+#include "neverhood/modules/module1600_sprites.h" // for Tracks
namespace Neverhood {
-// Module2500
-
class Module2500 : public Module {
public:
Module2500(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -47,6 +43,8 @@ protected:
void createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL);
};
+class AsCommonCar;
+
class Scene2501 : public Scene {
public:
Scene2501(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -79,16 +77,6 @@ protected:
void updateKlaymenClipRect();
};
-class SsScene2504Button : public StaticSprite {
-public:
- SsScene2504Button(NeverhoodEngine *vm);
-protected:
- int _countdown;
- bool _isSoundPlaying;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2504 : public Scene {
public:
Scene2504(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2500_sprites.cpp b/engines/neverhood/modules/module2500_sprites.cpp
new file mode 100644
index 0000000000..ab6b3dcfbe
--- /dev/null
+++ b/engines/neverhood/modules/module2500_sprites.cpp
@@ -0,0 +1,127 @@
+/* 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 "neverhood/modules/module2500_sprites.h"
+
+namespace Neverhood {
+
+SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm)
+ : StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) {
+
+ loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
+ setVisible(false);
+ loadSound(0, 0x4600204C);
+ loadSound(1, 0x408C0034);
+ loadSound(2, 0x44043000);
+ loadSound(3, 0x44045000);
+ SetMessageHandler(&SsScene2504Button::handleMessage);
+ SetUpdateHandler(&SsScene2504Button::update);
+}
+
+void SsScene2504Button::update() {
+ updatePosition();
+ if (_isSoundPlaying && !isSoundPlaying(0) && !isSoundPlaying(1)) {
+ playSound(3);
+ setVisible(false);
+ _isSoundPlaying = false;
+ }
+ if (_countdown != 0 && (--_countdown) == 0) {
+ if (getSubVar(VA_LOCKS_DISABLED, 0x01180951))
+ playSound(0);
+ else
+ playSound(1);
+ _isSoundPlaying = true;
+ }
+}
+
+uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0 && !_isSoundPlaying) {
+ setVisible(true);
+ _countdown = 2;
+ if (getSubVar(VA_LOCKS_DISABLED, 0x01180951))
+ setSubVar(VA_LOCKS_DISABLED, 0x01180951, 0);
+ else
+ setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1);
+ playSound(2);
+ }
+ messageResult = 1;
+ 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) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2500_sprites.h b/engines/neverhood/modules/module2500_sprites.h
new file mode 100644
index 0000000000..e7f7b05702
--- /dev/null
+++ b/engines/neverhood/modules/module2500_sprites.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE2500_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2500_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class SsScene2504Button : public StaticSprite {
+public:
+ SsScene2504Button(NeverhoodEngine *vm);
+protected:
+ int _countdown;
+ bool _isSoundPlaying;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene2501 : public Klaymen {
+public:
+ KmScene2501(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2500_SPRITES_H */
diff --git a/engines/neverhood/modules/module2600.cpp b/engines/neverhood/modules/module2600.cpp
index b8dbf7bff1..a6484a4926 100644
--- a/engines/neverhood/modules/module2600.cpp
+++ b/engines/neverhood/modules/module2600.cpp
@@ -21,6 +21,7 @@
*/
#include "neverhood/modules/module2600.h"
+#include "neverhood/modules/module2600_sprites.h"
namespace Neverhood {
@@ -35,7 +36,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)
@@ -54,7 +55,7 @@ Module2600::~Module2600() {
}
void Module2600::createScene(int sceneNum, int which) {
- debug("Module2600::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2600::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -218,98 +219,10 @@ void Module2600::updateScene() {
}
}
}
-
-SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene)
- : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) {
-
- SetUpdateHandler(&SsScene2609Button::update);
- SetMessageHandler(&SsScene2609Button::handleMessage);
-
- loadSprite(0x825A6923, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
- if (!getGlobalVar(V_WATER_RUNNING))
- setVisible(false);
- loadSound(0, 0x10267160);
- loadSound(1, 0x7027FD64);
- loadSound(2, 0x44043000);
- loadSound(3, 0x44045000);
-}
-
-void SsScene2609Button::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0)) {
- if (getGlobalVar(V_WATER_RUNNING)) {
- setGlobalVar(V_WATER_RUNNING, 0);
- sendMessage(_parentScene, 0x2001, 0);
- } else {
- setGlobalVar(V_WATER_RUNNING, 1);
- sendMessage(_parentScene, 0x2002, 0);
- }
- }
-}
-
-uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0) {
- sendMessage(_parentScene, 0x2000, 0);
- if (getGlobalVar(V_WATER_RUNNING)) {
- setVisible(false);
- playSound(3);
- playSound(1);
- _countdown = 12;
- } else {
- setVisible(true);
- playSound(2);
- playSound(0);
- _countdown = 96;
- }
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1000) {
-
- _x = 240;
- _y = 420;
- setDoDeltaX(1);
- createSurface1(0x9C210C90, 1200);
- setClipRect(260, 260, 400, 368);
- _vm->_soundMan->addSound(0x08526C36, 0xDC2769B0);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2609Water::handleMessage);
- if (getGlobalVar(V_WATER_RUNNING))
- sendMessage(this, 0x2002, 0);
-}
-
-AsScene2609Water::~AsScene2609Water() {
- _vm->_soundMan->deleteSoundGroup(0x08526C36);
-}
-
-uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2001:
- stopAnimation();
- setVisible(false);
- _vm->_soundMan->stopSound(0xDC2769B0);
- break;
- case 0x2002:
- startAnimation(0x9C210C90, 0, -1);
- setVisible(true);
- _vm->_soundMan->playSoundLooping(0xDC2769B0);
- break;
- }
- return messageResult;
-}
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/module2600.h b/engines/neverhood/modules/module2600.h
index d972e0fb0d..99ec3a34ca 100644
--- a/engines/neverhood/modules/module2600.h
+++ b/engines/neverhood/modules/module2600.h
@@ -41,24 +41,6 @@ protected:
void updateScene();
};
-class SsScene2609Button : public StaticSprite {
-public:
- SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2609Water : public AnimatedSprite {
-public:
- AsScene2609Water(NeverhoodEngine *vm);
- virtual ~AsScene2609Water();
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2609 : public Scene {
public:
Scene2609(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2600_sprites.cpp b/engines/neverhood/modules/module2600_sprites.cpp
new file mode 100644
index 0000000000..2c24b533f3
--- /dev/null
+++ b/engines/neverhood/modules/module2600_sprites.cpp
@@ -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.
+ *
+ */
+
+#include "neverhood/modules/module2600_sprites.h"
+
+namespace Neverhood {
+
+SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene)
+ : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) {
+
+ SetUpdateHandler(&SsScene2609Button::update);
+ SetMessageHandler(&SsScene2609Button::handleMessage);
+
+ loadSprite(0x825A6923, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
+ if (!getGlobalVar(V_WATER_RUNNING))
+ setVisible(false);
+ loadSound(0, 0x10267160);
+ loadSound(1, 0x7027FD64);
+ loadSound(2, 0x44043000);
+ loadSound(3, 0x44045000);
+}
+
+void SsScene2609Button::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0)) {
+ if (getGlobalVar(V_WATER_RUNNING)) {
+ setGlobalVar(V_WATER_RUNNING, 0);
+ sendMessage(_parentScene, 0x2001, 0);
+ } else {
+ setGlobalVar(V_WATER_RUNNING, 1);
+ sendMessage(_parentScene, 0x2002, 0);
+ }
+ }
+}
+
+uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0) {
+ sendMessage(_parentScene, 0x2000, 0);
+ if (getGlobalVar(V_WATER_RUNNING)) {
+ setVisible(false);
+ playSound(3);
+ playSound(1);
+ _countdown = 12;
+ } else {
+ setVisible(true);
+ playSound(2);
+ playSound(0);
+ _countdown = 96;
+ }
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1000) {
+
+ _x = 240;
+ _y = 420;
+ setDoDeltaX(1);
+ createSurface1(0x9C210C90, 1200);
+ setClipRect(260, 260, 400, 368);
+ _vm->_soundMan->addSound(0x08526C36, 0xDC2769B0);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2609Water::handleMessage);
+ if (getGlobalVar(V_WATER_RUNNING))
+ sendMessage(this, 0x2002, 0);
+}
+
+AsScene2609Water::~AsScene2609Water() {
+ _vm->_soundMan->deleteSoundGroup(0x08526C36);
+}
+
+uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2001:
+ stopAnimation();
+ setVisible(false);
+ _vm->_soundMan->stopSound(0xDC2769B0);
+ break;
+ case 0x2002:
+ startAnimation(0x9C210C90, 0, -1);
+ setVisible(true);
+ _vm->_soundMan->playSoundLooping(0xDC2769B0);
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2600_sprites.h b/engines/neverhood/modules/module2600_sprites.h
new file mode 100644
index 0000000000..c36e72cae8
--- /dev/null
+++ b/engines/neverhood/modules/module2600_sprites.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULES_MODULE2600_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2600_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+// Module2600
+
+class SsScene2609Button : public StaticSprite {
+public:
+ SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2609Water : public AnimatedSprite {
+public:
+ AsScene2609Water(NeverhoodEngine *vm);
+ virtual ~AsScene2609Water();
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2600_SPRITES_H */
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index 8b69bc050e..1b78615fdb 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -20,20 +20,21 @@
*
*/
-#include "neverhood/modules/module2700.h"
#include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1000.h"
+#include "neverhood/modules/module1600_sprites.h"
+#include "neverhood/modules/module2700.h"
+#include "neverhood/modules/module2700_sprites.h"
namespace Neverhood {
-static const NRect kScene2710ClipRect = NRect(0, 0, 626, 480);
+static const NRect kScene2710ClipRect = { 0, 0, 626, 480 };
static const uint32 kScene2710StaticSprites[] = {
0x0D2016C0,
0
};
-static const NRect kScene2711ClipRect = NRect(0, 0, 521, 480);
+static const NRect kScene2711ClipRect = { 0, 0, 521, 480 };
static const uint32 kScene2711FileHashes1[] = {
0,
@@ -68,14 +69,14 @@ static const uint32 kScene2711FileHashes3[] = {
0
};
-static const NRect kScene2724ClipRect = NRect(0, 141, 640, 480);
+static const NRect kScene2724ClipRect = { 0, 141, 640, 480 };
static const uint32 kScene2724StaticSprites[] = {
0xC20D00A5,
0
};
-static const NRect kScene2725ClipRect = NRect(0, 0, 640, 413);
+static const NRect kScene2725ClipRect = { 0, 0, 640, 413 };
static const uint32 kScene2725StaticSprites[] = {
0xC20E00A5,
@@ -83,8 +84,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);
@@ -111,7 +112,7 @@ Module2700::~Module2700() {
}
void Module2700::createScene(int sceneNum, int which) {
- debug("Module2700::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2700::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -500,7 +501,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 +509,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 +528,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);
}
@@ -536,98 +537,21 @@ void Module2700::createScene2704(int which, uint32 trackInfoId, int16 value, con
_childObject = new Scene2704(_vm, this, which, trackInfoId, value, staticSprites, clipRect);
}
-static const NPoint kCarShadowOffsets[] = {
- {-63, 3}, {-48, 40}, {-33, 58},
- { 0, 65}, { 40, 53}, { 56, 27},
- { 63, 0}, {-30, 26}, { 0, 30},
- { 26, 25}
-};
-
-SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash)
- : StaticSprite(vm, 0) {
-
- loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0);
-}
-
-AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index)
- : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index), _animFileHash(0) {
-
- SetUpdateHandler(&AsCommonCarShadow::update);
- createShadowSurface(shadowSurface, 211, 147, 100);
- updateShadow();
-}
-
-void AsCommonCarShadow::update() {
- updateShadow();
- AnimatedSprite::update();
-}
-
-void AsCommonCarShadow::updateShadow() {
- if (_asCar->getFrameIndex() != _currFrameIndex || _asCar->getCurrAnimFileHash() != _animFileHash) {
- uint32 fileHash = _asCar->getCurrAnimFileHash();
- if (fileHash == 0x35698F78 || fileHash == 0x192ADD30 || fileHash == 0x9C220DA4 ||
- fileHash == 0x9966B138 || fileHash == 0xB579A77C || fileHash == 0xA86A9538 ||
- fileHash == 0xD4220027 || fileHash == 0xD00A1364 || fileHash == 0xD4AA03A4 ||
- fileHash == 0xF46A0324) {
- startAnimation(fileHash, _asCar->getFrameIndex(), -1);
- _newStickFrameIndex = _asCar->getFrameIndex();
- }
- _animFileHash = fileHash;
- }
- _x = _asCar->getX() + kCarShadowOffsets[_index].x;
- _y = _asCar->getY() + kCarShadowOffsets[_index].y;
- if (!_asCar->getVisible()) {
- startAnimation(0x1209E09F, 0, -1);
- _newStickFrameIndex = 0;
- }
- setDoDeltaX(_asCar->isDoDeltaX() ? 1 : 0);
-}
-
-AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index)
- : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index) {
-
- SetUpdateHandler(&AsCommonCarConnectorShadow::update);
- createShadowSurface1(shadowSurface, 0x60281C10, 150);
- startAnimation(0x60281C10, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
-
-void AsCommonCarConnectorShadow::update() {
- _x = _asCar->getX() + kCarShadowOffsets[_index].x;
- _y = _asCar->getY() + kCarShadowOffsets[_index].y;
- AnimatedSprite::update();
-}
-
-AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex)
- : AnimatedSprite(vm, 1100), _asCar(asCar) {
-
- SetUpdateHandler(&AsCommonCarTrackShadow::update);
- createShadowSurface1(shadowSurface, 0x0759129C, 100);
- startAnimation(0x0759129C, frameIndex, -1);
- _newStickFrameIndex = frameIndex;
-}
-
-void AsCommonCarTrackShadow::update() {
- _x = _asCar->getX();
- _y = _asCar->getY();
- AnimatedSprite::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 +585,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 +639,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 +658,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 +689,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 +797,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 +829,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 +845,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 +855,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 +905,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 +923,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 +948,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 +964,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 +1007,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 +1032,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 +1047,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 +1116,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..97b4f1cbea 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -26,7 +26,7 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module1600_sprites.h" // for Tracks
namespace Neverhood {
@@ -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);
@@ -49,38 +49,7 @@ protected:
void createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL);
};
-class SsCommonTrackShadowBackground : public StaticSprite {
-public:
- SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash);
-};
-
-class AsCommonCarShadow : public AnimatedSprite {
-public:
- AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index);
-protected:
- uint _index;
- AnimatedSprite *_asCar;
- uint32 _animFileHash;
- void update();
- void updateShadow();
-};
-
-class AsCommonCarConnectorShadow : public AnimatedSprite {
-public:
- AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index);
-protected:
- uint _index;
- Sprite *_asCar;
- void update();
-};
-
-class AsCommonCarTrackShadow : public AnimatedSprite {
-public:
- AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex);
-protected:
- Sprite *_asCar;
- void update();
-};
+class AsCommonCar;
class Scene2701 : public Scene {
public:
diff --git a/engines/neverhood/modules/module2700_sprites.cpp b/engines/neverhood/modules/module2700_sprites.cpp
new file mode 100644
index 0000000000..8dd2fa3461
--- /dev/null
+++ b/engines/neverhood/modules/module2700_sprites.cpp
@@ -0,0 +1,178 @@
+/* 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 "neverhood/modules/module2700_sprites.h"
+
+namespace Neverhood {
+
+static const NRect kScene2710ClipRect = { 0, 0, 626, 480 };
+
+static const uint32 kScene2710StaticSprites[] = {
+ 0x0D2016C0,
+ 0
+};
+
+static const NRect kScene2711ClipRect = { 0, 0, 521, 480 };
+
+static const uint32 kScene2711FileHashes1[] = {
+ 0,
+ 0x100801A1,
+ 0x201081A0,
+ 0x006800A4,
+ 0x40390120,
+ 0x000001B1,
+ 0x001000A1,
+ 0
+};
+
+static const uint32 kScene2711FileHashes2[] = {
+ 0,
+ 0x40403308,
+ 0x71403168,
+ 0x80423928,
+ 0x224131A8,
+ 0x50401328,
+ 0x70423328,
+ 0
+};
+
+static const uint32 kScene2711FileHashes3[] = {
+ 0,
+ 0x1088A021,
+ 0x108120E5,
+ 0x18A02321,
+ 0x148221A9,
+ 0x10082061,
+ 0x188820E1,
+ 0
+};
+
+static const NRect kScene2724ClipRect = { 0, 141, 640, 480 };
+
+static const uint32 kScene2724StaticSprites[] = {
+ 0xC20D00A5,
+ 0
+};
+
+static const NRect kScene2725ClipRect = { 0, 0, 640, 413 };
+
+static const uint32 kScene2725StaticSprites[] = {
+ 0xC20E00A5,
+ 0
+};
+
+static const NPoint kCarShadowOffsets[] = {
+ {-63, 3}, {-48, 40}, {-33, 58},
+ { 0, 65}, { 40, 53}, { 56, 27},
+ { 63, 0}, {-30, 26}, { 0, 30},
+ { 26, 25}
+};
+
+SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash)
+ : StaticSprite(vm, 0) {
+
+ loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0);
+}
+
+AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index)
+ : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index), _animFileHash(0) {
+
+ SetUpdateHandler(&AsCommonCarShadow::update);
+ createShadowSurface(shadowSurface, 211, 147, 100);
+ updateShadow();
+}
+
+void AsCommonCarShadow::update() {
+ updateShadow();
+ AnimatedSprite::update();
+}
+
+void AsCommonCarShadow::updateShadow() {
+ if (_asCar->getFrameIndex() != _currFrameIndex || _asCar->getCurrAnimFileHash() != _animFileHash) {
+ uint32 fileHash = _asCar->getCurrAnimFileHash();
+ if (fileHash == 0x35698F78 || fileHash == 0x192ADD30 || fileHash == 0x9C220DA4 ||
+ fileHash == 0x9966B138 || fileHash == 0xB579A77C || fileHash == 0xA86A9538 ||
+ fileHash == 0xD4220027 || fileHash == 0xD00A1364 || fileHash == 0xD4AA03A4 ||
+ fileHash == 0xF46A0324) {
+ startAnimation(fileHash, _asCar->getFrameIndex(), -1);
+ _newStickFrameIndex = _asCar->getFrameIndex();
+ }
+ _animFileHash = fileHash;
+ }
+ _x = _asCar->getX() + kCarShadowOffsets[_index].x;
+ _y = _asCar->getY() + kCarShadowOffsets[_index].y;
+ if (!_asCar->getVisible()) {
+ startAnimation(0x1209E09F, 0, -1);
+ _newStickFrameIndex = 0;
+ }
+ setDoDeltaX(_asCar->isDoDeltaX() ? 1 : 0);
+}
+
+AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index)
+ : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index) {
+
+ SetUpdateHandler(&AsCommonCarConnectorShadow::update);
+ createShadowSurface1(shadowSurface, 0x60281C10, 150);
+ startAnimation(0x60281C10, -1, -1);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
+
+void AsCommonCarConnectorShadow::update() {
+ _x = _asCar->getX() + kCarShadowOffsets[_index].x;
+ _y = _asCar->getY() + kCarShadowOffsets[_index].y;
+ AnimatedSprite::update();
+}
+
+AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex)
+ : AnimatedSprite(vm, 1100), _asCar(asCar) {
+
+ SetUpdateHandler(&AsCommonCarTrackShadow::update);
+ createShadowSurface1(shadowSurface, 0x0759129C, 100);
+ startAnimation(0x0759129C, frameIndex, -1);
+ _newStickFrameIndex = frameIndex;
+}
+
+void AsCommonCarTrackShadow::update() {
+ _x = _asCar->getX();
+ _y = _asCar->getY();
+ AnimatedSprite::update();
+}
+
+KmScene2732::KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2732::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4804:
+ GotoState(&Klaymen::stPeekInside);
+ break;
+ case 0x483C:
+ GotoState(&Klaymen::stPeekInsideReturn);
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2700_sprites.h b/engines/neverhood/modules/module2700_sprites.h
new file mode 100644
index 0000000000..394ba896a1
--- /dev/null
+++ b/engines/neverhood/modules/module2700_sprites.h
@@ -0,0 +1,74 @@
+/* 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 NEVERHOOD_MODULES_MODULE2700_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2700_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class SsCommonTrackShadowBackground : public StaticSprite {
+public:
+ SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash);
+};
+
+class AsCommonCarShadow : public AnimatedSprite {
+public:
+ AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index);
+protected:
+ uint _index;
+ AnimatedSprite *_asCar;
+ uint32 _animFileHash;
+ void update();
+ void updateShadow();
+};
+
+class AsCommonCarConnectorShadow : public AnimatedSprite {
+public:
+ AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index);
+protected:
+ uint _index;
+ Sprite *_asCar;
+ void update();
+};
+
+class AsCommonCarTrackShadow : public AnimatedSprite {
+public:
+ AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex);
+protected:
+ Sprite *_asCar;
+ void update();
+};
+
+class KmScene2732 : public Klaymen {
+public:
+ KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2700_SPRITES_H */
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index 183de8e6b2..d51515ce81 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -20,13 +20,15 @@
*
*/
-#include "neverhood/modules/module2800.h"
-#include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module1700.h"
-#include "neverhood/modules/module2200.h"
#include "neverhood/diskplayerscene.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/scene.h"
+#include "neverhood/modules/module1000_sprites.h"
+#include "neverhood/modules/module1200_sprites.h"
+#include "neverhood/modules/module1700_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
+#include "neverhood/modules/module2800.h"
+#include "neverhood/modules/module2800_sprites.h"
namespace Neverhood {
@@ -36,7 +38,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) {
@@ -58,7 +60,7 @@ Module2800::~Module2800() {
}
void Module2800::createScene(int sceneNum, int which) {
- debug("Module2800::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2800::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -206,6 +208,8 @@ void Module2800::createScene(int sceneNum, int which) {
break;
case 1001:
_vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0);
+ _musicResource->stop(0);
+ _currentMusicFileHash = 0;
createSmackerScene(0x00800801, true, true, false);
break;
}
@@ -224,7 +228,7 @@ void Module2800::updateScene() {
_musicResource = NULL;
}
_currentMusicFileHash = 0;
- }
+ }
if (_moduleResult == 1) {
createScene(2, 0);
} else if (_moduleResult == 2) {
@@ -251,7 +255,7 @@ void Module2800::updateScene() {
createScene(9, 0);
else if (_moduleResult == 5)
createScene(25, 0);
- else
+ else
createScene(0, 1);
break;
case 3:
@@ -294,31 +298,9 @@ void Module2800::updateScene() {
createScene(8, 0);
else if (_moduleResult == 6)
createScene(2, 6);
- else if (_moduleResult == 11)
- createScene(12, 0);
- else if (_moduleResult == 12)
- createScene(13, 0);
- else if (_moduleResult == 13)
- createScene(14, 0);
- else if (_moduleResult == 14)
- createScene(15, 0);
- else if (_moduleResult == 15)
- createScene(16, 0);
- else if (_moduleResult == 16)
- createScene(17, 0);
- else if (_moduleResult == 17)
- createScene(18, 0);
- else if (_moduleResult == 18)
- createScene(19, 0);
- else if (_moduleResult == 19)
- createScene(20, 0);
- else if (_moduleResult == 20)
- createScene(21, 0);
- else if (_moduleResult == 21)
- createScene(22, 0);
- else if (_moduleResult == 22)
- createScene(23, 0);
- else
+ else if (_moduleResult >= 11 && _moduleResult <= 22)
+ createScene(_moduleResult + 1, 0);
+ else
createScene(2, 4);
break;
case 10:
@@ -331,44 +313,22 @@ void Module2800::updateScene() {
createScene(26, 0);
else if (_moduleResult == 3)
createScene(9, 5);
- else
+ else
createScene(9, 1);
break;
case 12:
- createScene(9, 11);
- break;
case 13:
- createScene(9, 12);
- break;
case 14:
- createScene(9, 13);
- break;
case 15:
- createScene(9, 14);
- break;
case 16:
- createScene(9, 15);
- break;
case 17:
- createScene(9, 16);
- break;
case 18:
- createScene(9, 17);
- break;
case 19:
- createScene(9, 18);
- break;
case 20:
- createScene(9, 19);
- break;
case 21:
- createScene(9, 20);
- break;
case 22:
- createScene(9, 21);
- break;
case 23:
- createScene(9, 22);
+ createScene(9, _sceneNum - 1);
break;
case 24:
createScene(9, 3);
@@ -396,12 +356,11 @@ void Module2800::updateScene() {
}
void Module2800::updateMusic(bool halfVolume) {
-
uint32 newMusicFileHash = _vm->_gameModule->getCurrRadioMusicFileHash();
if (!_musicResource)
_musicResource = new MusicResource(_vm);
-
+
if (newMusicFileHash != _currentMusicFileHash) {
_currentMusicFileHash = newMusicFileHash;
if (_currentMusicFileHash != 0) {
@@ -469,7 +428,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 +439,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 +450,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 +462,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 +524,7 @@ Scene2802::~Scene2802() {
}
setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex);
}
-
+
void Scene2802::update() {
int prevTuneStatus = _currTuneStatus;
uint prevRadioMusicIndex = _currRadioMusicIndex;
@@ -577,7 +536,7 @@ void Scene2802::update() {
_currTuneStatus = 3;
else if (_currTuneStatus == 4)
_currTuneStatus = 6;
-
+
switch (_currTuneStatus) {
case 2:
if (_currRadioMusicIndex < 90)
@@ -607,24 +566,20 @@ void Scene2802::update() {
} else
_currTuneStatus = 0;
break;
-
+
}
if (prevRadioMusicIndex != _currRadioMusicIndex)
_smackerPlayer->gotoFrame(_currRadioMusicIndex);
-
+
if (prevTuneStatus != _currTuneStatus)
changeTuneStatus(prevTuneStatus, _currTuneStatus);
-
- //DEBUG>>>
- //debug("_currRadioMusicIndex = %d; V_GOOD_RADIO_MUSIC_INDEX = %d", _currRadioMusicIndex, getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX));
- //DEBUG<<<
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) {
@@ -691,157 +646,9 @@ void Scene2802::changeTuneStatus(int prevTuneStatus, int newTuneStatus) {
}
-AsScene2803LightCord::AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _fileHash1(fileHash1), _fileHash2(fileHash2),
- _isPulled(false), _isBusy(false) {
-
- createSurface(1010, 28, 379);
- SetUpdateHandler(&AnimatedSprite::update);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- _x = x;
- _y = y;
- stIdle();
-}
-
-uint32 AsScene2803LightCord::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x100D:
- if (!_isBusy && param.asInteger() == calcHash("ClickSwitch")) {
- sendMessage(_parentScene, 0x480F, 0);
- playSound(0, 0x4E1CA4A0);
- }
- break;
- case 0x480F:
- stPulled();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene2803LightCord::hmPulled(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2803LightCord::stPulled() {
- _isBusy = false;
- _isPulled = true;
- startAnimation(_fileHash2, 0, -1);
- SetMessageHandler(&AsScene2803LightCord::hmPulled);
- NextState(&AsScene2803LightCord::stIdle);
-}
-
-void AsScene2803LightCord::stIdle() {
- _isPulled = false;
- startAnimation(_fileHash1, 0, -1);
- SetMessageHandler(&AsScene2803LightCord::handleMessage);
-}
-
-void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
- _fileHash1 = fileHash1;
- _fileHash2 = fileHash2;
- if (_isPulled) {
- startAnimation(_fileHash2, _currFrameIndex, -1);
- _isBusy = true;
- } else {
- startAnimation(_fileHash1, 0, -1);
- }
-}
-
-AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2)
- : AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) {
-
- createSurface1(fileHash1, 100);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2803TestTubeOne::handleMessage);
- _x = 529;
- _y = 326;
-}
-
-uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- if (param.asInteger())
- startAnimation(_fileHash2, 0, -1);
- else
- startAnimation(_fileHash1, 0, -1);
- break;
- }
- return messageResult;
-}
-
-AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- createSurface(990, 68, 476);
- SetUpdateHandler(&AnimatedSprite::update);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- SetMessageHandler(&AsScene2803Rope::handleMessage);
- startAnimation(0x9D098C23, 35, 53);
- NextState(&AsScene2803Rope::stReleased);
- _x = x;
- _y = -276;
-}
-
-uint32 AsScene2803Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- startAnimation(0x9D098C23, 50, -1);
- SetMessageHandler(&AsScene2803Rope::hmReleased);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene2803Rope::hmReleased(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-void AsScene2803Rope::stReleased() {
- startAnimation(0x8258A030, 0, 1);
- NextState(&AsScene2803Rope::stHide);
-}
-
-void AsScene2803Rope::stHide() {
- stopAnimation();
- setVisible(false);
-}
-
Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteArea(0) {
-
+
static const uint32 kScene2803FileHashes1[] = {
0,
0x081000F1,
@@ -858,20 +665,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 {
@@ -879,13 +686,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);
@@ -900,7 +707,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;
@@ -910,12 +717,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();
@@ -1116,7 +923,7 @@ Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int wh
static const uint32 kScene2803SmallFileHashes2[] = {
0, 0x286800D4, 0x286806D4, 0x28680AD4
};
-
+
SetMessageHandler(&Scene2803Small::handleMessage);
loadDataResource(0x81120132);
@@ -1164,7 +971,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);
@@ -1354,379 +1161,6 @@ void Scene2803Small::updatePaletteArea(bool instantly) {
_palette->startFadeToPalette(instantly ? 0 : 12);
}
-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);
- SetMessageHandler(&SsScene2804RedButton::handleMessage);
- loadSound(0, 0x44241240);
-}
-
-void SsScene2804RedButton::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown) == 0) {
- setVisible(false);
- }
-}
-
-uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0 && !_parentScene->isWorking()) {
- playSound(0);
- setVisible(true);
- _countdown = 4;
- sendMessage(_parentScene, 0x2000, 0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm)
- : StaticSprite(vm, 900) {
-
- loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400);
- setVisible(false);
- SetMessageHandler(&SsScene2804LightCoil::handleMessage);
-}
-
-uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2002:
- setVisible(true);
- updatePosition();
- messageResult = 1;
- break;
- case 0x2003:
- setVisible(false);
- updatePosition();
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm)
- : StaticSprite(vm, 900) {
-
- loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400);
- setVisible(false);
- SetMessageHandler(&SsScene2804LightTarget::handleMessage);
-}
-
-uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2004:
- setVisible(true);
- updatePosition();
- messageResult = 1;
- break;
- case 0x2005:
- setVisible(false);
- updatePosition();
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm)
- : StaticSprite(vm, 900) {
-
- loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400);
- setVisible(false);
- loadSound(0, 0xCB36BA54);
-}
-
-void SsScene2804Flash::show() {
- setVisible(true);
- updatePosition();
- playSound(0);
-}
-
-SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm)
- : StaticSprite(vm, 900) {
-
- loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400);
- setVisible(false);
-}
-
-AsScene2804CrystalWaves::AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex)
- : AnimatedSprite(vm, 1100), _crystalIndex(crystalIndex) {
-
- static const NPoint kAsScene2804CrystalWavesPoints[] = {
- {323, 245},
- {387, 76},
- {454, 260},
- {527, 70}
- };
-
- _x = kAsScene2804CrystalWavesPoints[crystalIndex].x;
- _y = kAsScene2804CrystalWavesPoints[crystalIndex].y;
- createSurface1(0x840C41F0, 1200);
- if (crystalIndex & 1)
- setDoDeltaY(1);
- setVisible(false);
- _needRefresh = true;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&Sprite::handleMessage);
-}
-
-void AsScene2804CrystalWaves::show() {
- setVisible(true);
- startAnimation(0x840C41F0, 0, -1);
-}
-
-void AsScene2804CrystalWaves::hide() {
- setVisible(false);
- stopAnimation();
-}
-
-static const int16 kAsScene2804CrystalFrameNums[] = {
- 0, 6, 2, 8, 1, 10, 0, 0
-};
-
-static const uint32 kAsScene2804CrystalFileHashes[] = {
- 0x000540B0,
- 0x001280D0,
- 0x003D0010,
- 0x00620190,
- 0x00DC0290
-};
-
-AsScene2804Crystal::AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex)
- : AnimatedSprite(vm, 1100), _asCrystalWaves(asCrystalWaves), _crystalIndex(crystalIndex), _isShowing(false) {
-
- static const NPoint kAsScene2804CrystalPoints[] = {
- {204, 196},
- {272, 316},
- {334, 206},
- {410, 334},
- {470, 180}
- };
-
- _colorNum = (int16)getSubVar(VA_CURR_CRYSTAL_COLORS, crystalIndex);
- _isLightOn = getGlobalVar(V_SHRINK_LIGHTS_ON) != 0;
- if (_isLightOn) {
- _x = kAsScene2804CrystalPoints[crystalIndex].x;
- _y = kAsScene2804CrystalPoints[crystalIndex].y;
- createSurface1(0x108DFB12, 1200);
- startAnimation(0x108DFB12, kAsScene2804CrystalFrameNums[_colorNum], -1);
- _needRefresh = true;
- _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum];
- } else {
- _x = 320;
- _y = 240;
- createSurface1(kAsScene2804CrystalFileHashes[crystalIndex], 1200);
- startAnimation(kAsScene2804CrystalFileHashes[crystalIndex], _colorNum, -1);
- setVisible(false);
- _needRefresh = true;
- _newStickFrameIndex = _colorNum;
- }
- loadSound(0, 0x725294D4);
- SetUpdateHandler(&AnimatedSprite::update);
-}
-
-void AsScene2804Crystal::show() {
- if (!_isLightOn) {
- setVisible(true);
- _isShowing = true;
- if (_asCrystalWaves)
- _asCrystalWaves->show();
- playSound(0);
- }
-}
-
-void AsScene2804Crystal::hide() {
- if (!_isLightOn) {
- setVisible(false);
- _isShowing = false;
- if (_asCrystalWaves)
- _asCrystalWaves->hide();
- }
-}
-
-void AsScene2804Crystal::activate() {
- if (!_isShowing) {
- int16 frameNum = kAsScene2804CrystalFrameNums[_colorNum];
- _colorNum++;
- if (_colorNum >= 6)
- _colorNum = 0;
- if (_isLightOn) {
- startAnimation(0x108DFB12, frameNum, kAsScene2804CrystalFrameNums[_colorNum]);
- _playBackwards = kAsScene2804CrystalFrameNums[_colorNum] < _colorNum;
- _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum];
- } else {
- startAnimation(kAsScene2804CrystalFileHashes[_crystalIndex], _colorNum, -1);
- _newStickFrameIndex = _colorNum;
- }
- setSubVar(VA_CURR_CRYSTAL_COLORS, _crystalIndex, _colorNum);
- }
-}
-
-SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex)
- : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), _asCrystal(asCrystal), _crystalIndex(crystalIndex) {
-
- static const uint32 kSsScene2804CrystalButtonFileHashes1[] = {
- 0x911101B0,
- 0x22226001,
- 0x4444A362,
- 0x888925A4,
- 0x11122829
- };
-
- static const uint32 kSsScene2804CrystalButtonFileHashes2[] = {
- 0xB500A1A0,
- 0x6A012021,
- 0xD4022322,
- 0xA8042525,
- 0x5008292B
- };
-
- loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex],
- kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
- setVisible(false);
- loadSound(0, 0x44045140);
- SetUpdateHandler(&SsScene2804CrystalButton::update);
- SetMessageHandler(&SsScene2804CrystalButton::handleMessage);
-}
-
-void SsScene2804CrystalButton::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown) == 0) {
- setVisible(false);
- }
-}
-
-uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0 && !_parentScene->isWorking()) {
- playSound(0);
- setVisible(true);
- _countdown = 4;
- _asCrystal->activate();
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody)
- : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) {
-
- createSurface1(0x00494891, 1000);
- _x = 125;
- _y = 184;
- setVisible(false);
- _needRefresh = true;
- AnimatedSprite::updatePosition();
- loadSound(0, 0x6352F051);
- _vm->_soundMan->addSound(0xC5EA0B28, 0xEF56B094);
- SetUpdateHandler(&AsScene2804BeamCoil::update);
- SetMessageHandler(&AsScene2804BeamCoil::handleMessage);
-}
-
-AsScene2804BeamCoil::~AsScene2804BeamCoil() {
- _vm->_soundMan->deleteSoundGroup(0xC5EA0B28);
-}
-
-void AsScene2804BeamCoil::update() {
- updateAnim();
- updatePosition();
- if (_countdown != 0 && (--_countdown) == 0) {
- sendMessage(_parentScene, 0x2001, 0);
- }
-}
-
-uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2002:
- show();
- _countdown = 92;
- messageResult = 1;
- break;
- case 0x2003:
- hide();
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void AsScene2804BeamCoil::show() {
- _ssBeamCoilBody->setVisible(true);
- setVisible(true);
- startAnimation(0x00494891, 0, -1);
- playSound(0);
- SetMessageHandler(&AsScene2804BeamCoil::hmBeaming);
- NextState(&AsScene2804BeamCoil::stBeaming);
-}
-
-void AsScene2804BeamCoil::hide() {
- stopAnimation();
- SetMessageHandler(&AsScene2804BeamCoil::handleMessage);
- setVisible(false);
- _ssBeamCoilBody->setVisible(false);
- _vm->_soundMan->stopSound(0xEF56B094);
-}
-
-void AsScene2804BeamCoil::stBeaming() {
- startAnimation(0x00494891, 93, -1);
- NextState(&AsScene2804BeamCoil::stBeaming);
- _vm->_soundMan->playSoundLooping(0xEF56B094);
-}
-
-uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1400) {
-
- createSurface1(0x03842000, 1000);
- _x = 475;
- _y = 278;
- setVisible(false);
- _needRefresh = true;
- updatePosition();
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2804BeamTarget::handleMessage);
-}
-
-uint32 AsScene2804BeamTarget::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2004:
- setVisible(true);
- startAnimation(0x03842000, 0, -1);
- messageResult = 1;
- break;
- case 0x2005:
- setVisible(false);
- stopAnimation();
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown1(0), _countdown2(0), _countdown3(0),
_beamStatus(0), _isSolved(false), _isWorking(false) {
@@ -1754,7 +1188,7 @@ Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which)
_asTarget = insertSprite<AsScene2804BeamTarget>();
_ssFlash = insertSprite<SsScene2804Flash>();
}
-
+
_ssRedButton = insertSprite<SsScene2804RedButton>(this);
addCollisionSprite(_ssRedButton);
@@ -1801,7 +1235,7 @@ uint32 Scene2804::handleMessage(int messageNum, const MessageParam &param, Entit
void Scene2804::update() {
Scene::update();
-
+
if (_countdown1 != 0 && (--_countdown1) == 0) {
leaveScene(0);
}
@@ -1840,7 +1274,7 @@ void Scene2804::update() {
Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene2805::handleMessage);
setBackground(0x08021E04);
@@ -1896,53 +1330,23 @@ uint32 Scene2805::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200) {
-
- createSurface1(0x04211490, 1200);
- _x = 378;
- _y = 423;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2806Spew::handleMessage);
- setDoDeltaX(1);
- setVisible(false);
-}
-
-uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- playSound(0, 0x48640244);
- startAnimation(0x04211490, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
Sprite *tempSprite;
- which = 3;
-
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;
@@ -1957,7 +1361,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();
@@ -2033,7 +1437,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;
@@ -2042,12 +1446,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) {
@@ -2117,267 +1521,6 @@ static const uint32 kClass428FileHashes[] = {
0x40800711
};
-static const int kClass428Countdowns1[] = {
- 18, 16, 10, 0
-};
-
-static const int kClass428Countdowns2[] = {
- 9, 9, 8, 8, 5, 5, 0, 0
-};
-
-static const uint32 kClass490FileHashes[] = {
- 0x08100071,
- 0x24084215,
- 0x18980A10
-};
-
-static const int16 kClass490FrameIndices1[] = {
- 0, 8, 15, 19
-};
-
-static const int16 kClass490FrameIndices2[] = {
- 0, 4, 8, 11, 15, 17, 19, 0
-};
-
-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);
- SetMessageHandler(&SsScene2808Dispenser::handleMessage);
-}
-
-void SsScene2808Dispenser::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown) == 0) {
- setVisible(false);
- }
-}
-
-uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- sendMessage(_parentScene, 0x2000, _testTubeIndex);
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void SsScene2808Dispenser::startCountdown(int index) {
- setVisible(true);
- updatePosition();
- if (_testTubeSetNum == 0) {
- _countdown = kClass428Countdowns1[index];
- } else {
- _countdown = kClass428Countdowns2[index];
- }
-}
-
-AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser)
- : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _ssDispenser(ssDispenser), _fillLevel(0) {
-
- if (testTubeSetNum == 0) {
- _x = 504;
- _y = 278;
- } else {
- setDoDeltaX(1);
- _x = 136;
- _y = 278;
- }
-
- createSurface1(kClass490FileHashes[testTubeIndex], 1100);
-
- if (testTubeSetNum == 0) {
- loadSound(0, 0x30809E2D);
- loadSound(1, 0x72811E2D);
- loadSound(2, 0x78B01625);
- } else {
- loadSound(3, 0x70A41E0C);
- loadSound(4, 0x50205E2D);
- loadSound(5, 0xF8621E2D);
- loadSound(6, 0xF1A03C2D);
- 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) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- fill();
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void AsScene2808TestTube::fill() {
- if ((int)_fillLevel < _testTubeSetNum * 3 + 3) {
- if (_testTubeSetNum == 0) {
- playSound(_fillLevel);
- setVisible(true);
- startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], kClass490FrameIndices1[_fillLevel + 1]);
- _newStickFrameIndex = kClass490FrameIndices1[_fillLevel + 1];
- } else {
- playSound(3 + _fillLevel);
- setVisible(true);
- startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], kClass490FrameIndices2[_fillLevel + 1]);
- _newStickFrameIndex = kClass490FrameIndices2[_fillLevel + 1];
- }
- _ssDispenser->startCountdown(_fillLevel);
- _fillLevel++;
- }
-}
-
-void AsScene2808TestTube::flush() {
- if (_fillLevel != 0) {
- if (_testTubeSetNum == 0) {
- startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], -1);
- } else {
- startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], -1);
- }
- _newStickFrameIndex = 0;
- _playBackwards = true;
- setVisible(true);
- }
-}
-
-AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum)
- : AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) {
-
- loadSound(0, 0xE18D1F30);
- _x = 320;
- _y = 240;
- if (_testTubeSetNum == 1)
- setDoDeltaX(1);
- createSurface1(0x040900D0, 1300);
- startAnimation(0x040900D0, 0, -1);
- _needRefresh = true;
- _newStickFrameIndex = 0;
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2808Handle::handleMessage);
- AnimatedSprite::updatePosition();
-}
-
-uint32 AsScene2808Handle::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (!_isActivated) {
- sendMessage(_parentScene, 0x2001, 0);
- playSound(0);
- activate();
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene2808Handle::hmActivating(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2808Handle::activate() {
- startAnimation(0x040900D0, 0, -1);
- SetMessageHandler(&AsScene2808Handle::hmActivating);
- NextState(&AsScene2808Handle::stActivated);
- _isActivated = true;
- _newStickFrameIndex = -1;
-}
-
-void AsScene2808Handle::stActivated() {
- stopAnimation();
- sendMessage(_parentScene, 0x2002, 0);
-}
-
-AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum) {
-
- if (testTubeSetNum == 0) {
- _x = 312;
- _y = 444;
- } else {
- _x = 328;
- _y = 444;
- }
- createSurface1(0xB8414818, 1200);
- startAnimation(0xB8414818, 0, -1);
- setVisible(false);
- _newStickFrameIndex = 0;
- _needRefresh = true;
- loadSound(0, 0x6389B652);
- SetUpdateHandler(&AnimatedSprite::update);
- AnimatedSprite::updatePosition();
-}
-
-uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2808Flow::start() {
- startAnimation(0xB8414818, 0, -1);
- setVisible(true);
- SetMessageHandler(&AsScene2808Flow::hmFlowing);
- NextState(&AsScene2808Flow::stKeepFlowing);
- playSound(0);
-}
-
-void AsScene2808Flow::stKeepFlowing() {
- startAnimation(0xB8414818, 1, -1);
- NextState(&AsScene2808Flow::stKeepFlowing);
-}
-
-AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum)
- : AnimatedSprite(vm, 800), _countdown(1) {
-
- _x = 320;
- _y = 240;
- if (testTubeSetNum == 1)
- setDoDeltaX(1);
- createSurface1(0x804C2404, 800);
- SetUpdateHandler(&AsScene2808LightEffect::update);
- _needRefresh = true;
- AnimatedSprite::updatePosition();
-}
-
-void AsScene2808LightEffect::update() {
- if (_countdown != 0 && (--_countdown) == 0) {
- int16 frameIndex = _vm->_rnd->getRandomNumber(3 - 1);
- startAnimation(0x804C2404, frameIndex, frameIndex);
- updateAnim();
- updatePosition();
- _countdown = _vm->_rnd->getRandomNumber(3 - 1) + 1;
- }
-}
-
Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _testTubeSetNum(which), _leaveResult(0), _isFlowing(false) {
@@ -2387,7 +1530,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
_vm->gameModule()->initTestTubes1Puzzle();
else
_vm->gameModule()->initTestTubes2Puzzle();
-
+
SetMessageHandler(&Scene2808::handleMessage);
SetUpdateHandler(&Scene2808::update);
@@ -2406,7 +1549,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
_asTestTubes[testTubeIndex] = insertSprite<AsScene2808TestTube>(which, testTubeIndex, ssDispenser);
addCollisionSprite(_asTestTubes[testTubeIndex]);
}
-
+
insertScreenMouse(kScene2808FileHashes2[which]);
}
@@ -2445,18 +1588,6 @@ uint32 Scene2808::handleMessage(int messageNum, const MessageParam &param, Entit
}
void Scene2808::update() {
-
- // DEBUG>>> Show correct values
- #if 1
- debug("---------------");
- if (_testTubeSetNum == 0)
- debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2));
- else
- debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2));
- debug("%03d %03d %03d", _asTestTubes[0]->getFillLevel(), _asTestTubes[1]->getFillLevel(), _asTestTubes[2]->getFillLevel());
- #endif
- // DEBUG<<<
-
Scene::update();
if (_countdown != 0 && (--_countdown) == 0) {
leaveScene(_leaveResult);
@@ -2484,45 +1615,17 @@ bool Scene2808::isAnyTestTubeFilled() {
_asTestTubes[2]->getFillLevel() > 0;
}
-AsScene2809Spew::AsScene2809Spew(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1200) {
-
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2809Spew::handleMessage);
- createSurface1(0x04211490, 1200);
- _x = 262;
- _y = 423;
- setDoDeltaX(0);
- setVisible(false);
-}
-
-uint32 AsScene2809Spew::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- playSound(0, 0x48640244);
- startAnimation(0x04211490, 0, -1);
- setVisible(true);
- break;
- case 0x3002:
- stopAnimation();
- setVisible(false);
- break;
- }
- return messageResult;
-}
-
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);
@@ -2553,7 +1656,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);
@@ -2628,35 +1731,7 @@ void Scene2809::findClosestPoint() {
_pointIndex = index;
_palette->addPalette(kScene2809PaletteFileHashes[index], 0, 64, 0);
}
-
-}
-
-AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
- : AnimatedSprite(vm, 1100) {
-
- createSurface(990, 68, 476);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2810Rope::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- _x = x;
- _y = -276;
- startAnimation(0x9D098C23, 35, 53);
-}
-uint32 AsScene2810Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- startAnimation(0x9D098C23, 35, 53);
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
}
Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which)
@@ -2665,7 +1740,7 @@ Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which)
Sprite *tempSprite;
SetMessageHandler(&Scene2810::handleMessage);
-
+
setBackground(0x26508804);
setPalette(0x26508804);
insertScreenMouse(0x0880026D);
@@ -2701,7 +1776,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);
@@ -2880,112 +1955,17 @@ uint32 Scene2810::handleMessage(int messageNum, const MessageParam &param, Entit
return messageResult;
}
-AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 1100) {
-
- createSurface1(0x20DA08A0, 1200);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2812Winch::handleMessage);
- setVisible(false);
- _x = 280;
- _y = 184;
-}
-
-AsScene2812Winch::~AsScene2812Winch() {
- _vm->_soundMan->deleteSoundGroup(0x00B000E2);
-}
-
-uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- startAnimation(0x20DA08A0, 0, -1);
- setVisible(true);
- _vm->_soundMan->addSound(0x00B000E2, 0xC874EE6C);
- _vm->_soundMan->playSoundLooping(0xC874EE6C);
- break;
- case 0x3002:
- startAnimation(0x20DA08A0, 7, -1);
- break;
- }
- return messageResult;
-}
-
-AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
- createSurface(990, 68, 476);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene2812Rope::handleMessage);
- SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
- startAnimation(0xAE080551, 0, -1);
- _x = 334;
- _y = 201;
-}
-
-uint32 AsScene2812Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x4806:
- setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
- stRopingDown();
- break;
- case 0x482A:
- sendMessage(_parentScene, 0x1022, 990);
- break;
- case 0x482B:
- sendMessage(_parentScene, 0x1022, 1010);
- break;
- }
- return messageResult;
-}
-
-uint32 AsScene2812Rope::hmRopingDown(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene2812Rope::stRopingDown() {
- sendMessage(_parentScene, 0x4806, 0);
- startAnimation(0x9D098C23, 0, -1);
- SetMessageHandler(&AsScene2812Rope::hmRopingDown);
-}
-
-AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm)
- : AnimatedSprite(vm, 0x805D0029, 100, 320, 240) {
-
- SetMessageHandler(&AsScene2812TrapDoor::handleMessage);
- _newStickFrameIndex = 0;
-}
-
-uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2000:
- startAnimation(0x805D0029, 0, -1);
- playSound(0, 0xEA005F40);
- _newStickFrameIndex = STICK_LAST_FRAME;
- break;
- }
- return messageResult;
-}
-
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);
@@ -3001,7 +1981,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);
@@ -3041,9 +2021,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() {
@@ -3138,7 +2118,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);
@@ -3158,7 +2138,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..26e44bc543 100644
--- a/engines/neverhood/modules/module2800.h
+++ b/engines/neverhood/modules/module2800.h
@@ -70,38 +70,7 @@ protected:
void changeTuneStatus(int prevTuneStatus, int newTuneStatus);
};
-class AsScene2803LightCord : public AnimatedSprite {
-public:
- AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y);
- void stPulled();
- void stIdle();
- void setFileHashes(uint32 fileHash1, uint32 fileHash2);
-protected:
- Scene *_parentScene;
- uint32 _fileHash1, _fileHash2;
- bool _isPulled, _isBusy;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmPulled(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2803TestTubeOne : public AnimatedSprite {
-public:
- AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2);
-protected:
- uint32 _fileHash1, _fileHash2;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2803Rope : public AnimatedSprite {
-public:
- AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmReleased(int messageNum, const MessageParam &param, Entity *sender);
- void stReleased();
- void stHide();
-};
+class AsScene2803LightCord;
class Scene2803 : public Scene {
public:
@@ -158,101 +127,8 @@ protected:
void updatePaletteArea(bool instantly);
};
-class Scene2804;
-
-class SsScene2804RedButton : public StaticSprite {
-public:
- SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene);
-protected:
- Scene2804 *_parentScene;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene2804LightCoil : public StaticSprite {
-public:
- SsScene2804LightCoil(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene2804BeamCoilBody : public StaticSprite {
-public:
- SsScene2804BeamCoilBody(NeverhoodEngine *vm);
-};
-
-class SsScene2804LightTarget : public StaticSprite {
-public:
- SsScene2804LightTarget(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene2804Flash : public StaticSprite {
-public:
- SsScene2804Flash(NeverhoodEngine *vm);
- void show();
-};
-
-class AsScene2804CrystalWaves : public AnimatedSprite {
-public:
- AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex);
- void show();
- void hide();
-protected:
- uint _crystalIndex;
-};
-
-class AsScene2804Crystal : public AnimatedSprite {
-public:
- AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex);
- void show();
- void hide();
- void activate();
- int16 getColorNum() const { return _colorNum; }
-protected:
- AsScene2804CrystalWaves *_asCrystalWaves;
- uint _crystalIndex;
- int16 _colorNum;
- bool _isLightOn;
- bool _isShowing;
-};
-
-class SsScene2804CrystalButton : public StaticSprite {
-public:
- SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex);
-protected:
- Scene2804 *_parentScene;
- AsScene2804Crystal *_asCrystal;
- uint _crystalIndex;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2804BeamCoil : public AnimatedSprite {
-public:
- AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody);
- virtual ~AsScene2804BeamCoil();
-protected:
- Scene *_parentScene;
- SsScene2804BeamCoilBody *_ssBeamCoilBody;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void show();
- void hide();
- void stBeaming();
- uint32 hmBeaming(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2804BeamTarget : public AnimatedSprite {
-public:
- AsScene2804BeamTarget(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class SsScene2804Flash;
+class AsScene2804Crystal;
class Scene2804 : public Scene {
public:
@@ -284,13 +160,6 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class AsScene2806Spew : public AnimatedSprite {
-public:
- AsScene2806Spew(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2806 : public Scene {
public:
Scene2806(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -315,63 +184,8 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-class SsScene2808Dispenser : public StaticSprite {
-public:
- SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex);
- void startCountdown(int index);
-protected:
- Scene *_parentScene;
- int _countdown;
- int _testTubeSetNum, _testTubeIndex;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2808TestTube : public AnimatedSprite {
-public:
- AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser);
- void fill();
- void flush();
- uint32 getFillLevel() const { return _fillLevel; }
-protected:
- SsScene2808Dispenser *_ssDispenser;
- int _testTubeSetNum;
- uint32 _fillLevel;
- int _testTubeIndex;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2808Handle : public AnimatedSprite {
-public:
- AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
- void activate();
- void stActivated();
-protected:
- Scene *_parentScene;
- int _testTubeSetNum;
- bool _isActivated;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmActivating(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2808Flow : public AnimatedSprite {
-public:
- AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
- void start();
- void stKeepFlowing();
-protected:
- Scene *_parentScene;
- int _testTubeSetNum;
- uint32 hmFlowing(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2808LightEffect : public AnimatedSprite {
-public:
- AsScene2808LightEffect(NeverhoodEngine *vm, int which);
-protected:
- int _countdown;
- void update();
-};
+class AsScene2808Flow;
+class AsScene2808TestTube;
class Scene2808 : public Scene {
public:
@@ -389,13 +203,6 @@ protected:
bool isAnyTestTubeFilled();
};
-class AsScene2809Spew : public AnimatedSprite {
-public:
- AsScene2809Spew(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2809 : public Scene {
public:
Scene2809(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -408,19 +215,11 @@ protected:
Sprite *_sprite3;
Sprite *_sprite4;
Sprite *_asSpew;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
void findClosestPoint();
};
-class AsScene2810Rope : public AnimatedSprite {
-public:
- AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2810 : public Scene {
public:
Scene2810(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -440,31 +239,6 @@ protected:
void insertKlaymenLadder();
};
-class AsScene2812Winch : public AnimatedSprite {
-public:
- AsScene2812Winch(NeverhoodEngine *vm);
- virtual ~AsScene2812Winch();
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2812Rope : public AnimatedSprite {
-public:
- AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene);
-protected:
- Scene *_parentScene;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- uint32 hmRopingDown(int messageNum, const MessageParam &param, Entity *sender);
- void stRopingDown();
-};
-
-class AsScene2812TrapDoor : public AnimatedSprite {
-public:
- AsScene2812TrapDoor(NeverhoodEngine *vm);
-protected:
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
class Scene2812 : public Scene {
public:
Scene2812(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2800_sprites.cpp b/engines/neverhood/modules/module2800_sprites.cpp
new file mode 100644
index 0000000000..a600c55dd3
--- /dev/null
+++ b/engines/neverhood/modules/module2800_sprites.cpp
@@ -0,0 +1,1626 @@
+/* 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 "neverhood/modules/module2800.h"
+#include "neverhood/modules/module2800_sprites.h"
+
+namespace Neverhood {
+
+AsScene2803LightCord::AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _fileHash1(fileHash1), _fileHash2(fileHash2),
+ _isPulled(false), _isBusy(false) {
+
+ createSurface(1010, 28, 379);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ _x = x;
+ _y = y;
+ stIdle();
+}
+
+uint32 AsScene2803LightCord::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (!_isBusy && param.asInteger() == calcHash("ClickSwitch")) {
+ sendMessage(_parentScene, 0x480F, 0);
+ playSound(0, 0x4E1CA4A0);
+ }
+ break;
+ case 0x480F:
+ stPulled();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene2803LightCord::hmPulled(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2803LightCord::stPulled() {
+ _isBusy = false;
+ _isPulled = true;
+ startAnimation(_fileHash2, 0, -1);
+ SetMessageHandler(&AsScene2803LightCord::hmPulled);
+ NextState(&AsScene2803LightCord::stIdle);
+}
+
+void AsScene2803LightCord::stIdle() {
+ _isPulled = false;
+ startAnimation(_fileHash1, 0, -1);
+ SetMessageHandler(&AsScene2803LightCord::handleMessage);
+}
+
+void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
+ _fileHash1 = fileHash1;
+ _fileHash2 = fileHash2;
+ if (_isPulled) {
+ startAnimation(_fileHash2, _currFrameIndex, -1);
+ _isBusy = true;
+ } else {
+ startAnimation(_fileHash1, 0, -1);
+ }
+}
+
+AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2)
+ : AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) {
+
+ createSurface1(fileHash1, 100);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2803TestTubeOne::handleMessage);
+ _x = 529;
+ _y = 326;
+}
+
+uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ if (param.asInteger())
+ startAnimation(_fileHash2, 0, -1);
+ else
+ startAnimation(_fileHash1, 0, -1);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(990, 68, 476);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ SetMessageHandler(&AsScene2803Rope::handleMessage);
+ startAnimation(0x9D098C23, 35, 53);
+ NextState(&AsScene2803Rope::stReleased);
+ _x = x;
+ _y = -276;
+}
+
+uint32 AsScene2803Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ startAnimation(0x9D098C23, 50, -1);
+ SetMessageHandler(&AsScene2803Rope::hmReleased);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene2803Rope::hmReleased(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2803Rope::stReleased() {
+ startAnimation(0x8258A030, 0, 1);
+ NextState(&AsScene2803Rope::stHide);
+}
+
+void AsScene2803Rope::stHide() {
+ stopAnimation();
+ setVisible(false);
+}
+
+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);
+ SetMessageHandler(&SsScene2804RedButton::handleMessage);
+ loadSound(0, 0x44241240);
+}
+
+void SsScene2804RedButton::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown) == 0) {
+ setVisible(false);
+ }
+}
+
+uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0 && !_parentScene->isWorking()) {
+ playSound(0);
+ setVisible(true);
+ _countdown = 4;
+ sendMessage(_parentScene, 0x2000, 0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm)
+ : StaticSprite(vm, 900) {
+
+ loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400);
+ setVisible(false);
+ SetMessageHandler(&SsScene2804LightCoil::handleMessage);
+}
+
+uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2002:
+ setVisible(true);
+ updatePosition();
+ messageResult = 1;
+ break;
+ case 0x2003:
+ setVisible(false);
+ updatePosition();
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm)
+ : StaticSprite(vm, 900) {
+
+ loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400);
+ setVisible(false);
+ SetMessageHandler(&SsScene2804LightTarget::handleMessage);
+}
+
+uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2004:
+ setVisible(true);
+ updatePosition();
+ messageResult = 1;
+ break;
+ case 0x2005:
+ setVisible(false);
+ updatePosition();
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm)
+ : StaticSprite(vm, 900) {
+
+ loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400);
+ setVisible(false);
+ loadSound(0, 0xCB36BA54);
+}
+
+void SsScene2804Flash::show() {
+ setVisible(true);
+ updatePosition();
+ playSound(0);
+}
+
+SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm)
+ : StaticSprite(vm, 900) {
+
+ loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400);
+ setVisible(false);
+}
+
+AsScene2804CrystalWaves::AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex)
+ : AnimatedSprite(vm, 1100), _crystalIndex(crystalIndex) {
+
+ static const NPoint kAsScene2804CrystalWavesPoints[] = {
+ {323, 245},
+ {387, 76},
+ {454, 260},
+ {527, 70}
+ };
+
+ _x = kAsScene2804CrystalWavesPoints[crystalIndex].x;
+ _y = kAsScene2804CrystalWavesPoints[crystalIndex].y;
+ createSurface1(0x840C41F0, 1200);
+ if (crystalIndex & 1)
+ setDoDeltaY(1);
+ setVisible(false);
+ _needRefresh = true;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+void AsScene2804CrystalWaves::show() {
+ setVisible(true);
+ startAnimation(0x840C41F0, 0, -1);
+}
+
+void AsScene2804CrystalWaves::hide() {
+ setVisible(false);
+ stopAnimation();
+}
+
+static const int16 kAsScene2804CrystalFrameNums[] = {
+ 0, 6, 2, 8, 1, 10, 0, 0
+};
+
+static const uint32 kAsScene2804CrystalFileHashes[] = {
+ 0x000540B0,
+ 0x001280D0,
+ 0x003D0010,
+ 0x00620190,
+ 0x00DC0290
+};
+
+AsScene2804Crystal::AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex)
+ : AnimatedSprite(vm, 1100), _asCrystalWaves(asCrystalWaves), _crystalIndex(crystalIndex), _isShowing(false) {
+
+ static const NPoint kAsScene2804CrystalPoints[] = {
+ {204, 196},
+ {272, 316},
+ {334, 206},
+ {410, 334},
+ {470, 180}
+ };
+
+ _colorNum = (int16)getSubVar(VA_CURR_CRYSTAL_COLORS, crystalIndex);
+ _isLightOn = getGlobalVar(V_SHRINK_LIGHTS_ON) != 0;
+ if (_isLightOn) {
+ _x = kAsScene2804CrystalPoints[crystalIndex].x;
+ _y = kAsScene2804CrystalPoints[crystalIndex].y;
+ createSurface1(0x108DFB12, 1200);
+ startAnimation(0x108DFB12, kAsScene2804CrystalFrameNums[_colorNum], -1);
+ _needRefresh = true;
+ _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum];
+ } else {
+ _x = 320;
+ _y = 240;
+ createSurface1(kAsScene2804CrystalFileHashes[crystalIndex], 1200);
+ startAnimation(kAsScene2804CrystalFileHashes[crystalIndex], _colorNum, -1);
+ setVisible(false);
+ _needRefresh = true;
+ _newStickFrameIndex = _colorNum;
+ }
+ loadSound(0, 0x725294D4);
+ SetUpdateHandler(&AnimatedSprite::update);
+}
+
+void AsScene2804Crystal::show() {
+ if (!_isLightOn) {
+ setVisible(true);
+ _isShowing = true;
+ if (_asCrystalWaves)
+ _asCrystalWaves->show();
+ playSound(0);
+ }
+}
+
+void AsScene2804Crystal::hide() {
+ if (!_isLightOn) {
+ setVisible(false);
+ _isShowing = false;
+ if (_asCrystalWaves)
+ _asCrystalWaves->hide();
+ }
+}
+
+void AsScene2804Crystal::activate() {
+ if (!_isShowing) {
+ int16 frameNum = kAsScene2804CrystalFrameNums[_colorNum];
+ _colorNum++;
+ if (_colorNum >= 6)
+ _colorNum = 0;
+ if (_isLightOn) {
+ startAnimation(0x108DFB12, frameNum, kAsScene2804CrystalFrameNums[_colorNum]);
+ _playBackwards = kAsScene2804CrystalFrameNums[_colorNum] < _colorNum;
+ _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum];
+ } else {
+ startAnimation(kAsScene2804CrystalFileHashes[_crystalIndex], _colorNum, -1);
+ _newStickFrameIndex = _colorNum;
+ }
+ setSubVar(VA_CURR_CRYSTAL_COLORS, _crystalIndex, _colorNum);
+ }
+}
+
+SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex)
+ : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), _asCrystal(asCrystal), _crystalIndex(crystalIndex) {
+
+ static const uint32 kSsScene2804CrystalButtonFileHashes1[] = {
+ 0x911101B0,
+ 0x22226001,
+ 0x4444A362,
+ 0x888925A4,
+ 0x11122829
+ };
+
+ static const uint32 kSsScene2804CrystalButtonFileHashes2[] = {
+ 0xB500A1A0,
+ 0x6A012021,
+ 0xD4022322,
+ 0xA8042525,
+ 0x5008292B
+ };
+
+ loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex],
+ kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
+ setVisible(false);
+ loadSound(0, 0x44045140);
+ SetUpdateHandler(&SsScene2804CrystalButton::update);
+ SetMessageHandler(&SsScene2804CrystalButton::handleMessage);
+}
+
+void SsScene2804CrystalButton::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown) == 0) {
+ setVisible(false);
+ }
+}
+
+uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0 && !_parentScene->isWorking()) {
+ playSound(0);
+ setVisible(true);
+ _countdown = 4;
+ _asCrystal->activate();
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody)
+ : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) {
+
+ createSurface1(0x00494891, 1000);
+ _x = 125;
+ _y = 184;
+ setVisible(false);
+ _needRefresh = true;
+ AnimatedSprite::updatePosition();
+ loadSound(0, 0x6352F051);
+ _vm->_soundMan->addSound(0xC5EA0B28, 0xEF56B094);
+ SetUpdateHandler(&AsScene2804BeamCoil::update);
+ SetMessageHandler(&AsScene2804BeamCoil::handleMessage);
+}
+
+AsScene2804BeamCoil::~AsScene2804BeamCoil() {
+ _vm->_soundMan->deleteSoundGroup(0xC5EA0B28);
+}
+
+void AsScene2804BeamCoil::update() {
+ updateAnim();
+ updatePosition();
+ if (_countdown != 0 && (--_countdown) == 0) {
+ sendMessage(_parentScene, 0x2001, 0);
+ }
+}
+
+uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2002:
+ show();
+ _countdown = 92;
+ messageResult = 1;
+ break;
+ case 0x2003:
+ hide();
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2804BeamCoil::show() {
+ _ssBeamCoilBody->setVisible(true);
+ setVisible(true);
+ startAnimation(0x00494891, 0, -1);
+ playSound(0);
+ SetMessageHandler(&AsScene2804BeamCoil::hmBeaming);
+ NextState(&AsScene2804BeamCoil::stBeaming);
+}
+
+void AsScene2804BeamCoil::hide() {
+ stopAnimation();
+ SetMessageHandler(&AsScene2804BeamCoil::handleMessage);
+ setVisible(false);
+ _ssBeamCoilBody->setVisible(false);
+ _vm->_soundMan->stopSound(0xEF56B094);
+}
+
+void AsScene2804BeamCoil::stBeaming() {
+ startAnimation(0x00494891, 93, -1);
+ NextState(&AsScene2804BeamCoil::stBeaming);
+ _vm->_soundMan->playSoundLooping(0xEF56B094);
+}
+
+uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1400) {
+
+ createSurface1(0x03842000, 1000);
+ _x = 475;
+ _y = 278;
+ setVisible(false);
+ _needRefresh = true;
+ updatePosition();
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2804BeamTarget::handleMessage);
+}
+
+uint32 AsScene2804BeamTarget::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2004:
+ setVisible(true);
+ startAnimation(0x03842000, 0, -1);
+ messageResult = 1;
+ break;
+ case 0x2005:
+ setVisible(false);
+ stopAnimation();
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200) {
+
+ createSurface1(0x04211490, 1200);
+ _x = 378;
+ _y = 423;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2806Spew::handleMessage);
+ setDoDeltaX(1);
+ setVisible(false);
+}
+
+uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ playSound(0, 0x48640244);
+ startAnimation(0x04211490, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+static const uint32 kScene2808FileHashes1[] = {
+ 0x90B0392,
+ 0x90B0192
+};
+
+static const uint32 kScene2808FileHashes2[] = {
+ 0xB0396098,
+ 0xB0196098
+};
+
+static const uint32 kClass428FileHashes[] = {
+ 0x140022CA,
+ 0x4C30A602,
+ 0xB1633402,
+ 0x12982135,
+ 0x0540B728,
+ 0x002A81E3,
+ 0x08982841,
+ 0x10982841,
+ 0x20982841,
+ 0x40982841,
+ 0x80982841,
+ 0x40800711
+};
+
+static const int kClass428Countdowns1[] = {
+ 18, 16, 10, 0
+};
+
+static const int kClass428Countdowns2[] = {
+ 9, 9, 8, 8, 5, 5, 0, 0
+};
+
+static const uint32 kClass490FileHashes[] = {
+ 0x08100071,
+ 0x24084215,
+ 0x18980A10
+};
+
+static const int16 kClass490FrameIndices1[] = {
+ 0, 8, 15, 19
+};
+
+static const int16 kClass490FrameIndices2[] = {
+ 0, 4, 8, 11, 15, 17, 19, 0
+};
+
+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);
+ SetMessageHandler(&SsScene2808Dispenser::handleMessage);
+}
+
+void SsScene2808Dispenser::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown) == 0) {
+ setVisible(false);
+ }
+}
+
+uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ sendMessage(_parentScene, 0x2000, _testTubeIndex);
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void SsScene2808Dispenser::startCountdown(int index) {
+ setVisible(true);
+ updatePosition();
+ if (_testTubeSetNum == 0) {
+ _countdown = kClass428Countdowns1[index];
+ } else {
+ _countdown = kClass428Countdowns2[index];
+ }
+}
+
+AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser)
+ : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _ssDispenser(ssDispenser), _fillLevel(0) {
+
+ if (testTubeSetNum == 0) {
+ _x = 504;
+ _y = 278;
+ } else {
+ setDoDeltaX(1);
+ _x = 136;
+ _y = 278;
+ }
+
+ createSurface1(kClass490FileHashes[testTubeIndex], 1100);
+
+ if (testTubeSetNum == 0) {
+ loadSound(0, 0x30809E2D);
+ loadSound(1, 0x72811E2D);
+ loadSound(2, 0x78B01625);
+ } else {
+ loadSound(3, 0x70A41E0C);
+ loadSound(4, 0x50205E2D);
+ loadSound(5, 0xF8621E2D);
+ loadSound(6, 0xF1A03C2D);
+ 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) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ fill();
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2808TestTube::fill() {
+ if ((int)_fillLevel < _testTubeSetNum * 3 + 3) {
+ if (_testTubeSetNum == 0) {
+ playSound(_fillLevel);
+ setVisible(true);
+ startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], kClass490FrameIndices1[_fillLevel + 1]);
+ _newStickFrameIndex = kClass490FrameIndices1[_fillLevel + 1];
+ } else {
+ playSound(3 + _fillLevel);
+ setVisible(true);
+ startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], kClass490FrameIndices2[_fillLevel + 1]);
+ _newStickFrameIndex = kClass490FrameIndices2[_fillLevel + 1];
+ }
+ _ssDispenser->startCountdown(_fillLevel);
+ _fillLevel++;
+ }
+}
+
+void AsScene2808TestTube::flush() {
+ if (_fillLevel != 0) {
+ if (_testTubeSetNum == 0) {
+ startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], -1);
+ } else {
+ startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], -1);
+ }
+ _newStickFrameIndex = 0;
+ _playBackwards = true;
+ setVisible(true);
+ }
+}
+
+AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum)
+ : AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) {
+
+ loadSound(0, 0xE18D1F30);
+ _x = 320;
+ _y = 240;
+ if (_testTubeSetNum == 1)
+ setDoDeltaX(1);
+ createSurface1(0x040900D0, 1300);
+ startAnimation(0x040900D0, 0, -1);
+ _needRefresh = true;
+ _newStickFrameIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2808Handle::handleMessage);
+ AnimatedSprite::updatePosition();
+}
+
+uint32 AsScene2808Handle::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isActivated) {
+ sendMessage(_parentScene, 0x2001, 0);
+ playSound(0);
+ activate();
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene2808Handle::hmActivating(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2808Handle::activate() {
+ startAnimation(0x040900D0, 0, -1);
+ SetMessageHandler(&AsScene2808Handle::hmActivating);
+ NextState(&AsScene2808Handle::stActivated);
+ _isActivated = true;
+ _newStickFrameIndex = -1;
+}
+
+void AsScene2808Handle::stActivated() {
+ stopAnimation();
+ sendMessage(_parentScene, 0x2002, 0);
+}
+
+AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum) {
+
+ if (testTubeSetNum == 0) {
+ _x = 312;
+ _y = 444;
+ } else {
+ _x = 328;
+ _y = 444;
+ }
+ createSurface1(0xB8414818, 1200);
+ startAnimation(0xB8414818, 0, -1);
+ setVisible(false);
+ _newStickFrameIndex = 0;
+ _needRefresh = true;
+ loadSound(0, 0x6389B652);
+ SetUpdateHandler(&AnimatedSprite::update);
+ AnimatedSprite::updatePosition();
+}
+
+uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2808Flow::start() {
+ startAnimation(0xB8414818, 0, -1);
+ setVisible(true);
+ SetMessageHandler(&AsScene2808Flow::hmFlowing);
+ NextState(&AsScene2808Flow::stKeepFlowing);
+ playSound(0);
+}
+
+void AsScene2808Flow::stKeepFlowing() {
+ startAnimation(0xB8414818, 1, -1);
+ NextState(&AsScene2808Flow::stKeepFlowing);
+}
+
+AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum)
+ : AnimatedSprite(vm, 800), _countdown(1) {
+
+ _x = 320;
+ _y = 240;
+ if (testTubeSetNum == 1)
+ setDoDeltaX(1);
+ createSurface1(0x804C2404, 800);
+ SetUpdateHandler(&AsScene2808LightEffect::update);
+ _needRefresh = true;
+ AnimatedSprite::updatePosition();
+}
+
+void AsScene2808LightEffect::update() {
+ if (_countdown != 0 && (--_countdown) == 0) {
+ int16 frameIndex = _vm->_rnd->getRandomNumber(3 - 1);
+ startAnimation(0x804C2404, frameIndex, frameIndex);
+ updateAnim();
+ updatePosition();
+ _countdown = _vm->_rnd->getRandomNumber(3 - 1) + 1;
+ }
+}
+
+AsScene2809Spew::AsScene2809Spew(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1200) {
+
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2809Spew::handleMessage);
+ createSurface1(0x04211490, 1200);
+ _x = 262;
+ _y = 423;
+ setDoDeltaX(0);
+ setVisible(false);
+}
+
+uint32 AsScene2809Spew::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ playSound(0, 0x48640244);
+ startAnimation(0x04211490, 0, -1);
+ setVisible(true);
+ break;
+ case 0x3002:
+ stopAnimation();
+ setVisible(false);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(990, 68, 476);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2810Rope::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ _x = x;
+ _y = -276;
+ startAnimation(0x9D098C23, 35, 53);
+}
+
+uint32 AsScene2810Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ startAnimation(0x9D098C23, 35, 53);
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1100) {
+
+ createSurface1(0x20DA08A0, 1200);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2812Winch::handleMessage);
+ setVisible(false);
+ _x = 280;
+ _y = 184;
+}
+
+AsScene2812Winch::~AsScene2812Winch() {
+ _vm->_soundMan->deleteSoundGroup(0x00B000E2);
+}
+
+uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ startAnimation(0x20DA08A0, 0, -1);
+ setVisible(true);
+ _vm->_soundMan->addSound(0x00B000E2, 0xC874EE6C);
+ _vm->_soundMan->playSoundLooping(0xC874EE6C);
+ break;
+ case 0x3002:
+ startAnimation(0x20DA08A0, 7, -1);
+ break;
+ }
+ return messageResult;
+}
+
+AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+ createSurface(990, 68, 476);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene2812Rope::handleMessage);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+ startAnimation(0xAE080551, 0, -1);
+ _x = 334;
+ _y = 201;
+}
+
+uint32 AsScene2812Rope::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x4806:
+ setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
+ stRopingDown();
+ break;
+ case 0x482A:
+ sendMessage(_parentScene, 0x1022, 990);
+ break;
+ case 0x482B:
+ sendMessage(_parentScene, 0x1022, 1010);
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene2812Rope::hmRopingDown(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene2812Rope::stRopingDown() {
+ sendMessage(_parentScene, 0x4806, 0);
+ startAnimation(0x9D098C23, 0, -1);
+ SetMessageHandler(&AsScene2812Rope::hmRopingDown);
+}
+
+AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 0x805D0029, 100, 320, 240) {
+
+ SetMessageHandler(&AsScene2812TrapDoor::handleMessage);
+ _newStickFrameIndex = 0;
+}
+
+uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2000:
+ startAnimation(0x805D0029, 0, -1);
+ playSound(0, 0xEA005F40);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2801::KmScene2801(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+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);
+}
+
+uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4803:
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stJumpToGrab);
+ break;
+ case 0x4804:
+ if (param.asInteger() == 3)
+ GotoState(&Klaymen::stFinishGrow);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stPullCord);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else
+ GotoState(&Klaymen::stWonderAboutHalf);
+ break;
+ case 0x482E:
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4838:
+ GotoState(&Klaymen::stJumpToGrabRelease);
+ break;
+ }
+ return 0;
+}
+
+KmScene2803Small::KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ _dataResource.load(0x81120132);
+}
+
+uint32 KmScene2803Small::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToXSmall(param.asPoint().x);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stStandIdleSmall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfterSmall);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalfSmall);
+ else
+ GotoState(&Klaymen::stWonderAboutSmall);
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStepSmall);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stWalkToFront2Small);
+ else
+ GotoState(&Klaymen::stWalkToFrontSmall);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToBackHalfSmall);
+ else if (param.asInteger() == 2)
+ GotoState(&Klaymen::stTurnToBackWalkSmall);
+ else
+ GotoState(&Klaymen::stTurnToBackSmall);
+ break;
+ case 0x4830:
+ GotoState(&KmScene2803Small::stShrink);
+ break;
+ }
+ return 0;
+}
+
+uint32 KmScene2803Small::hmShrink(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x80C110B5)
+ sendMessage(_parentScene, 0x482A, 0);
+ else if (param.asInteger() == 0x33288344)
+ playSound(2, 0x10688664);
+ break;
+ }
+ return messageResult;
+}
+
+void KmScene2803Small::stShrink() {
+ _busyStatus = 0;
+ _acceptInput = false;
+ playSound(0, 0x4C69EA53);
+ startAnimation(0x1AE88904, 0, -1);
+ SetUpdateHandler(&Klaymen::update);
+ SetMessageHandler(&KmScene2803Small::hmShrink);
+ SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
+}
+
+KmScene2805::KmScene2805(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam &param) {
+ uint32 messageResult = 0;
+ switch (messageNum) {
+ case 0x2000:
+ _isSittingInTeleporter = param.asInteger() != 0;
+ messageResult = 1;
+ break;
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stSitIdleTeleporter);
+ else
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481D:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stTurnToUseInTeleporter);
+ break;
+ case 0x481E:
+ if (_isSittingInTeleporter)
+ GotoState(&Klaymen::stReturnFromUseInTeleporter);
+ break;
+ case 0x4834:
+ GotoState(&Klaymen::stStepOver);
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2000, 1);
+ _isSittingInTeleporter = true;
+ GotoState(&Klaymen::stSitInTeleporter);
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2000, 0);
+ _isSittingInTeleporter = false;
+ GotoState(&Klaymen::stGetUpFromTeleporter);
+ break;
+ case 0x483D:
+ teleporterAppear(0xDE284B74);
+ break;
+ case 0x483E:
+ teleporterDisappear(0xD82A4094);
+ break;
+ }
+ return messageResult;
+}
+
+KmScene2806::KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
+ bool needsLargeSurface, NRect *clipRects, uint clipRectsCount)
+ : Klaymen(vm, parentScene, x, y) {
+
+ if (needsLargeSurface) {
+ NDimensions dimensions = _animResource.loadSpriteDimensions(0x2838C010);
+ delete _surface;
+ createSurface(1000, dimensions.width, dimensions.height);
+ loadSound(3, 0x58E0C341);
+ loadSound(4, 0x40A00342);
+ loadSound(5, 0xD0A1C348);
+ loadSound(6, 0x166FC6E0);
+ loadSound(7, 0x00018040);
+ }
+
+ _dataResource.load(0x98182003);
+ _surface->setClipRects(clipRects, clipRectsCount);
+}
+
+uint32 KmScene2806::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ startWalkToX(440, true);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stPullCord);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x4831:
+ GotoState(&Klaymen::stGrow);
+ break;
+ case 0x4832:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stDrinkPotion);
+ else
+ GotoState(&Klaymen::stUseTube);
+ break;
+ }
+ return 0;
+}
+
+KmScene2809::KmScene2809(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
+ bool needsLargeSurface, NRect *clipRects, uint clipRectsCount)
+ : Klaymen(vm, parentScene, x, y) {
+
+ if (needsLargeSurface) {
+ NDimensions dimensions = _animResource.loadSpriteDimensions(0x2838C010);
+ delete _surface;
+ createSurface(1000, dimensions.width, dimensions.height);
+ loadSound(3, 0x58E0C341);
+ loadSound(4, 0x40A00342);
+ loadSound(5, 0xD0A1C348);
+ loadSound(6, 0x166FC6E0);
+ loadSound(7, 0x00018040);
+ }
+
+ _dataResource.load(0x1830009A);
+ _surface->setClipRects(clipRects, clipRectsCount);
+}
+
+uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4804:
+ startWalkToX(226, true);
+ break;
+ case 0x480D:
+ GotoState(&Klaymen::stPullCord);
+ break;
+ case 0x4816:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stPressButtonSide);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x4831:
+ GotoState(&Klaymen::stGrow);
+ break;
+ case 0x4832:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stDrinkPotion);
+ else
+ GotoState(&Klaymen::stUseTube);
+ break;
+ }
+ return 0;
+}
+
+KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToXSmall(param.asPoint().x);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stStandIdleSmall);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfterSmall);
+ else if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalfSmall);
+ else
+ GotoState(&Klaymen::stWonderAboutSmall);
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStepSmall);
+ else
+ GotoState(&Klaymen::stWalkToFrontSmall);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToBackHalfSmall);
+ else
+ GotoState(&Klaymen::stTurnToBackSmall);
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+KmScene2810::KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, uint clipRectsCount)
+ : Klaymen(vm, parentScene, x, y) {
+
+ _surface->setClipRects(clipRects, clipRectsCount);
+}
+
+uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4803:
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stJumpToGrab);
+ break;
+ case 0x4804:
+ if (param.asInteger() == 3)
+ GotoState(&Klaymen::stFinishGrow);
+ break;
+ case 0x4812:
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x4818:
+ startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481F:
+ if (param.asInteger() == 0)
+ GotoState(&Klaymen::stWonderAboutHalf);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWonderAboutAfter);
+ else if (param.asInteger() == 3)
+ GotoState(&Klaymen::stTurnToUseHalf);
+ else if (param.asInteger() == 4)
+ GotoState(&Klaymen::stTurnAwayFromUse);
+ else if (param.asInteger() == 5)
+ GotoState(&Klaymen::stTurnToUseExt);
+ else
+ GotoState(&Klaymen::stWonderAbout);
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2000, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2001, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x4824:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = _dataResource.getPoint(param.asInteger()).y;
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4825:
+ sendMessage(_parentScene, 0x2000, 0);
+ _destY = _dataResource.getPoint(param.asInteger()).y;
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x4837:
+ stopWalking();
+ break;
+ }
+ return 0;
+}
+
+KmScene2812::KmScene2812(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : Klaymen(vm, parentScene, x, y) {
+
+ // Empty
+}
+
+uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ startWalkToX(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ GotoState(&Klaymen::stTryStandIdle);
+ break;
+ case 0x4805:
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stJumpToGrabFall);
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2)
+ GotoState(&Klaymen::stPickUpNeedle);
+ else if (param.asInteger() == 1)
+ GotoState(&Klaymen::stPickUpTube);
+ else
+ GotoState(&Klaymen::stPickUpGeneric);
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ gotoNextStateExt();
+ break;
+ case 0x481A:
+ GotoState(&Klaymen::stInsertDisk);
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0)
+ startWalkToXDistance(param.asPoint().y, param.asPoint().x);
+ else
+ startWalkToAttachedSpriteXDistance(param.asPoint().x);
+ break;
+ case 0x481D:
+ GotoState(&Klaymen::stTurnToUse);
+ break;
+ case 0x481E:
+ GotoState(&Klaymen::stReturnFromUse);
+ break;
+ case 0x4820:
+ sendMessage(_parentScene, 0x2001, 0);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
+ break;
+ case 0x4821:
+ sendMessage(_parentScene, 0x2001, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderDown);
+ break;
+ case 0x4822:
+ sendMessage(_parentScene, 0x2001, 0);
+ _destY = param.asInteger();
+ GotoState(&Klaymen::stStartClimbLadderUp);
+ break;
+ case 0x4823:
+ sendMessage(_parentScene, 0x2002, 0);
+ GotoState(&Klaymen::stClimbLadderHalf);
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ gotoNextStateExt();
+ break;
+ case 0x482E:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stWalkToFrontNoStep);
+ else
+ GotoState(&Klaymen::stWalkToFront);
+ break;
+ case 0x482F:
+ if (param.asInteger() == 1)
+ GotoState(&Klaymen::stTurnToFront);
+ else
+ GotoState(&Klaymen::stTurnToBack);
+ break;
+ case 0x483F:
+ startSpecialWalkRight(param.asInteger());
+ break;
+ case 0x4840:
+ startSpecialWalkLeft(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2800_sprites.h b/engines/neverhood/modules/module2800_sprites.h
new file mode 100644
index 0000000000..91f26d7849
--- /dev/null
+++ b/engines/neverhood/modules/module2800_sprites.h
@@ -0,0 +1,337 @@
+/* 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 NEVERHOOD_MODULES_MODULE2800_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2800_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsScene2803LightCord : public AnimatedSprite {
+public:
+ AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y);
+ void stPulled();
+ void stIdle();
+ void setFileHashes(uint32 fileHash1, uint32 fileHash2);
+protected:
+ Scene *_parentScene;
+ uint32 _fileHash1, _fileHash2;
+ bool _isPulled, _isBusy;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmPulled(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2803TestTubeOne : public AnimatedSprite {
+public:
+ AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2);
+protected:
+ uint32 _fileHash1, _fileHash2;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2803Rope : public AnimatedSprite {
+public:
+ AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmReleased(int messageNum, const MessageParam &param, Entity *sender);
+ void stReleased();
+ void stHide();
+};
+
+class Scene2804;
+
+class SsScene2804RedButton : public StaticSprite {
+public:
+ SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene);
+protected:
+ Scene2804 *_parentScene;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene2804LightCoil : public StaticSprite {
+public:
+ SsScene2804LightCoil(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene2804BeamCoilBody : public StaticSprite {
+public:
+ SsScene2804BeamCoilBody(NeverhoodEngine *vm);
+};
+
+class SsScene2804LightTarget : public StaticSprite {
+public:
+ SsScene2804LightTarget(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene2804Flash : public StaticSprite {
+public:
+ SsScene2804Flash(NeverhoodEngine *vm);
+ void show();
+};
+
+class AsScene2804CrystalWaves : public AnimatedSprite {
+public:
+ AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex);
+ void show();
+ void hide();
+protected:
+ uint _crystalIndex;
+};
+
+class AsScene2804Crystal : public AnimatedSprite {
+public:
+ AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex);
+ void show();
+ void hide();
+ void activate();
+ int16 getColorNum() const { return _colorNum; }
+protected:
+ AsScene2804CrystalWaves *_asCrystalWaves;
+ uint _crystalIndex;
+ int16 _colorNum;
+ bool _isLightOn;
+ bool _isShowing;
+};
+
+class SsScene2804CrystalButton : public StaticSprite {
+public:
+ SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex);
+protected:
+ Scene2804 *_parentScene;
+ AsScene2804Crystal *_asCrystal;
+ uint _crystalIndex;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2804BeamCoil : public AnimatedSprite {
+public:
+ AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody);
+ virtual ~AsScene2804BeamCoil();
+protected:
+ Scene *_parentScene;
+ SsScene2804BeamCoilBody *_ssBeamCoilBody;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void show();
+ void hide();
+ void stBeaming();
+ uint32 hmBeaming(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2804BeamTarget : public AnimatedSprite {
+public:
+ AsScene2804BeamTarget(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2806Spew : public AnimatedSprite {
+public:
+ AsScene2806Spew(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene2808Dispenser : public StaticSprite {
+public:
+ SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex);
+ void startCountdown(int index);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ int _testTubeSetNum, _testTubeIndex;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2808TestTube : public AnimatedSprite {
+public:
+ AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser);
+ void fill();
+ void flush();
+ uint32 getFillLevel() const { return _fillLevel; }
+protected:
+ SsScene2808Dispenser *_ssDispenser;
+ int _testTubeSetNum;
+ uint32 _fillLevel;
+ int _testTubeIndex;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2808Handle : public AnimatedSprite {
+public:
+ AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
+ void activate();
+ void stActivated();
+protected:
+ Scene *_parentScene;
+ int _testTubeSetNum;
+ bool _isActivated;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmActivating(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2808Flow : public AnimatedSprite {
+public:
+ AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
+ void start();
+ void stKeepFlowing();
+protected:
+ Scene *_parentScene;
+ int _testTubeSetNum;
+ uint32 hmFlowing(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2808LightEffect : public AnimatedSprite {
+public:
+ AsScene2808LightEffect(NeverhoodEngine *vm, int which);
+protected:
+ int _countdown;
+ void update();
+};
+
+class AsScene2809Spew : public AnimatedSprite {
+public:
+ AsScene2809Spew(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2810Rope : public AnimatedSprite {
+public:
+ AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2812Winch : public AnimatedSprite {
+public:
+ AsScene2812Winch(NeverhoodEngine *vm);
+ virtual ~AsScene2812Winch();
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2812Rope : public AnimatedSprite {
+public:
+ AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmRopingDown(int messageNum, const MessageParam &param, Entity *sender);
+ void stRopingDown();
+};
+
+class AsScene2812TrapDoor : public AnimatedSprite {
+public:
+ AsScene2812TrapDoor(NeverhoodEngine *vm);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class KmScene2801 : public Klaymen {
+public:
+ KmScene2801(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2803 : public Klaymen {
+public:
+ KmScene2803(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2803Small : public Klaymen {
+public:
+ KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ void stShrink();
+ uint32 hmShrink(int messageNum, const MessageParam &param, Entity *sender);
+
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2805 : public Klaymen {
+public:
+ KmScene2805(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2806 : public Klaymen {
+public:
+ KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
+ bool needsLargeSurface, NRect *clipRects, uint clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2809 : public Klaymen {
+public:
+ KmScene2809(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
+ bool needsLargeSurface, NRect *clipRects, uint clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2810Small : public Klaymen {
+public:
+ KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2810 : public Klaymen {
+public:
+ KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y,
+ NRect *clipRects, uint clipRectsCount);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+class KmScene2812 : public Klaymen {
+public:
+ KmScene2812(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2800_SPRITES_H */
diff --git a/engines/neverhood/modules/module2900.cpp b/engines/neverhood/modules/module2900.cpp
index bd95b82f4c..bb0b69f35d 100644
--- a/engines/neverhood/modules/module2900.cpp
+++ b/engines/neverhood/modules/module2900.cpp
@@ -21,7 +21,7 @@
*/
#include "neverhood/modules/module2900.h"
-#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module2900_sprites.h"
#include "neverhood/modules/module1100.h"
#include "neverhood/modules/module1300.h"
#include "neverhood/modules/module1700.h"
@@ -36,13 +36,13 @@ Module2900::Module2900(NeverhoodEngine *vm, Module *parentModule, int which)
if (which >= 0)
setGlobalVar(V_TELEPORTER_WHICH, which);
-
+
createScene(0, 0);
}
void Module2900::createScene(int sceneNum, int which) {
- debug("Module2900::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module2900::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
case 0:
@@ -141,211 +141,6 @@ static const uint32 kScene2901FileHashes2[] = {
0x08030029
};
-static const uint32 kSsScene2901LocationButtonFileHashes[] = {
- 0x2311326A,
- 0x212323AC,
- 0x10098138,
- 0x25213167,
- 0x1119A363,
- 0x94452612,
- 0x39464212,
- 0x01860450,
- 0x53002104,
- 0x58E68412,
- 0x18600300,
- 0xB650A890,
- 0x2452A7C4,
- 0xA0232748,
- 0x08862B02,
- 0x2491E648,
- 0x0010EB46,
- 0x214C8A11,
- 0x16A31921,
- 0x0AC33A00,
- 0x238028AA,
- 0x26737A21,
- 0x063039A8,
- 0x51286C60,
- 0x464006B4,
- 0x42242538,
- 0x20716010,
- 0x4A2000AE,
- 0x225124A6,
- 0x28E82E45,
- 0x58652C04,
- 0xC82210A4,
- 0x62A84060,
- 0xC0693CB4,
- 0x22212C64,
- 0x5034EA71
-};
-
-static const NPoint kSsScene2901LocationButtonPoints[] = {
- {525, 120}, {576, 149}, {587, 205},
- {538, 232}, {484, 205}, {479, 153}
-};
-
-static const uint32 kSsScene2901LocationButtonLightFileHashes1[] = {
- 0x03136246,
- 0x2106216E,
- 0x4025A13A,
- 0x21816927,
- 0x110B2202,
- 0xCC0522B2,
- 0x3CC24258,
- 0x59C600F0,
- 0x534A2480,
- 0x50E61019,
- 0x34400150,
- 0x225BA090,
- 0xB059AFC4,
- 0xE093A741,
- 0x0086BF09,
- 0x3281E760,
- 0xA048AB42,
- 0x20649C01,
- 0x14611904,
- 0x26E33850,
- 0x23A52A68,
- 0xA2733024,
- 0x10203880,
- 0x1B2DE860,
- 0x0644A6EC,
- 0x426E20BC,
- 0x80292014,
- 0x4360B02E,
- 0x22742664,
- 0x98682705,
- 0x0925B82C,
- 0x5C2918A4,
- 0xD2284920,
- 0x41083CA6,
- 0x6824A864,
- 0x50266B10
-};
-
-static const uint32 kSsScene2901LocationButtonLightFileHashes2[] = {
- 0x43C46D4C,
- 0x43C4AD4C,
- 0x43C52D4C,
- 0x43C62D4C,
- 0x43C02D4C,
- 0x43CC2D4C
-};
-
-static const uint32 kSsScene2901BrokenButtonFileHashes[] = {
- 0x3081BD3A,
- 0xD3443003,
- 0x0786A320,
- 0xE3A22029,
- 0x61611814,
- 0x425848E2
-};
-
-static const uint32 kSsScene2901BigButtonFileHashes[] = {
- 0x010D7748,
- 0x9D02019A,
- 0x351A2F43,
- 0x448138E5,
- 0x02788CF0,
- 0x71718024
-};
-
-SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index)
- : 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);
- loadSound(0, 0x440430C0);
- SetUpdateHandler(&SsScene2901LocationButton::update);
- SetMessageHandler(&SsScene2901LocationButton::handleMessage);
-}
-
-void SsScene2901LocationButton::update() {
- updatePosition();
- if (_countdown1 != 0 && (--_countdown1) == 0) {
- setVisible(false);
- }
-}
-
-uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown1 == 0) {
- playSound(0);
- setVisible(true);
- _countdown1 = 4;
- sendMessage(_parentScene, 0x2001, _index);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-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]);
-}
-
-void SsScene2901LocationButtonLight::show() {
- playSound(0);
- setVisible(true);
- updatePosition();
-}
-
-void SsScene2901LocationButtonLight::hide() {
- setVisible(false);
- updatePosition();
-}
-
-SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which)
- : StaticSprite(vm, 900) {
-
- loadSprite(kSsScene2901BrokenButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 900);
-}
-
-SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which)
- : StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) {
-
- loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400);
- _collisionBounds.set(62, 94, 322, 350);
- setVisible(false);
- loadSound(0, 0xF3D420C8);
- SetUpdateHandler(&SsScene2901BigButton::update);
- SetMessageHandler(&SsScene2901BigButton::handleMessage);
-}
-
-void SsScene2901BigButton::update() {
- updatePosition();
- if (_countdown1 != 0 && (--_countdown1) == 0) {
- setVisible(false);
- sendMessage(_parentScene, 0x2000, 0);
- }
-}
-
-uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown1 == 0) {
- playSound(0);
- setVisible(true);
- _countdown1 = 4;
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _currLocationButtonNum(which), _selectedButtonNum(which),
_currWhirlButtonNum(0), _prevWhirlButtonNum(0), _countdown1(1), _skipCountdown(0), _blinkOn(0) {
@@ -361,7 +156,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 +164,7 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which)
_ssLocationButtonLights[i] = insertSprite<SsScene2901LocationButtonLight>(_currLocationButtonNum, i);
}
}
-
+
if (_isButton2Broken)
insertSprite<SsScene2901BrokenButton>(_currLocationButtonNum);
@@ -377,10 +172,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..5f6ed29a12 100644
--- a/engines/neverhood/modules/module2900.h
+++ b/engines/neverhood/modules/module2900.h
@@ -42,41 +42,7 @@ protected:
void updateMusic(bool halfVolume);
};
-class SsScene2901LocationButton : public StaticSprite {
-public:
- SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index);
-protected:
- Scene *_parentScene;
- uint _index;
- int _countdown1;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene2901LocationButtonLight : public StaticSprite {
-public:
- SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index);
- void show();
- void hide();
-protected:
- uint _index;
-};
-
-class SsScene2901BrokenButton : public StaticSprite {
-public:
- SsScene2901BrokenButton(NeverhoodEngine *vm, int which);
-};
-
-class SsScene2901BigButton : public StaticSprite {
-public:
- SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which);
-protected:
- Scene *_parentScene;
- int _which;
- int _countdown1;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class SsScene2901LocationButtonLight;
class Scene2901 : public Scene {
public:
diff --git a/engines/neverhood/modules/module2900_sprites.cpp b/engines/neverhood/modules/module2900_sprites.cpp
new file mode 100644
index 0000000000..59780b33a0
--- /dev/null
+++ b/engines/neverhood/modules/module2900_sprites.cpp
@@ -0,0 +1,232 @@
+/* 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 "neverhood/modules/module2900_sprites.h"
+
+namespace Neverhood {
+
+static const uint32 kSsScene2901LocationButtonFileHashes[] = {
+ 0x2311326A,
+ 0x212323AC,
+ 0x10098138,
+ 0x25213167,
+ 0x1119A363,
+ 0x94452612,
+ 0x39464212,
+ 0x01860450,
+ 0x53002104,
+ 0x58E68412,
+ 0x18600300,
+ 0xB650A890,
+ 0x2452A7C4,
+ 0xA0232748,
+ 0x08862B02,
+ 0x2491E648,
+ 0x0010EB46,
+ 0x214C8A11,
+ 0x16A31921,
+ 0x0AC33A00,
+ 0x238028AA,
+ 0x26737A21,
+ 0x063039A8,
+ 0x51286C60,
+ 0x464006B4,
+ 0x42242538,
+ 0x20716010,
+ 0x4A2000AE,
+ 0x225124A6,
+ 0x28E82E45,
+ 0x58652C04,
+ 0xC82210A4,
+ 0x62A84060,
+ 0xC0693CB4,
+ 0x22212C64,
+ 0x5034EA71
+};
+
+static const NPoint kSsScene2901LocationButtonPoints[] = {
+ {525, 120}, {576, 149}, {587, 205},
+ {538, 232}, {484, 205}, {479, 153}
+};
+
+static const uint32 kSsScene2901LocationButtonLightFileHashes1[] = {
+ 0x03136246,
+ 0x2106216E,
+ 0x4025A13A,
+ 0x21816927,
+ 0x110B2202,
+ 0xCC0522B2,
+ 0x3CC24258,
+ 0x59C600F0,
+ 0x534A2480,
+ 0x50E61019,
+ 0x34400150,
+ 0x225BA090,
+ 0xB059AFC4,
+ 0xE093A741,
+ 0x0086BF09,
+ 0x3281E760,
+ 0xA048AB42,
+ 0x20649C01,
+ 0x14611904,
+ 0x26E33850,
+ 0x23A52A68,
+ 0xA2733024,
+ 0x10203880,
+ 0x1B2DE860,
+ 0x0644A6EC,
+ 0x426E20BC,
+ 0x80292014,
+ 0x4360B02E,
+ 0x22742664,
+ 0x98682705,
+ 0x0925B82C,
+ 0x5C2918A4,
+ 0xD2284920,
+ 0x41083CA6,
+ 0x6824A864,
+ 0x50266B10
+};
+
+static const uint32 kSsScene2901LocationButtonLightFileHashes2[] = {
+ 0x43C46D4C,
+ 0x43C4AD4C,
+ 0x43C52D4C,
+ 0x43C62D4C,
+ 0x43C02D4C,
+ 0x43CC2D4C
+};
+
+static const uint32 kSsScene2901BrokenButtonFileHashes[] = {
+ 0x3081BD3A,
+ 0xD3443003,
+ 0x0786A320,
+ 0xE3A22029,
+ 0x61611814,
+ 0x425848E2
+};
+
+static const uint32 kSsScene2901BigButtonFileHashes[] = {
+ 0x010D7748,
+ 0x9D02019A,
+ 0x351A2F43,
+ 0x448138E5,
+ 0x02788CF0,
+ 0x71718024
+};
+
+SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index)
+ : 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);
+ loadSound(0, 0x440430C0);
+ SetUpdateHandler(&SsScene2901LocationButton::update);
+ SetMessageHandler(&SsScene2901LocationButton::handleMessage);
+}
+
+void SsScene2901LocationButton::update() {
+ updatePosition();
+ if (_countdown1 != 0 && (--_countdown1) == 0) {
+ setVisible(false);
+ }
+}
+
+uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown1 == 0) {
+ playSound(0);
+ setVisible(true);
+ _countdown1 = 4;
+ sendMessage(_parentScene, 0x2001, _index);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+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]);
+}
+
+void SsScene2901LocationButtonLight::show() {
+ playSound(0);
+ setVisible(true);
+ updatePosition();
+}
+
+void SsScene2901LocationButtonLight::hide() {
+ setVisible(false);
+ updatePosition();
+}
+
+SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which)
+ : StaticSprite(vm, 900) {
+
+ loadSprite(kSsScene2901BrokenButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 900);
+}
+
+SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which)
+ : StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) {
+
+ loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400);
+ _collisionBounds.set(62, 94, 322, 350);
+ setVisible(false);
+ loadSound(0, 0xF3D420C8);
+ SetUpdateHandler(&SsScene2901BigButton::update);
+ SetMessageHandler(&SsScene2901BigButton::handleMessage);
+}
+
+void SsScene2901BigButton::update() {
+ updatePosition();
+ if (_countdown1 != 0 && (--_countdown1) == 0) {
+ setVisible(false);
+ sendMessage(_parentScene, 0x2000, 0);
+ }
+}
+
+uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown1 == 0) {
+ playSound(0);
+ setVisible(true);
+ _countdown1 = 4;
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2900_sprites.h b/engines/neverhood/modules/module2900_sprites.h
new file mode 100644
index 0000000000..9f7df502e1
--- /dev/null
+++ b/engines/neverhood/modules/module2900_sprites.h
@@ -0,0 +1,72 @@
+/* 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 NEVERHOOD_MODULES_MODULE2900_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2900_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+// Module2900
+
+class SsScene2901LocationButton : public StaticSprite {
+public:
+ SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index);
+protected:
+ Scene *_parentScene;
+ uint _index;
+ int _countdown1;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene2901LocationButtonLight : public StaticSprite {
+public:
+ SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index);
+ void show();
+ void hide();
+protected:
+ uint _index;
+};
+
+class SsScene2901BrokenButton : public StaticSprite {
+public:
+ SsScene2901BrokenButton(NeverhoodEngine *vm, int which);
+};
+
+class SsScene2901BigButton : public StaticSprite {
+public:
+ SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which);
+protected:
+ Scene *_parentScene;
+ int _which;
+ int _countdown1;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2900_SPRITES_H */
diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp
index 2bdb9f0497..a12776611e 100644
--- a/engines/neverhood/modules/module3000.cpp
+++ b/engines/neverhood/modules/module3000.cpp
@@ -20,9 +20,10 @@
*
*/
-#include "neverhood/modules/module3000.h"
#include "neverhood/gamemodule.h"
#include "neverhood/navigationscene.h"
+#include "neverhood/modules/module3000.h"
+#include "neverhood/modules/module3000_sprites.h"
namespace Neverhood {
@@ -39,7 +40,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);
@@ -49,7 +50,7 @@ Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which)
_isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0;
- if (_isWallBroken) {
+ if (!_isWallBroken) {
_vm->_soundMan->setSoundVolume(0x90F0D1C3, 0);
_vm->_soundMan->playSoundLooping(0x90F0D1C3);
}
@@ -73,15 +74,16 @@ 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("Module3000::createScene(%d, %d)", sceneNum, which);
+ debug(1, "Module3000::createScene(%d, %d)", sceneNum, which);
_vm->gameState().sceneNum = sceneNum;
+ _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0;
switch (_vm->gameState().sceneNum) {
case 1:
if (!getGlobalVar(V_BOLT_DOOR_OPEN)) {
createNavigationScene(0x004B7C80, which);
- } else if (getGlobalVar(V_WALL_BROKEN)) {
+ } else if (_isWallBroken) {
createNavigationScene(0x004B7CE0, which);
} else {
createNavigationScene(0x004B7CB0, which);
@@ -89,11 +91,11 @@ void Module3000::createScene(int sceneNum, int which) {
break;
case 2:
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
- if (_isWallBroken) {
+ if (!_isWallBroken) {
_soundVolume = 90;
_vm->_soundMan->setSoundVolume(0x90F0D1C3, 90);
}
- if (getGlobalVar(V_WALL_BROKEN)) {
+ if (_isWallBroken) {
createNavigationScene(0x004B7D58, which);
} else {
createNavigationScene(0x004B7D10, which);
@@ -102,7 +104,7 @@ void Module3000::createScene(int sceneNum, int which) {
case 3:
if (getGlobalVar(V_STAIRS_DOWN))
createNavigationScene(0x004B7E60, which);
- else if (getGlobalVar(V_WALL_BROKEN))
+ else if (_isWallBroken)
createNavigationScene(0x004B7DA0, which);
else
createNavigationScene(0x004B7E00, which);
@@ -150,12 +152,12 @@ void Module3000::createScene(int sceneNum, int which) {
// NOTE: Newly introduced sceneNums
case 1001:
if (!getGlobalVar(V_BOLT_DOOR_OPEN))
- if (getGlobalVar(V_WALL_BROKEN))
+ if (_isWallBroken)
createSmackerScene(0x00940021, true, true, false);
else
createSmackerScene(0x01140021, true, true, false);
else
- if (getGlobalVar(V_WALL_BROKEN))
+ if (_isWallBroken)
createSmackerScene(0x001011B1, true, true, false);
else
createSmackerScene(0x001021B1, true, true, false);
@@ -299,7 +301,7 @@ void Module3000::updateScene() {
} else if (frameNumber == 10) {
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
}
- if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
if (frameNumber == 0)
_soundVolume = 40;
else
@@ -313,7 +315,7 @@ void Module3000::updateScene() {
if (navigationScene()->isWalkingForward()) {
uint32 frameNumber = navigationScene()->getFrameNumber();
int navigationIndex = navigationScene()->getNavigationIndex();
- if (_isWallBroken && _soundVolume > 1 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume > 1 && frameNumber % 2) {
_soundVolume--;
_vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume);
}
@@ -338,7 +340,7 @@ void Module3000::updateScene() {
if (frameNumber == 40) {
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
}
- if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
if (frameNumber == 0)
_soundVolume = 40;
else
@@ -414,355 +416,18 @@ static const uint32 kScene3009CannonActionVideos[] = {
0x240A1101 // 14 Lower the cannon
};
-static const uint32 kSsScene3009SymbolEdgesFileHashes[] = {
- 0x618827A0,
- 0xB1A92322
-};
-
-static const uint32 kSsScene3009TargetLineFileHashes[] = {
- 0x4011018C,
- 0x15086623
-};
-
-static const NPoint kAsScene3009SymbolPoints[] = {
- {289, 338},
- {285, 375},
- {284, 419},
- {456, 372},
- {498, 372},
- {541, 372}
-};
-
-static const uint32 kAsScene3009SymbolFileHashes[] = {
- 0x24542582,
- 0x1CD61D96
-};
-
-static const uint32 kSsScene3009SymbolArrowFileHashes1[] = {
- 0x24016060,
- 0x21216221,
- 0x486160A0,
- 0x42216422,
- 0x90A16120,
- 0x84216824,
- 0x08017029,
- 0x08217029,
- 0x10014032,
- 0x10214032,
- 0x20012004,
- 0x20212004
-};
-
-static const uint32 kSsScene3009SymbolArrowFileHashes2[] = {
- 0x40092024,
- 0x01636002,
- 0x8071E028,
- 0x02A56064,
- 0x00806031,
- 0x052960A8,
- 0x0A116130,
- 0x0A316130,
- 0x14216200,
- 0x14016200,
- 0x28416460,
- 0x28616460
-};
-
-SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene)
- : StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) {
-
- loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
- setVisible(false);
- SetUpdateHandler(&SsScene3009FireCannonButton::update);
- SetMessageHandler(&SsScene3009FireCannonButton::handleMessage);
- loadSound(0, 0x3901B44F);
-}
-
-void SsScene3009FireCannonButton::update() {
- updatePosition();
- if (_isClicked && !isSoundPlaying(0)) {
- sendMessage(_parentScene, 0x2000, 0);
- setVisible(false);
- }
-}
-
-uint32 SsScene3009FireCannonButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (!_isClicked && !_parentScene->isTurning()) {
- _isClicked = true;
- setVisible(true);
- playSound(0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-SsScene3009SymbolEdges::SsScene3009SymbolEdges(NeverhoodEngine *vm, int index)
- : StaticSprite(vm, 1400), _blinkCountdown(0) {
-
- loadSprite(kSsScene3009SymbolEdgesFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600);
- if (getGlobalVar(V_ROBOT_HIT))
- hide();
- else
- startBlinking();
- SetUpdateHandler(&SsScene3009SymbolEdges::update);
-}
-
-void SsScene3009SymbolEdges::update() {
- if (_blinkCountdown != 0 && (--_blinkCountdown == 0)) {
- if (_blinkToggle) {
- setVisible(true);
- } else {
- setVisible(false);
- }
- updatePosition();
- _blinkCountdown = 3;
- _blinkToggle = !_blinkToggle;
- }
-}
-
-void SsScene3009SymbolEdges::show() {
- setVisible(true);
- updatePosition();
- _blinkCountdown = 0;
-}
-
-void SsScene3009SymbolEdges::hide() {
- setVisible(false);
- updatePosition();
- _blinkCountdown = 0;
-}
-
-void SsScene3009SymbolEdges::startBlinking() {
- setVisible(true);
- updatePosition();
- _blinkCountdown = 3;
- _blinkToggle = true;
-}
-
-SsScene3009TargetLine::SsScene3009TargetLine(NeverhoodEngine *vm, int index)
- : StaticSprite(vm, 1400) {
-
- loadSprite(kSsScene3009TargetLineFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600);
- setVisible(false);
-}
-
-void SsScene3009TargetLine::show() {
- setVisible(true);
- updatePosition();
-}
-
-SsScene3009SymbolArrow::SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index)
- : StaticSprite(vm, 1400), _asSymbol(asSymbol), _index(index), _enabled(true), _countdown(0) {
-
- _incrDecr = _index % 2;
-
- createSurface(1200, 33, 31);
- loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefPosition);
- _drawOffset.set(0, 0, 33, 31);
- _collisionBoundsOffset = _drawOffset;
- updateBounds();
- _needRefresh = true;
-
- SetUpdateHandler(&SsScene3009SymbolArrow::update);
- SetMessageHandler(&SsScene3009SymbolArrow::handleMessage);
- loadSound(0, 0x2C852206);
-}
-
-void SsScene3009SymbolArrow::hide() {
- _enabled = false;
- setVisible(false);
-}
-
-void SsScene3009SymbolArrow::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0)) {
- loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefDrawOffset);
- }
-}
-
-uint32 SsScene3009SymbolArrow::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_enabled && _countdown == 0) {
- _countdown = 2;
- loadSprite(kSsScene3009SymbolArrowFileHashes1[_index], kSLFDefDrawOffset);
- playSound(0);
- sendMessage(_asSymbol, 0x2005, _incrDecr);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-AsScene3009VerticalIndicator::AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index)
- : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) {
-
- _x = 300;
- _y = getGlobalVar(V_CANNON_RAISED) ? 52 : 266;
- createSurface1(0xC2463913, 1200);
- _needRefresh = true;
- updatePosition();
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene3009VerticalIndicator::handleMessage);
-}
-
-void AsScene3009VerticalIndicator::show() {
- startAnimation(0xC2463913, 0, -1);
- setVisible(true);
- updatePosition();
- _enabled = true;
-}
-
-uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_enabled) {
- sendMessage(_parentScene, 0x2002, 0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-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);
- _needRefresh = true;
- updatePosition();
- setVisible(false);
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene3009HorizontalIndicator::handleMessage);
- if (cannonTargetStatus == kCTSRightRobotNoTarget || cannonTargetStatus == kCTSRightRobotIsTarget || cannonTargetStatus == kCTSRightNoRobot) {
- SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight);
- _x = 280;
- }
-}
-
-uint32 AsScene3009HorizontalIndicator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_enabled) {
- sendMessage(_parentScene, 0x2004, 0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void AsScene3009HorizontalIndicator::suMoveLeft() {
- _x -= 6;
- if (_x < 92) {
- SetSpriteUpdate(NULL);
- _x = 92;
- }
-}
-
-void AsScene3009HorizontalIndicator::suMoveRight() {
- _x += 6;
- if (_x > 533) {
- SetSpriteUpdate(NULL);
- _x = 533;
- }
-}
-
-void AsScene3009HorizontalIndicator::show() {
- startAnimation(0xC0C12954, 0, -1);
- setVisible(true);
- updatePosition();
- _enabled = true;
-}
-
-void AsScene3009HorizontalIndicator::stMoveLeft() {
- _x = 533;
- SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveLeft);
-}
-
-void AsScene3009HorizontalIndicator::stMoveRight() {
- _x = 330;
- SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight);
-}
-
-AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition)
- : 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);
- startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1);
- _newStickFrameIndex = _symbolIndex;
- _needRefresh = true;
- updatePosition();
- SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene3009Symbol::handleMessage);
- _ssArrowPrev = _parentScene->insertSprite<SsScene3009SymbolArrow>(this, _symbolPosition * 2 + 0);
- _parentScene->addCollisionSprite(_ssArrowPrev);
- _ssArrowNext = _parentScene->insertSprite<SsScene3009SymbolArrow>(this, _symbolPosition * 2 + 1);
- _parentScene->addCollisionSprite(_ssArrowNext);
-}
-
-uint32 AsScene3009Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x2005:
- if (param.asInteger()) {
- if (_symbolIndex == 11)
- _symbolIndex = 0;
- else
- _symbolIndex++;
- } else {
- if (_symbolIndex == 0)
- _symbolIndex = 11;
- else
- _symbolIndex--;
- }
- startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1);
- _newStickFrameIndex = _symbolIndex;
- setSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition, _symbolIndex);
- if (_symbolPosition / 3 == 0) {
- sendMessage(_parentScene, 0x2001, 0);
- } else {
- sendMessage(_parentScene, 0x2003, 0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void AsScene3009Symbol::hide() {
- _ssArrowPrev->hide();
- _ssArrowNext->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);
@@ -786,8 +451,8 @@ Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which)
}
}
- _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo));
- _smackerPlayer->setDrawPos(89, 37);
+ _cannonSmackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo));
+ _cannonSmackerPlayer->setDrawPos(89, 37);
_palette->usePalette(); // Use it again since the SmackerPlayer overrides the usage
insertStaticSprite(0x8540252C, 400);
@@ -807,42 +472,39 @@ Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene3009::handleMessage);
SetUpdateHandler(&Scene3009::update);
+}
- // DEBUG Enable to set the correct code
-#if 0
- for (int i = 0; i < 6; i++)
- setSubVar(VA_CURR_CANNON_SYMBOLS, i, _correctSymbols[i]);
- sendMessage(this, 0x2003, 0);
-#endif
+Scene3009::~Scene3009() {
+}
+void Scene3009::openSmacker(uint32 fileHash, bool keepLastFrame) {
+ _cannonSmackerPlayer->open(fileHash, keepLastFrame);
+ //_vm->_screen->setSmackerDecoder(_cannonSmackerPlayer->getSmackerDecoder());
+ _palette->usePalette();
}
void Scene3009::update() {
Scene::update();
-
- if (!_keepVideo && _smackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) {
+
+ if (!_keepVideo && _cannonSmackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) {
switch (_cannonTargetStatus) {
case kCTSNull:
case kCTSLowerCannon:
- _smackerPlayer->open(0x340A0049, true);
- _palette->usePalette();
+ openSmacker(0x340A0049, true);
_keepVideo = true;
break;
case kCTSRightRobotNoTarget:
- _smackerPlayer->open(0x0082080D, true);
- _palette->usePalette();
+ openSmacker(0x0082080D, true);
_keepVideo = true;
_isTurning = false;
break;
case kCTSRightRobotIsTarget:
- _smackerPlayer->open(0x0282080D, true);
- _palette->usePalette();
+ openSmacker(0x0282080D, true);
_keepVideo = true;
_isTurning = false;
break;
case kCTSRightNoRobot:
- _smackerPlayer->open(0x0882080D, true);
- _palette->usePalette();
+ openSmacker(0x0882080D, true);
_keepVideo = true;
_isTurning = false;
break;
@@ -851,12 +513,11 @@ void Scene3009::update() {
case kCTSLeftNoRobot:
if (_moveCannonLeftFirst) {
if (_cannonTargetStatus == kCTSLeftRobotNoTarget)
- _smackerPlayer->open(0x110A000F, false);
- else if (_cannonTargetStatus == kCTSLeftRobotIsTarget)
- _smackerPlayer->open(0x500B004F, false);
- else if (_cannonTargetStatus == kCTSLeftNoRobot)
- _smackerPlayer->open(0x100B010E, false);
- _palette->usePalette();
+ openSmacker(0x110A000F, false);
+ else if (_cannonTargetStatus == kCTSLeftRobotIsTarget)
+ openSmacker(0x500B004F, false);
+ else if (_cannonTargetStatus == kCTSLeftNoRobot)
+ openSmacker(0x100B010E, false);
_moveCannonLeftFirst = false;
_asHorizontalIndicator->stMoveLeft();
} else {
@@ -955,15 +616,14 @@ uint32 Scene3009::handleMessage(int messageNum, const MessageParam &param, Entit
// Cannon is at the right position
if (!getGlobalVar(V_ROBOT_TARGET)) {
_cannonTargetStatus = kCTSLeftRobotNoTarget;
- _smackerPlayer->open(0x108A000F, false);
+ openSmacker(0x108A000F, false);
} else if (!getGlobalVar(V_ROBOT_HIT)) {
_cannonTargetStatus = kCTSLeftRobotIsTarget;
- _smackerPlayer->open(0x500B002F, false);
+ openSmacker(0x500B002F, false);
} else {
_cannonTargetStatus = kCTSLeftNoRobot;
- _smackerPlayer->open(0x100B008E, false);
+ openSmacker(0x100B008E, false);
}
- _palette->usePalette();
_moveCannonLeftFirst = true;
_isTurning = true;
_keepVideo = false;
@@ -1019,217 +679,10 @@ static const uint32 kScene3010DeadBoltButtonFileHashes2[] = {
0x5000A7E8
};
-static const NPoint kAsScene3010DeadBoltPoints[] = {
- {550, 307},
- {564, 415},
- {560, 514}
-};
-
-static const uint32 kAsScene3010DeadBoltFileHashes2[] = {
- 0x181A0042,
- 0x580A08F2,
- 0x18420076
-};
-
-static const uint32 kAsScene3010DeadBoltFileHashes1[] = {
- 0x300E105A,
- 0x804E0052,
- 0x040E485A
-};
-
-SsScene3010DeadBoltButton::SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled)
- : StaticSprite(vm, 900), _parentScene(parentScene), _buttonLocked(false), _countdown1(0), _countdown2(0), _buttonIndex(buttonIndex) {
-
- _buttonEnabled = getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_buttonIndex]) != 0;
- createSurface(400, 88, 95);
- setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]);
- if (initDisabled)
- disableButton();
- else if (_buttonEnabled)
- _countdown1 = initCountdown * 12 + 1;
- loadSound(0, 0xF4217243);
- loadSound(1, 0x44049000);
- loadSound(2, 0x6408107E);
- SetUpdateHandler(&SsScene3010DeadBoltButton::update);
- SetMessageHandler(&SsScene3010DeadBoltButton::handleMessage);
-}
-
-void SsScene3010DeadBoltButton::update() {
-
- if (_countdown1 != 0 && (--_countdown1 == 0)) {
- playSound(0);
- setVisible(false);
- setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]);
- }
-
- if (_countdown2 != 0 && (--_countdown2 == 0)) {
- setVisible(true);
- setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]);
- }
-
-}
-
-uint32 SsScene3010DeadBoltButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (!_buttonLocked && _countdown1 == 0) {
- if (_buttonEnabled) {
- playSound(1);
- playSound(2);
- setVisible(true);
- _buttonLocked = true;
- sendMessage(_parentScene, 0x2000, _buttonIndex);
- } else {
- sendMessage(_parentScene, 0x2002, _buttonIndex);
- }
- _needRefresh = true;
- updatePosition();
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-void SsScene3010DeadBoltButton::disableButton() {
- _buttonLocked = true;
- setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]);
- setVisible(true);
-}
-
-void SsScene3010DeadBoltButton::setSprite(uint32 fileHash) {
- loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset);
-}
-
-void SsScene3010DeadBoltButton::setCountdown(int count) {
- _countdown2 = count * 18 + 1;
-}
-
-AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked)
- : AnimatedSprite(vm, 1100), _parentScene(parentScene), _boltIndex(boltIndex), _soundToggle(true),
- _unlocked(false), _locked(false), _countdown(0) {
-
- _x = kAsScene3010DeadBoltPoints[_boltIndex].x;
- _y = kAsScene3010DeadBoltPoints[_boltIndex].y;
-
- if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_boltIndex])) {
- createSurface1(kAsScene3010DeadBoltFileHashes1[_boltIndex], 1200);
- startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
- loadSound(0, 0x46005BC4);
- } else {
- createSurface1(kAsScene3010DeadBoltFileHashes2[_boltIndex], 1200);
- startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1);
- loadSound(0, 0x420073DC);
- loadSound(1, 0x420073DC);
- }
-
- setVisible(false);
- stIdle();
- if (initUnlocked)
- unlock(true);
-
- _needRefresh = true;
- AnimatedSprite::updatePosition();
-
-}
-
-void AsScene3010DeadBolt::update() {
- updateAnim();
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0)) {
- stDisabled();
- }
-}
-
-uint32 AsScene3010DeadBolt::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x3002:
- gotoNextState();
- break;
- }
- return messageResult;
-}
-
-void AsScene3010DeadBolt::stIdle() {
- stopAnimation();
- SetUpdateHandler(&AsScene3010DeadBolt::update);
- SetMessageHandler(&Sprite::handleMessage);
- _locked = false;
-}
-
-void AsScene3010DeadBolt::unlock(bool skipAnim) {
- if (!_unlocked) {
- setVisible(true);
- if (skipAnim) {
- startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], -1, 0);
- _newStickFrameIndex = STICK_LAST_FRAME;
- } else {
- startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
- SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
- FinalizeState(&AsScene3010DeadBolt::stIdleMessage);
- NextState(&AsScene3010DeadBolt::stIdle);
- playSound(0);
- }
- _unlocked = true;
- loadSound(2, 0x4010C345);
- }
-}
-
-void AsScene3010DeadBolt::stIdleMessage() {
- stopAnimation();
- SetMessageHandler(&Sprite::handleMessage);
- sendMessage(_parentScene, 0x2001, _boltIndex);
-}
-
-void AsScene3010DeadBolt::lock() {
- if (!_locked) {
- _locked = true;
- setVisible(true);
- startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1);
- SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
- FinalizeState(&AsScene3010DeadBolt::stDisabledMessage);
- NextState(&AsScene3010DeadBolt::stIdle);
- if (_soundToggle) {
- playSound(0);
- } else {
- playSound(1);
- }
- _soundToggle = !_soundToggle;
- }
-}
-
-void AsScene3010DeadBolt::setCountdown(int count) {
- _countdown = count * 18 + 1;
-}
-
-void AsScene3010DeadBolt::stDisabled() {
- setVisible(true);
- startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
- SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
- FinalizeState(&AsScene3010DeadBolt::stDisabledMessage);
- NextState(&AsScene3010DeadBolt::stIdle);
- _playBackwards = true;
- playSound(2);
-}
-
-void AsScene3010DeadBolt::stDisabledMessage() {
- setVisible(false);
- sendMessage(_parentScene, 0x2003, _boltIndex);
-}
-
Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) {
-
- int initCountdown = 0;
- // DEBUG Enable to activate all buttons
-#if 0
- setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[0], 1);
- setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[1], 1);
- setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[2], 1);
-#endif
+ int initCountdown = 0;
setBackground(0x80802626);
setPalette(0x80802626);
@@ -1328,127 +781,6 @@ uint32 Scene3010::handleMessage(int messageNum, const MessageParam &param, Entit
return 0;
}
-// Scene3011
-
-static const uint32 kAsScene3011SymbolFileHashes[] = {
- 0x00C88050,
- 0x01488050,
- 0x02488050,
- 0x04488050,
- 0x08488050,
- 0x10488050,
- 0x20488050,
- 0x40488050,
- 0x80488050,
- 0x00488051,
- 0x00488052,
- 0x00488054,
- 0x008B0000,
- 0x008D0000,
- 0x00810000,
- 0x00990000,
- 0x00A90000,
- 0x00C90000,
- 0x00090000,
- 0x01890000,
- 0x02890000,
- 0x04890000,
- 0x08890000,
- 0x10890000
-};
-
-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);
- SetUpdateHandler(&SsScene3011Button::update);
- SetMessageHandler(&SsScene3011Button::handleMessage);
-}
-
-void SsScene3011Button::update() {
- updatePosition();
- if (_countdown != 0 && (--_countdown == 0)) {
- setVisible(false);
- }
-}
-
-uint32 SsScene3011Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
- uint32 messageResult = 0;
- StaticSprite::handleMessage(messageNum, param, sender);
- switch (messageNum) {
- case 0x1011:
- if (_countdown == 0) {
- setVisible(true);
- _countdown = 4;
- sendMessage(_parentScene, 0x2000, 0);
- playSound(0);
- }
- messageResult = 1;
- break;
- }
- return messageResult;
-}
-
-AsScene3011Symbol::AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol)
- : AnimatedSprite(vm, 1000), _symbolIndex(symbolIndex), _largeSymbol(largeSymbol), _isNoisy(false) {
-
- if (_largeSymbol) {
- _x = 310;
- _y = 200;
- createSurface1(kAsScene3011SymbolFileHashes[_symbolIndex], 1200);
- loadSound(0, 0x6052C60F);
- loadSound(1, 0x6890433B);
- } else {
- _symbolIndex = 12;
- _x = symbolIndex * 39 + 96;
- _y = 225;
- createSurface(1200, 41, 48);
- loadSound(0, 0x64428609);
- loadSound(1, 0x7080023B);
- }
- setVisible(false);
- _needRefresh = true;
- SetUpdateHandler(&AnimatedSprite::update);
-}
-
-void AsScene3011Symbol::show(bool isNoisy) {
- _isNoisy = isNoisy;
- startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1);
- setVisible(true);
- if (_isNoisy) {
- playSound(1);
- } else {
- playSound(0);
- }
-}
-
-void AsScene3011Symbol::hide() {
- stopAnimation();
- setVisible(false);
-}
-
-void AsScene3011Symbol::stopSymbolSound() {
- if (_isNoisy) {
- stopSound(1);
- } else {
- stopSound(0);
- }
-}
-
-void AsScene3011Symbol::change(int symbolIndex, bool isNoisy) {
- _symbolIndex = symbolIndex;
- _isNoisy = isNoisy;
- startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1);
- setVisible(true);
- if (_isNoisy) {
- playSound(1);
- } else {
- playSound(0);
- }
-}
-
Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _updateStatus(0), _buttonClicked(false), _currentSymbolIndex(0), _countdown(0) {
@@ -1457,7 +789,7 @@ Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene3011::handleMessage);
SetUpdateHandler(&Scene3011::update);
-
+
setBackground(0x92124A04);
setPalette(0xA4070114);
addEntity(_palette);
@@ -1469,12 +801,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 7634360d7c..a88dea513e 100644
--- a/engines/neverhood/modules/module3000.h
+++ b/engines/neverhood/modules/module3000.h
@@ -26,7 +26,6 @@
#include "neverhood/neverhood.h"
#include "neverhood/module.h"
#include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
namespace Neverhood {
@@ -41,98 +40,21 @@ protected:
void updateScene();
};
-// Scene3009
-
-class Scene3009;
-
-class SsScene3009FireCannonButton : public StaticSprite {
-public:
- SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene);
-protected:
- Scene3009 *_parentScene;
- bool _isClicked;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene3009SymbolEdges : public StaticSprite {
-public:
- SsScene3009SymbolEdges(NeverhoodEngine *vm, int index);
- void show();
- void hide();
- void startBlinking();
-protected:
- int _blinkCountdown;
- bool _blinkToggle;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsScene3009TargetLine : public StaticSprite {
-public:
- SsScene3009TargetLine(NeverhoodEngine *vm, int index);
- void show();
-};
-
-class SsScene3009SymbolArrow : public StaticSprite {
-public:
- SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index);
- void hide();
-protected:
- Sprite *_asSymbol;
- int _index;
- int _incrDecr;
- bool _enabled;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene3009VerticalIndicator : public AnimatedSprite {
-public:
- AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index);
- void show();
-protected:
- Scene3009 *_parentScene;
- bool _enabled;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene3009HorizontalIndicator : public AnimatedSprite {
-public:
- AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus);
- void show();
- void stMoveLeft();
- void stMoveRight();
-protected:
- Scene3009 *_parentScene;
- bool _enabled;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void suMoveLeft();
- void suMoveRight();
-};
-
-class AsScene3009Symbol : public AnimatedSprite {
-public:
- AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition);
- void hide();
-protected:
- Scene3009 *_parentScene;
- int _symbolPosition;
- uint32 _symbolIndex;
- SsScene3009SymbolArrow *_ssArrowPrev;
- SsScene3009SymbolArrow *_ssArrowNext;
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class SsScene3009SymbolEdges;
+class SsScene3009TargetLine;
+class AsScene3009VerticalIndicator;
+class AsScene3009HorizontalIndicator;
+class AsScene3009Symbol;
class Scene3009 : public Scene {
public:
Scene3009(NeverhoodEngine *vm, Module *parentModule, int which);
+ virtual ~Scene3009();
bool isTurning();
protected:
int _lockSymbolsPart1Countdown;
int _lockSymbolsPart2Countdown;
- SmackerPlayer *_smackerPlayer;
+ SmackerPlayer *_cannonSmackerPlayer;
Sprite *_ssFireCannonButton;
SsScene3009SymbolEdges *_ssSymbolEdges[2];
SsScene3009TargetLine *_ssTargetLines[2];
@@ -149,47 +71,11 @@ protected:
void playActionVideo();
bool isSymbolsPart1Solved();
bool isSymbolsPart2Solved();
+ void openSmacker(uint32 fileHash, bool keepLastFrame);
};
-// Scene3010
-
-class SsScene3010DeadBoltButton : public StaticSprite {
-public:
- SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled);
- void setCountdown(int count);
-protected:
- Scene *_parentScene;
- int _buttonIndex;
- bool _buttonEnabled;
- bool _buttonLocked;
- int _countdown1;
- int _countdown2;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
- void disableButton();
- void setSprite(uint32 fileHash);
-};
-
-class AsScene3010DeadBolt : public AnimatedSprite {
-public:
- AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked);
- void setCountdown(int count);
- void lock();
- void unlock(bool skipAnim);
-protected:
- Scene *_parentScene;
- int _boltIndex;
- int _countdown;
- bool _soundToggle;
- bool _unlocked;
- bool _locked;
- void update();
- uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
- void stIdle();
- void stIdleMessage();
- void stDisabled();
- void stDisabledMessage();
-};
+class SsScene3010DeadBoltButton;
+class AsScene3010DeadBolt;
class Scene3010 : public Scene {
public:
@@ -206,31 +92,7 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
-// Scene3011
-
-class SsScene3011Button : public StaticSprite {
-public:
- SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag);
-protected:
- Scene *_parentScene;
- int _countdown;
- void update();
- uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene3011Symbol : public AnimatedSprite {
-public:
- AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol);
- void show(bool isNoisy);
- void hide();
- void stopSymbolSound();
- void change(int symbolIndex, bool isNoisy);
- int getSymbolIndex() { return _largeSymbol ? _symbolIndex : _symbolIndex - 12; }
-protected:
- bool _largeSymbol;
- bool _isNoisy;
- int _symbolIndex;
-};
+class AsScene3011Symbol;
class Scene3011 : public Scene {
public:
@@ -242,7 +104,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/modules/module3000_sprites.cpp b/engines/neverhood/modules/module3000_sprites.cpp
new file mode 100644
index 0000000000..7d0162d7d0
--- /dev/null
+++ b/engines/neverhood/modules/module3000_sprites.cpp
@@ -0,0 +1,763 @@
+/* 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 "neverhood/modules/module3000.h"
+#include "neverhood/modules/module3000_sprites.h"
+
+namespace Neverhood {
+
+// Scene3009
+
+enum {
+ kCTSNull = 0,
+ kCTSBreakWall = 1,
+ kCTSWall = 2,
+ kCTSEmptyness = 3,
+ kCTSFireRobotNoTarget = 4,
+ kCTSFireRobotIsTarget = 5,
+ kCTSFireNoRobot = 6,
+ kCTSRaiseCannon = 7,
+ kCTSRightRobotNoTarget = 8,
+ kCTSRightRobotIsTarget = 9,
+ kCTSRightNoRobot = 10,
+ kCTSLeftRobotNoTarget = 11,
+ kCTSLeftRobotIsTarget = 12,
+ kCTSLeftNoRobot = 13,
+ kCTSLowerCannon = 14,
+ kCTSCount = 14
+};
+
+static const uint32 kScene3009CannonScopeVideos[] = {
+ 0x1010000D,
+ 0x340A0049,
+ 0x340A0049,
+ 0x0282081D,
+ 0x0082080D,
+ 0x0882080D,
+ 0x0882080D,
+ 0x0282081D,
+ 0x004B000B,
+ 0x014B000B,
+ 0x044B000B,
+ 0x0282081D,
+ 0x0282081D,
+ 0x0282081D,
+ 0x340A0049
+};
+
+static const uint32 kScene3009CannonActionVideos[] = {
+ 0x00000000,
+ 0x8004001B, // 1 Fire cannon at wall, it breaks (lowered)
+ 0x0004001A, // 2 Fire cannon at wall, nothing happens (lowered)
+ 0x1048404B, // 3 Fire cannon at emptyness (raised)
+ 0x50200109, // 4 Fire cannon, robot missed (raised)
+ 0x12032109, // 5 Fire cannon, robot hit (raised)
+ 0x10201109, // 6 Fire cannon, no robot (raised)
+ 0x000A2030, // 7 Raise the cannon
+ 0x000A0028, // 8
+ 0x000A0028, // 9
+ 0x000A0028, // 10
+ 0x040A1069, // 11
+ 0x040A1069, // 12
+ 0x040A1069, // 13
+ 0x240A1101 // 14 Lower the cannon
+};
+
+static const uint32 kSsScene3009SymbolEdgesFileHashes[] = {
+ 0x618827A0,
+ 0xB1A92322
+};
+
+static const uint32 kSsScene3009TargetLineFileHashes[] = {
+ 0x4011018C,
+ 0x15086623
+};
+
+static const NPoint kAsScene3009SymbolPoints[] = {
+ {289, 338},
+ {285, 375},
+ {284, 419},
+ {456, 372},
+ {498, 372},
+ {541, 372}
+};
+
+static const uint32 kAsScene3009SymbolFileHashes[] = {
+ 0x24542582,
+ 0x1CD61D96
+};
+
+static const uint32 kSsScene3009SymbolArrowFileHashes1[] = {
+ 0x24016060,
+ 0x21216221,
+ 0x486160A0,
+ 0x42216422,
+ 0x90A16120,
+ 0x84216824,
+ 0x08017029,
+ 0x08217029,
+ 0x10014032,
+ 0x10214032,
+ 0x20012004,
+ 0x20212004
+};
+
+static const uint32 kSsScene3009SymbolArrowFileHashes2[] = {
+ 0x40092024,
+ 0x01636002,
+ 0x8071E028,
+ 0x02A56064,
+ 0x00806031,
+ 0x052960A8,
+ 0x0A116130,
+ 0x0A316130,
+ 0x14216200,
+ 0x14016200,
+ 0x28416460,
+ 0x28616460
+};
+
+SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene)
+ : StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) {
+
+ loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
+ setVisible(false);
+ SetUpdateHandler(&SsScene3009FireCannonButton::update);
+ SetMessageHandler(&SsScene3009FireCannonButton::handleMessage);
+ loadSound(0, 0x3901B44F);
+}
+
+void SsScene3009FireCannonButton::update() {
+ updatePosition();
+ if (_isClicked && !isSoundPlaying(0)) {
+ sendMessage(_parentScene, 0x2000, 0);
+ setVisible(false);
+ }
+}
+
+uint32 SsScene3009FireCannonButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isClicked && !_parentScene->isTurning()) {
+ _isClicked = true;
+ setVisible(true);
+ playSound(0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+SsScene3009SymbolEdges::SsScene3009SymbolEdges(NeverhoodEngine *vm, int index)
+ : StaticSprite(vm, 1400), _blinkCountdown(0) {
+
+ loadSprite(kSsScene3009SymbolEdgesFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600);
+ if (getGlobalVar(V_ROBOT_HIT))
+ hide();
+ else
+ startBlinking();
+ SetUpdateHandler(&SsScene3009SymbolEdges::update);
+}
+
+void SsScene3009SymbolEdges::update() {
+ if (_blinkCountdown != 0 && (--_blinkCountdown == 0)) {
+ if (_blinkToggle) {
+ setVisible(true);
+ } else {
+ setVisible(false);
+ }
+ updatePosition();
+ _blinkCountdown = 3;
+ _blinkToggle = !_blinkToggle;
+ }
+}
+
+void SsScene3009SymbolEdges::show() {
+ setVisible(true);
+ updatePosition();
+ _blinkCountdown = 0;
+}
+
+void SsScene3009SymbolEdges::hide() {
+ setVisible(false);
+ updatePosition();
+ _blinkCountdown = 0;
+}
+
+void SsScene3009SymbolEdges::startBlinking() {
+ setVisible(true);
+ updatePosition();
+ _blinkCountdown = 3;
+ _blinkToggle = true;
+}
+
+SsScene3009TargetLine::SsScene3009TargetLine(NeverhoodEngine *vm, int index)
+ : StaticSprite(vm, 1400) {
+
+ loadSprite(kSsScene3009TargetLineFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600);
+ setVisible(false);
+}
+
+void SsScene3009TargetLine::show() {
+ setVisible(true);
+ updatePosition();
+}
+
+SsScene3009SymbolArrow::SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index)
+ : StaticSprite(vm, 1400), _asSymbol(asSymbol), _index(index), _enabled(true), _countdown(0) {
+
+ _incrDecr = _index % 2;
+
+ createSurface(1200, 33, 31);
+ loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefPosition);
+ _drawOffset.set(0, 0, 33, 31);
+ _collisionBoundsOffset = _drawOffset;
+ updateBounds();
+ _needRefresh = true;
+
+ SetUpdateHandler(&SsScene3009SymbolArrow::update);
+ SetMessageHandler(&SsScene3009SymbolArrow::handleMessage);
+ loadSound(0, 0x2C852206);
+}
+
+void SsScene3009SymbolArrow::hide() {
+ _enabled = false;
+ setVisible(false);
+}
+
+void SsScene3009SymbolArrow::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0)) {
+ loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefDrawOffset);
+ }
+}
+
+uint32 SsScene3009SymbolArrow::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_enabled && _countdown == 0) {
+ _countdown = 2;
+ loadSprite(kSsScene3009SymbolArrowFileHashes1[_index], kSLFDefDrawOffset);
+ playSound(0);
+ sendMessage(_asSymbol, 0x2005, _incrDecr);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene3009VerticalIndicator::AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index)
+ : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) {
+
+ _x = 300;
+ _y = getGlobalVar(V_CANNON_RAISED) ? 52 : 266;
+ createSurface1(0xC2463913, 1200);
+ _needRefresh = true;
+ updatePosition();
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene3009VerticalIndicator::handleMessage);
+}
+
+void AsScene3009VerticalIndicator::show() {
+ startAnimation(0xC2463913, 0, -1);
+ setVisible(true);
+ updatePosition();
+ _enabled = true;
+}
+
+uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_enabled) {
+ sendMessage(_parentScene, 0x2002, 0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+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);
+ _needRefresh = true;
+ updatePosition();
+ setVisible(false);
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene3009HorizontalIndicator::handleMessage);
+ if (cannonTargetStatus == kCTSRightRobotNoTarget || cannonTargetStatus == kCTSRightRobotIsTarget || cannonTargetStatus == kCTSRightNoRobot) {
+ SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight);
+ _x = 280;
+ }
+}
+
+uint32 AsScene3009HorizontalIndicator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_enabled) {
+ sendMessage(_parentScene, 0x2004, 0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene3009HorizontalIndicator::suMoveLeft() {
+ _x -= 6;
+ if (_x < 92) {
+ SetSpriteUpdate(NULL);
+ _x = 92;
+ }
+}
+
+void AsScene3009HorizontalIndicator::suMoveRight() {
+ _x += 6;
+ if (_x > 533) {
+ SetSpriteUpdate(NULL);
+ _x = 533;
+ }
+}
+
+void AsScene3009HorizontalIndicator::show() {
+ startAnimation(0xC0C12954, 0, -1);
+ setVisible(true);
+ updatePosition();
+ _enabled = true;
+}
+
+void AsScene3009HorizontalIndicator::stMoveLeft() {
+ _x = 533;
+ SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveLeft);
+}
+
+void AsScene3009HorizontalIndicator::stMoveRight() {
+ _x = 330;
+ SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight);
+}
+
+AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition)
+ : 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);
+ startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1);
+ _newStickFrameIndex = _symbolIndex;
+ _needRefresh = true;
+ updatePosition();
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene3009Symbol::handleMessage);
+ _ssArrowPrev = _parentScene->insertSprite<SsScene3009SymbolArrow>(this, _symbolPosition * 2 + 0);
+ _parentScene->addCollisionSprite(_ssArrowPrev);
+ _ssArrowNext = _parentScene->insertSprite<SsScene3009SymbolArrow>(this, _symbolPosition * 2 + 1);
+ _parentScene->addCollisionSprite(_ssArrowNext);
+}
+
+uint32 AsScene3009Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2005:
+ if (param.asInteger()) {
+ if (_symbolIndex == 11)
+ _symbolIndex = 0;
+ else
+ _symbolIndex++;
+ } else {
+ if (_symbolIndex == 0)
+ _symbolIndex = 11;
+ else
+ _symbolIndex--;
+ }
+ startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1);
+ _newStickFrameIndex = _symbolIndex;
+ setSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition, _symbolIndex);
+ if (_symbolPosition / 3 == 0) {
+ sendMessage(_parentScene, 0x2001, 0);
+ } else {
+ sendMessage(_parentScene, 0x2003, 0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene3009Symbol::hide() {
+ _ssArrowPrev->hide();
+ _ssArrowNext->hide();
+}
+
+// Scene3010
+
+static const uint32 kScene3010ButtonNameHashes[] = {
+ 0x304008D2,
+ 0x40119852,
+ 0x01180951
+};
+
+static const uint32 kScene3010DeadBoltButtonFileHashes1[] = {
+ 0x301024C2,
+ 0x20280580,
+ 0x30200452
+};
+
+static const uint32 kScene3010DeadBoltButtonFileHashes2[] = {
+ 0x50C025A8,
+ 0x1020A0A0,
+ 0x5000A7E8
+};
+
+static const NPoint kAsScene3010DeadBoltPoints[] = {
+ {550, 307},
+ {564, 415},
+ {560, 514}
+};
+
+static const uint32 kAsScene3010DeadBoltFileHashes2[] = {
+ 0x181A0042,
+ 0x580A08F2,
+ 0x18420076
+};
+
+static const uint32 kAsScene3010DeadBoltFileHashes1[] = {
+ 0x300E105A,
+ 0x804E0052,
+ 0x040E485A
+};
+
+SsScene3010DeadBoltButton::SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled)
+ : StaticSprite(vm, 900), _parentScene(parentScene), _buttonLocked(false), _countdown1(0), _countdown2(0), _buttonIndex(buttonIndex) {
+
+ _buttonEnabled = getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_buttonIndex]) != 0;
+ createSurface(400, 88, 95);
+ setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]);
+ if (initDisabled)
+ disableButton();
+ else if (_buttonEnabled)
+ _countdown1 = initCountdown * 12 + 1;
+ loadSound(0, 0xF4217243);
+ loadSound(1, 0x44049000);
+ loadSound(2, 0x6408107E);
+ SetUpdateHandler(&SsScene3010DeadBoltButton::update);
+ SetMessageHandler(&SsScene3010DeadBoltButton::handleMessage);
+}
+
+void SsScene3010DeadBoltButton::update() {
+
+ if (_countdown1 != 0 && (--_countdown1 == 0)) {
+ playSound(0);
+ setVisible(false);
+ setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]);
+ }
+
+ if (_countdown2 != 0 && (--_countdown2 == 0)) {
+ setVisible(true);
+ setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]);
+ }
+
+}
+
+uint32 SsScene3010DeadBoltButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_buttonLocked && _countdown1 == 0) {
+ if (_buttonEnabled) {
+ playSound(1);
+ playSound(2);
+ setVisible(true);
+ _buttonLocked = true;
+ sendMessage(_parentScene, 0x2000, _buttonIndex);
+ } else {
+ sendMessage(_parentScene, 0x2002, _buttonIndex);
+ }
+ _needRefresh = true;
+ updatePosition();
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+void SsScene3010DeadBoltButton::disableButton() {
+ _buttonLocked = true;
+ setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]);
+ setVisible(true);
+}
+
+void SsScene3010DeadBoltButton::setSprite(uint32 fileHash) {
+ loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset);
+}
+
+void SsScene3010DeadBoltButton::setCountdown(int count) {
+ _countdown2 = count * 18 + 1;
+}
+
+AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked)
+ : AnimatedSprite(vm, 1100), _parentScene(parentScene), _boltIndex(boltIndex), _soundToggle(true),
+ _unlocked(false), _locked(false), _countdown(0) {
+
+ _x = kAsScene3010DeadBoltPoints[_boltIndex].x;
+ _y = kAsScene3010DeadBoltPoints[_boltIndex].y;
+
+ if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_boltIndex])) {
+ createSurface1(kAsScene3010DeadBoltFileHashes1[_boltIndex], 1200);
+ startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
+ loadSound(0, 0x46005BC4);
+ } else {
+ createSurface1(kAsScene3010DeadBoltFileHashes2[_boltIndex], 1200);
+ startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1);
+ loadSound(0, 0x420073DC);
+ loadSound(1, 0x420073DC);
+ }
+
+ setVisible(false);
+ stIdle();
+ if (initUnlocked)
+ unlock(true);
+
+ _needRefresh = true;
+ AnimatedSprite::updatePosition();
+
+}
+
+void AsScene3010DeadBolt::update() {
+ updateAnim();
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0)) {
+ stDisabled();
+ }
+}
+
+uint32 AsScene3010DeadBolt::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene3010DeadBolt::stIdle() {
+ stopAnimation();
+ SetUpdateHandler(&AsScene3010DeadBolt::update);
+ SetMessageHandler(&Sprite::handleMessage);
+ _locked = false;
+}
+
+void AsScene3010DeadBolt::unlock(bool skipAnim) {
+ if (!_unlocked) {
+ setVisible(true);
+ if (skipAnim) {
+ startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], -1, 0);
+ _newStickFrameIndex = STICK_LAST_FRAME;
+ } else {
+ startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
+ SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
+ FinalizeState(&AsScene3010DeadBolt::stIdleMessage);
+ NextState(&AsScene3010DeadBolt::stIdle);
+ playSound(0);
+ }
+ _unlocked = true;
+ loadSound(2, 0x4010C345);
+ }
+}
+
+void AsScene3010DeadBolt::stIdleMessage() {
+ stopAnimation();
+ SetMessageHandler(&Sprite::handleMessage);
+ sendMessage(_parentScene, 0x2001, _boltIndex);
+}
+
+void AsScene3010DeadBolt::lock() {
+ if (!_locked) {
+ _locked = true;
+ setVisible(true);
+ startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1);
+ SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
+ FinalizeState(&AsScene3010DeadBolt::stDisabledMessage);
+ NextState(&AsScene3010DeadBolt::stIdle);
+ if (_soundToggle) {
+ playSound(0);
+ } else {
+ playSound(1);
+ }
+ _soundToggle = !_soundToggle;
+ }
+}
+
+void AsScene3010DeadBolt::setCountdown(int count) {
+ _countdown = count * 18 + 1;
+}
+
+void AsScene3010DeadBolt::stDisabled() {
+ setVisible(true);
+ startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1);
+ SetMessageHandler(&AsScene3010DeadBolt::hmAnimation);
+ FinalizeState(&AsScene3010DeadBolt::stDisabledMessage);
+ NextState(&AsScene3010DeadBolt::stIdle);
+ _playBackwards = true;
+ playSound(2);
+}
+
+void AsScene3010DeadBolt::stDisabledMessage() {
+ setVisible(false);
+ sendMessage(_parentScene, 0x2003, _boltIndex);
+}
+
+// Scene3011
+
+static const uint32 kAsScene3011SymbolFileHashes[] = {
+ 0x00C88050,
+ 0x01488050,
+ 0x02488050,
+ 0x04488050,
+ 0x08488050,
+ 0x10488050,
+ 0x20488050,
+ 0x40488050,
+ 0x80488050,
+ 0x00488051,
+ 0x00488052,
+ 0x00488054,
+ 0x008B0000,
+ 0x008D0000,
+ 0x00810000,
+ 0x00990000,
+ 0x00A90000,
+ 0x00C90000,
+ 0x00090000,
+ 0x01890000,
+ 0x02890000,
+ 0x04890000,
+ 0x08890000,
+ 0x10890000
+};
+
+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);
+ SetUpdateHandler(&SsScene3011Button::update);
+ SetMessageHandler(&SsScene3011Button::handleMessage);
+}
+
+void SsScene3011Button::update() {
+ updatePosition();
+ if (_countdown != 0 && (--_countdown == 0)) {
+ setVisible(false);
+ }
+}
+
+uint32 SsScene3011Button::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = 0;
+ StaticSprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown == 0) {
+ setVisible(true);
+ _countdown = 4;
+ sendMessage(_parentScene, 0x2000, 0);
+ playSound(0);
+ }
+ messageResult = 1;
+ break;
+ }
+ return messageResult;
+}
+
+AsScene3011Symbol::AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol)
+ : AnimatedSprite(vm, 1000), _symbolIndex(symbolIndex), _largeSymbol(largeSymbol), _isNoisy(false) {
+
+ if (_largeSymbol) {
+ _x = 310;
+ _y = 200;
+ createSurface1(kAsScene3011SymbolFileHashes[_symbolIndex], 1200);
+ loadSound(0, 0x6052C60F);
+ loadSound(1, 0x6890433B);
+ } else {
+ _symbolIndex = 12;
+ _x = symbolIndex * 39 + 96;
+ _y = 225;
+ createSurface(1200, 41, 48);
+ loadSound(0, 0x64428609);
+ loadSound(1, 0x7080023B);
+ }
+ setVisible(false);
+ _needRefresh = true;
+ SetUpdateHandler(&AnimatedSprite::update);
+}
+
+void AsScene3011Symbol::show(bool isNoisy) {
+ _isNoisy = isNoisy;
+ startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1);
+ setVisible(true);
+ if (_isNoisy) {
+ playSound(1);
+ } else {
+ playSound(0);
+ }
+}
+
+void AsScene3011Symbol::hide() {
+ stopAnimation();
+ setVisible(false);
+}
+
+void AsScene3011Symbol::stopSymbolSound() {
+ if (_isNoisy) {
+ stopSound(1);
+ } else {
+ stopSound(0);
+ }
+}
+
+void AsScene3011Symbol::change(int symbolIndex, bool isNoisy) {
+ _symbolIndex = symbolIndex;
+ _isNoisy = isNoisy;
+ startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1);
+ setVisible(true);
+ if (_isNoisy) {
+ playSound(1);
+ } else {
+ playSound(0);
+ }
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module3000_sprites.h b/engines/neverhood/modules/module3000_sprites.h
new file mode 100644
index 0000000000..7316613327
--- /dev/null
+++ b/engines/neverhood/modules/module3000_sprites.h
@@ -0,0 +1,185 @@
+/* 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 NEVERHOOD_MODULES_MODULE3000_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE3000_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/modules/module1200.h"
+
+namespace Neverhood {
+
+// Scene3009
+
+class Scene3009;
+
+class SsScene3009FireCannonButton : public StaticSprite {
+public:
+ SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene);
+protected:
+ Scene3009 *_parentScene;
+ bool _isClicked;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene3009SymbolEdges : public StaticSprite {
+public:
+ SsScene3009SymbolEdges(NeverhoodEngine *vm, int index);
+ void show();
+ void hide();
+ void startBlinking();
+protected:
+ int _blinkCountdown;
+ bool _blinkToggle;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsScene3009TargetLine : public StaticSprite {
+public:
+ SsScene3009TargetLine(NeverhoodEngine *vm, int index);
+ void show();
+};
+
+class SsScene3009SymbolArrow : public StaticSprite {
+public:
+ SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index);
+ void hide();
+protected:
+ Sprite *_asSymbol;
+ int _index;
+ int _incrDecr;
+ bool _enabled;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene3009VerticalIndicator : public AnimatedSprite {
+public:
+ AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index);
+ void show();
+protected:
+ Scene3009 *_parentScene;
+ bool _enabled;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene3009HorizontalIndicator : public AnimatedSprite {
+public:
+ AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus);
+ void show();
+ void stMoveLeft();
+ void stMoveRight();
+protected:
+ Scene3009 *_parentScene;
+ bool _enabled;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoveLeft();
+ void suMoveRight();
+};
+
+class AsScene3009Symbol : public AnimatedSprite {
+public:
+ AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition);
+ void hide();
+protected:
+ Scene3009 *_parentScene;
+ int _symbolPosition;
+ uint32 _symbolIndex;
+ SsScene3009SymbolArrow *_ssArrowPrev;
+ SsScene3009SymbolArrow *_ssArrowNext;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+// Scene3010
+
+class SsScene3010DeadBoltButton : public StaticSprite {
+public:
+ SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled);
+ void setCountdown(int count);
+protected:
+ Scene *_parentScene;
+ int _buttonIndex;
+ bool _buttonEnabled;
+ bool _buttonLocked;
+ int _countdown1;
+ int _countdown2;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void disableButton();
+ void setSprite(uint32 fileHash);
+};
+
+class AsScene3010DeadBolt : public AnimatedSprite {
+public:
+ AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked);
+ void setCountdown(int count);
+ void lock();
+ void unlock(bool skipAnim);
+protected:
+ Scene *_parentScene;
+ int _boltIndex;
+ int _countdown;
+ bool _soundToggle;
+ bool _unlocked;
+ bool _locked;
+ void update();
+ uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
+ void stIdle();
+ void stIdleMessage();
+ void stDisabled();
+ void stDisabledMessage();
+};
+
+// Scene3011
+
+class SsScene3011Button : public StaticSprite {
+public:
+ SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag);
+protected:
+ Scene *_parentScene;
+ int _countdown;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene3011Symbol : public AnimatedSprite {
+public:
+ AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol);
+ void show(bool isNoisy);
+ void hide();
+ void stopSymbolSound();
+ void change(int symbolIndex, bool isNoisy);
+ int getSymbolIndex() { return _largeSymbol ? _symbolIndex : _symbolIndex - 12; }
+protected:
+ bool _largeSymbol;
+ bool _isNoisy;
+ int _symbolIndex;
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE3000_SPRITES_H */
diff --git a/engines/neverhood/mouse.cpp b/engines/neverhood/mouse.cpp
index 632f56fb74..f11a3f99ea 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;
@@ -183,7 +183,7 @@ void Mouse::updateCursor() {
_drawOffset = _mouseCursorResource.getRect();
_surface->drawMouseCursorResource(_mouseCursorResource, _frameNum / 2);
Graphics::Surface *cursorSurface = _surface->getSurface();
- CursorMan.replaceCursor((const byte*)cursorSurface->pixels,
+ CursorMan.replaceCursor((const byte*)cursorSurface->getPixels(),
cursorSurface->w, cursorSurface->h, -_drawOffset.x, -_drawOffset.y, 0);
}
@@ -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 d802322858..a15c00de07 100644
--- a/engines/neverhood/navigationscene.cpp
+++ b/engines/neverhood/navigationscene.cpp
@@ -25,33 +25,36 @@
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);
-
+ _navigationListId = 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 = new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true);
- addEntity(_smackerPlayer);
- addSurface(_smackerPlayer->getSurface());
-
+
+ _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() {
@@ -97,7 +100,7 @@ void NavigationScene::update() {
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
sendMessage(_parentModule, 0x100A, _navigationIndex);
}
- }
+ }
Scene::update();
}
@@ -123,39 +126,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) {
@@ -206,13 +204,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/navigationscene.h b/engines/neverhood/navigationscene.h
index ebe9a3597c..c17446811c 100644
--- a/engines/neverhood/navigationscene.h
+++ b/engines/neverhood/navigationscene.h
@@ -38,10 +38,12 @@ public:
bool isWalkingForward() const { return _isWalkingForward; }
bool isTurning() const { return _isTurning; }
int getFrameNumber() const { return _smackerPlayer->getFrameNumber(); }
+ uint32 getNavigationListId() const { return _navigationListId; }
protected:
SmackerPlayer *_smackerPlayer;
bool _smackerDone;
NavigationList *_navigationList;
+ uint32 _navigationListId; // used for debugging
int _navigationIndex;
uint32 _smackerFileHash;
bool _interactive;
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index 42fe1176b4..b961bccea7 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -22,12 +22,18 @@
#include "common/file.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
+
#include "base/plugins.h"
#include "base/version.h"
+
#include "graphics/cursorman.h"
+
#include "engines/util.h"
+
#include "neverhood/neverhood.h"
#include "neverhood/blbarchive.h"
+#include "neverhood/console.h"
#include "neverhood/gamemodule.h"
#include "neverhood/gamevars.h"
#include "neverhood/graphics.h"
@@ -71,12 +77,17 @@ Common::Error NeverhoodEngine::run() {
_gameState.sceneNum = 0;
_gameState.which = 0;
+ // Assign default values to the config manager, in case settings are missing
+ ConfMan.registerDefault("originalsaveload", "false");
+ ConfMan.registerDefault("skiphallofrecordsscenes", "false");
+
_staticData = new StaticData();
_staticData->load("neverhood.dat");
_gameVars = new GameVars();
_screen = new Screen(this);
_res = new ResourceMan();
-
+ _console = new Console(this);
+
if (isDemo()) {
_res->addArchive("a.blb");
_res->addArchive("nevdemo.blb");
@@ -90,15 +101,17 @@ Common::Error NeverhoodEngine::run() {
_res->addArchive("t.blb");
}
- CursorMan.showMouse(true);
+ CursorMan.showMouse(false);
_soundMan = new SoundMan(this);
_audioResourceMan = new AudioResourceMan(this);
-
+
_gameModule = new GameModule(this);
-
+
_isSaveAllowed = true;
-
+ _updateSound = true;
+ _enableMusic = !_mixer->isSoundTypeMuted(Audio::Mixer::kMusicSoundType);
+
if (isDemo()) {
// Adjust this navigation list for the demo version
NavigationList *navigationList = _staticData->getNavigationList(0x004B67E8);
@@ -111,24 +124,26 @@ Common::Error NeverhoodEngine::run() {
(*navigationList)[5].middleSmackerFileHash = 0;
(*navigationList)[5].middleFlag = 1;
}
-
- if (ConfMan.hasKey("save_slot"))
- loadGameState(ConfMan.getInt("save_slot"));
- else
+
+ 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;
+ delete _console;
delete _res;
delete _screen;
delete _gameVars;
delete _staticData;
-
+
return Common::kNoError;
}
@@ -140,6 +155,11 @@ void NeverhoodEngine::mainLoop() {
while (eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
+ if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) {
+ // Open debugger console
+ _console->attach();
+ continue;
+ }
_gameModule->handleKeyDown(event.kbd.keycode);
_gameModule->handleAsciiKey(event.kbd.ascii);
break;
@@ -169,11 +189,16 @@ void NeverhoodEngine::mainLoop() {
_gameModule->checkRequests();
_gameModule->handleUpdate();
_gameModule->draw();
+ _console->onFrame();
_screen->update();
nextFrameTime = _screen->getNextFrameTime();
};
- _soundMan->update();
- _audioResourceMan->updateMusic();
+
+ if (_updateSound) {
+ _soundMan->update();
+ _audioResourceMan->updateMusic();
+ }
+
_system->updateScreen();
_system->delayMillis(10);
}
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 577fbd7a66..0561aa251e 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -48,6 +48,7 @@ class Screen;
class SoundMan;
class AudioResourceMan;
class StaticData;
+class Console;
struct NPoint;
struct GameState {
@@ -71,8 +72,10 @@ public:
uint32 getFeatures() const;
uint16 getVersion() const;
Common::Platform getPlatform() const;
+ Common::Language getLanguage() const;
bool hasFeature(EngineFeature f) const;
bool isDemo() const;
+ bool applyResourceFixes() const;
Common::String getTargetName() { return _targetName; };
Common::RandomSource *_rnd;
@@ -86,12 +89,13 @@ public:
ResourceMan *_res;
GameModule *_gameModule;
StaticData *_staticData;
-
+ Console *_console;
+
SoundMan *_soundMan;
AudioResourceMan *_audioResourceMan;
public:
-
+
/* Save/load */
enum kReadSaveHeaderError {
@@ -116,12 +120,12 @@ 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);
- void savegame(const char *filename, const char *description);
- void loadgame(const char *filename);
+ bool savegame(const char *filename, const char *description);
+ bool loadgame(const char *filename);
const char *getSavegameFilename(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
@@ -132,7 +136,13 @@ public:
int16 getMouseY() const { return _mouseY; }
NPoint getMousePos();
-public:
+ void toggleSoundUpdate(bool state) { _updateSound = state; }
+ void toggleMusic(bool state) { _enableMusic = state; }
+ bool musicIsEnabled() { return _enableMusic; }
+
+private:
+ bool _updateSound;
+ bool _enableMusic;
};
diff --git a/engines/neverhood/palette.cpp b/engines/neverhood/palette.cpp
index d4b9b67f53..941bcc3cd3 100644
--- a/engines/neverhood/palette.cpp
+++ b/engines/neverhood/palette.cpp
@@ -66,6 +66,11 @@ void Palette::init() {
_status = 0;
_palette = new byte[1024];
_basePalette = new byte[1024];
+ _palCounter = 0;
+ _fadeToR = 0;
+ _fadeToG = 0;
+ _fadeToB = 0;
+ _fadeStep = 0;
}
void Palette::usePalette() {
@@ -81,7 +86,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 +95,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 +120,7 @@ void Palette::startFadeToBlack(int counter) {
_fadeToB = 0;
_palCounter = counter;
_fadeStep = 255 / counter;
- _status = 1;
+ _status = 1;
}
void Palette::startFadeToWhite(int counter) {
@@ -127,7 +132,7 @@ void Palette::startFadeToWhite(int counter) {
_fadeToB = 255;
_palCounter = counter;
_fadeStep = 255 / counter;
- _status = 1;
+ _status = 1;
}
void Palette::startFadeToPalette(int counter) {
@@ -136,7 +141,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..b45dbff3b9 100644
--- a/engines/neverhood/resource.cpp
+++ b/engines/neverhood/resource.cpp
@@ -39,7 +39,7 @@ SpriteResource::~SpriteResource() {
void SpriteResource::draw(Graphics::Surface *destSurface, bool flipX, bool flipY) {
if (_pixels) {
- byte *dest = (byte*)destSurface->pixels;
+ byte *dest = (byte*)destSurface->getPixels();
const int destPitch = destSurface->pitch;
if (_rle)
unpackSpriteRle(_pixels, _dimensions.width, _dimensions.height, dest, destPitch, flipX, flipY);
@@ -53,11 +53,11 @@ bool SpriteResource::load(uint32 fileHash, bool doLoadPosition) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeBitmap) {
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
const byte *spriteData = _resourceHandle.data();
NPoint *position = doLoadPosition ? &_position : NULL;
parseBitmapResource(spriteData, &_rle, &_dimensions, position, NULL, &_pixels);
- }
+ }
return _pixels != NULL;
}
@@ -83,7 +83,7 @@ bool PaletteResource::load(uint32 fileHash) {
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() &&
(_resourceHandle.type() == kResTypeBitmap || _resourceHandle.type() == kResTypePalette)) {
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_palette = _resourceHandle.data();
// Check if the palette is stored in a bitmap
if (_resourceHandle.type() == kResTypeBitmap)
@@ -116,7 +116,7 @@ AnimResource::~AnimResource() {
void AnimResource::draw(uint frameIndex, Graphics::Surface *destSurface, bool flipX, bool flipY) {
const AnimFrameInfo frameInfo = _frames[frameIndex];
- byte *dest = (byte*)destSurface->pixels;
+ byte *dest = (byte*)destSurface->getPixels();
const int destPitch = destSurface->pitch;
_currSpriteData = _spriteData + frameInfo.spriteDataOffs;
_width = frameInfo.drawOffset.width;
@@ -134,32 +134,32 @@ 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;
uint32 spriteDataOfs, paletteDataOfs;
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
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;
+ byte *dest = (byte*)destSurface->getPixels();
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() {
@@ -323,7 +323,7 @@ void TextResource::load(uint32 fileHash) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeText) {
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_textData = _resourceHandle.data();
_count = READ_LE_UINT32(_textData);
}
@@ -359,7 +359,7 @@ void DataResource::load(uint32 fileHash) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeData) {
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
data = _resourceHandle.data();
dataSize = _resourceHandle.size();
}
@@ -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..f6937384c0 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;
@@ -85,7 +85,44 @@ void ResourceMan::queryResource(uint32 fileHash, ResourceHandle &resourceHandle)
resourceHandle._extData = firstEntry ? firstEntry->archiveEntry->extData : NULL;
}
-void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
+struct EntrySizeFix {
+ uint32 fileHash;
+ uint32 offset;
+ uint32 diskSize;
+ uint32 size;
+ uint32 fixedSize;
+};
+
+static const EntrySizeFix entrySizeFixes[] = {
+ // fileHash offset diskSize size fixedSize
+ // Fixes for the Russian "Dyadyushka Risech" version
+ { 0x041137051, 667019, 23391, 41398, 41401 }, // "Options" menu header text
+ { 0x00f960021, 402268, 1704, 4378, 1870 }, // "Save" menu
+ { 0x01301a7ea, 1220008, 2373, 4146, 2877 }, // "Load" menu
+ { 0x084181e81, 201409, 1622, 5058, 1833 }, // "Delete" menu
+ { 0x008C0AC24, 1031009, 3030, 6498, 3646 }, // Overwrite dialog
+ { 0x0c6604282, 12813649, 19623, 35894, 35895 }, // One of the fonts when reading Willie's notes
+ { 0x080283101, 13104841, 1961, 3712, 3511 }, // First message from Willie
+ { 0x000918480, 17676417, 581, 916, 706 }, // First wall in the museum
+ { 0x00800090C, 16064875, 19555, 38518, 38526 }, // First wall in the museum
+ { 0x058208810, 46010519, 24852, 131874, 131776 }, // Entry to hut with musical lock
+ { 0x00008E486, 39600019, 240, 454, 271 }, // Second wall in the museum
+ { 0x003086004, 39621755, 482, 614, 600 }, // Second wall in the museum
+ { 0x02008048E, 39611075, 3798, 21089, 21087 }, // Next couple of walls in the museum
+ { 0x008586283, 39587864, 12155, 29731, 29730 }, // Next couple of walls in the museum
+ { 0x030A84C80, 39606142, 4933, 16305, 16275 }, // Next couple of walls in the museum
+ { 0x000C9A480, 39614873, 6882, 23915, 23913 }, // Next couple of walls in the museum
+ { 0x000098880, 39603114, 3028, 10860, 10859 }, // Next couple of walls in the museum
+ { 0x040080183, 39600259, 2855, 13400, 13395 }, // Last buggy wall in the museum
+
+ // Fixes for the Russian "Fargus" version
+ { 0x041137051, 758264, 29037, 49590, 49591 }, // "Options" menu header text
+ { 0x0c10b2015, 787304, 4414, 15848, 15853 }, // Text on option buttons
+ //
+ { 0, 0, 0, 0, 0 }
+};
+
+void ResourceMan::loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes) {
resourceHandle._data = NULL;
if (resourceHandle.isValid()) {
const uint32 fileHash = resourceHandle.fileHash();
@@ -97,8 +134,19 @@ void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
if (resourceData->data != NULL) {
resourceData->dataRefCount++;
} else {
- resourceData->data = new byte[resourceHandle._resourceFileEntry->archiveEntry->size];
- resourceHandle._resourceFileEntry->archive->load(resourceHandle._resourceFileEntry->archiveEntry, resourceData->data, 0);
+ BlbArchiveEntry *entry = resourceHandle._resourceFileEntry->archiveEntry;
+
+ // Apply fixes for broken resources in Russian versions
+ if (applyResourceFixes) {
+ for (const EntrySizeFix *cur = entrySizeFixes; cur->fileHash > 0; ++cur) {
+ if (entry->fileHash == cur->fileHash && entry->offset == cur->offset &&
+ entry->diskSize == cur->diskSize && entry->size == cur->size)
+ entry->size = cur->fixedSize;
+ }
+ }
+
+ resourceData->data = new byte[entry->size];
+ resourceHandle._resourceFileEntry->archive->load(entry, resourceData->data, 0);
resourceData->dataRefCount = 1;
}
resourceHandle._data = resourceData->data;
diff --git a/engines/neverhood/resourceman.h b/engines/neverhood/resourceman.h
index 5a3697fe0d..29bf40a6b8 100644
--- a/engines/neverhood/resourceman.h
+++ b/engines/neverhood/resourceman.h
@@ -78,7 +78,7 @@ public:
const ResourceFileEntry& getEntry(uint index) { return _entries[index]; }
uint getEntryCount() { return _entries.size(); }
void queryResource(uint32 fileHash, ResourceHandle &resourceHandle);
- void loadResource(ResourceHandle &resourceHandle);
+ void loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes);
void unloadResource(ResourceHandle &resourceHandle);
void purgeResources();
protected:
diff --git a/engines/neverhood/saveload.cpp b/engines/neverhood/saveload.cpp
index 578d9858ff..01988769e6 100644
--- a/engines/neverhood/saveload.cpp
+++ b/engines/neverhood/saveload.cpp
@@ -61,12 +61,12 @@ NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::Se
return ((in->eos() || in->err()) ? kRSHEIoError : kRSHENoError);
}
-void NeverhoodEngine::savegame(const char *filename, const char *description) {
+bool NeverhoodEngine::savegame(const char *filename, const char *description) {
Common::OutSaveFile *out;
if (!(out = g_system->getSavefileManager()->openForSaving(filename))) {
warning("Can't create file '%s', game not saved", filename);
- return;
+ return false;
}
TimeDate curTime;
@@ -78,7 +78,7 @@ void 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,50 +96,53 @@ void 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;
}
-void NeverhoodEngine::loadgame(const char *filename) {
+bool NeverhoodEngine::loadgame(const char *filename) {
Common::InSaveFile *in;
if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
warning("Can't open file '%s', game not loaded", filename);
- return;
+ return false;
}
SaveHeader header;
kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
-
+
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
delete in;
- return;
+ 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);
_gameModule->requestRestoreGame();
delete in;
-
+ return true;
}
Common::Error NeverhoodEngine::loadGameState(int slot) {
const char *fileName = getSavegameFilename(slot);
- loadgame(fileName);
+ if (!loadgame(fileName))
+ return Common::kReadingFailed;
return Common::kNoError;
}
Common::Error NeverhoodEngine::saveGameState(int slot, const Common::String &description) {
const char *fileName = getSavegameFilename(slot);
- savegame(fileName, description.c_str());
+ if (!savegame(fileName, description.c_str()))
+ return Common::kWritingFailed;
return Common::kNoError;
}
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
index 07d41754c9..9a7e87ac8d 100644
--- a/engines/neverhood/scene.cpp
+++ b/engines/neverhood/scene.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "neverhood/console.h"
#include "neverhood/scene.h"
namespace Neverhood {
@@ -27,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;
@@ -49,15 +50,22 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule)
_smackerPlayer = NULL;
_isMessageListBusy = false;
_messageValue = -1;
-
+ _messageListStatus = 0;
+ _messageListCount = 0;
+ _messageListIndex = 0;
+
+ _backgroundFileHash = _cursorFileHash = 0;
+
SetUpdateHandler(&Scene::update);
SetMessageHandler(&Scene::handleMessage);
-
+
_vm->_screen->clearRenderQueue();
}
Scene::~Scene() {
+ _vm->_screen->setSmackerDecoder(NULL);
+
if (_palette) {
removeEntity(_palette);
delete _palette;
@@ -68,7 +76,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();
@@ -81,7 +89,7 @@ void Scene::draw() {
} else {
for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++)
(*iter)->draw();
- }
+ }
}
void Scene::addEntity(Entity *entity) {
@@ -96,7 +104,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) {
@@ -105,7 +113,7 @@ bool Scene::removeEntity(Entity *entity) {
_entities.remove_at(index);
return true;
}
- return false;
+ return false;
}
void Scene::addSurface(BaseSurface *surface) {
@@ -121,7 +129,7 @@ void Scene::addSurface(BaseSurface *surface) {
if (insertIndex >= 0)
_surfaces.insert_at(insertIndex, surface);
else
- _surfaces.push_back(surface);
+ _surfaces.push_back(surface);
}
}
@@ -132,7 +140,19 @@ bool Scene::removeSurface(BaseSurface *surface) {
return true;
}
}
- return false;
+ return false;
+}
+
+void Scene::printSurfaces(Console *con) {
+ for (uint index = 0; index < _surfaces.size(); index++) {
+ NDrawRect drawRect = _surfaces[index]->getDrawRect();
+ NRect clipRect = _surfaces[index]->getClipRect();
+ int priority = _surfaces[index]->getPriority();
+ con->DebugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n",
+ index, _surfaces[index]->getName().c_str(), priority,
+ drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(),
+ clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2);
+ }
}
Sprite *Scene::addSprite(Sprite *sprite) {
@@ -173,6 +193,7 @@ Background *Scene::addBackground(Background *background) {
void Scene::setBackground(uint32 fileHash) {
_background = addBackground(new Background(_vm, fileHash, 0, 0));
+ _backgroundFileHash = fileHash;
}
void Scene::changeBackground(uint32 fileHash) {
@@ -197,18 +218,21 @@ Sprite *Scene::insertStaticSprite(uint32 fileHash, int surfacePriority) {
}
void Scene::insertScreenMouse(uint32 fileHash, const NRect *mouseRect) {
- NRect rect(-1, -1, -1, -1);
+ NRect rect = NRect::make(-1, -1, -1, -1);
if (mouseRect)
rect = *mouseRect;
insertMouse(new Mouse(_vm, fileHash, rect));
+ _cursorFileHash = fileHash;
}
void Scene::insertPuzzleMouse(uint32 fileHash, int16 x1, int16 x2) {
insertMouse(new Mouse(_vm, fileHash, x1, x2));
+ _cursorFileHash = fileHash;
}
void Scene::insertNavigationMouse(uint32 fileHash, int type) {
insertMouse(new Mouse(_vm, fileHash, type));
+ _cursorFileHash = fileHash;
}
void Scene::showMouse(bool visible) {
@@ -231,12 +255,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);
}
@@ -247,7 +271,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();
@@ -268,7 +292,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
@@ -317,7 +341,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;
}
@@ -397,8 +421,8 @@ void Scene::processMessageList() {
_messageList2 = NULL;
_messageListStatus = 0;
}
-
- if (_messageList && _klaymen) {
+
+ if (_messageList && _klaymen) {
#if 0
debug("MessageList: %p, %d", (void*)_messageList, _messageList->size());
@@ -408,11 +432,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);
@@ -445,7 +469,7 @@ void Scene::processMessageList() {
if (_klaymen->hasMessageHandler() && sendMessage(_klaymen, messageNum, messageParam) != 0) {
_isKlaymenBusy = false;
}
- }
+ }
if (_messageListIndex == _messageListCount) {
_canAcceptInput = true;
_messageList = NULL;
@@ -454,7 +478,7 @@ void Scene::processMessageList() {
}
_isMessageListBusy = false;
-
+
}
void Scene::cancelMessageList() {
@@ -516,7 +540,7 @@ uint16 Scene::convertMessageNum(uint32 messageNum) {
case 0x42002200:
return 0x4004;
case 0x428D4894:
- return 0x101A;
+ return 0x101A;
}
return 0x1000;
}
@@ -531,7 +555,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) {
@@ -546,7 +570,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) {
@@ -568,7 +592,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) {
@@ -578,4 +602,27 @@ void Scene::insertMouse(Mouse *mouseCursor) {
addEntity(_mouseCursor);
}
+// StaticScene
+
+StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash)
+ : Scene(vm, parentModule) {
+
+ SetMessageHandler(&StaticScene::handleMessage);
+
+ setBackground(backgroundFileHash);
+ setPalette(backgroundFileHash);
+ insertPuzzleMouse(cursorFileHash, 20, 620);
+}
+
+uint32 StaticScene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x0001:
+ if (param.asPoint().x <= 20 || param.asPoint().x >= 620)
+ leaveScene(0);
+ break;
+ }
+ return 0;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h
index 1abcbfb964..e6183199ce 100644
--- a/engines/neverhood/scene.h
+++ b/engines/neverhood/scene.h
@@ -37,6 +37,8 @@
namespace Neverhood {
+class Console;
+
class Scene : public Entity {
public:
Scene(NeverhoodEngine *vm, Module *parentModule);
@@ -46,6 +48,7 @@ public:
bool removeEntity(Entity *entity);
void addSurface(BaseSurface *surface);
bool removeSurface(BaseSurface *surface);
+ void printSurfaces(Console *con);
Sprite *addSprite(Sprite *sprite);
void removeSprite(Sprite *sprite);
void setSurfacePriority(BaseSurface *surface, int priority);
@@ -73,92 +76,96 @@ 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);
}
+
+ uint32 getBackgroundFileHash() const { return _backgroundFileHash; }
+ uint32 getCursorFileHash() const { return _cursorFileHash; }
+
protected:
Module *_parentModule;
Common::Array<Entity*> _entities;
@@ -194,8 +201,9 @@ protected:
HitRectList *_hitRects;
Common::Array<Sprite*> _collisionSprites;
- void (Entity::*_savedUpdateHandlerCb)();
- uint32 (Entity::*_savedMessageHandlerCb)(int messageNum, const MessageParam &param, Entity *sender);
+ // Used for debugging
+ uint32 _backgroundFileHash, _cursorFileHash; // for StaticScene and all Scene* classes
+
int _messageValue;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
bool queryPositionSprite(int16 mouseX, int16 mouseY);
@@ -221,6 +229,14 @@ protected:
void insertMouse(Mouse *mouseCursor);
};
+
+class StaticScene : public Scene {
+public:
+ StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash);
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
} // End of namespace Neverhood
#endif /* NEVERHOOD_SCENE_H */
diff --git a/engines/neverhood/screen.cpp b/engines/neverhood/screen.cpp
index 5a748cfab4..901ab73b39 100644
--- a/engines/neverhood/screen.cpp
+++ b/engines/neverhood/screen.cpp
@@ -27,17 +27,18 @@ namespace Neverhood {
Screen::Screen(NeverhoodEngine *vm)
: _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL),
- _yOffset(0), _fullRefresh(false) {
-
+ _yOffset(0), _fullRefresh(false), _frameDelay(0), _savedSmackerDecoder(NULL),
+ _savedFrameDelay(0), _savedYOffset(0) {
+
_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() {
@@ -54,7 +55,7 @@ void Screen::update() {
if (_fullRefresh) {
// NOTE When playing a fullscreen/doubled Smacker video usually a full screen refresh is needed
- _vm->_system->copyRectToScreen((const byte*)_backScreen->pixels, _backScreen->pitch, 0, 0, 640, 480);
+ _vm->_system->copyRectToScreen((const byte*)_backScreen->getPixels(), _backScreen->pitch, 0, 0, 640, 480);
_fullRefresh = false;
return;
}
@@ -72,13 +73,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 +94,7 @@ void Screen::update() {
for (RectangleList::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri)
blitRenderItem(renderItem, *ri);
}
-
+
SWAP(_renderQueue, _prevRenderQueue);
_renderQueue->clear();
@@ -174,7 +175,7 @@ void Screen::updatePalette() {
}
void Screen::clear() {
- memset(_backScreen->pixels, 0, _backScreen->pitch * _backScreen->h);
+ memset(_backScreen->getPixels(), 0, _backScreen->pitch * _backScreen->h);
_fullRefresh = true;
clearRenderQueue();
}
@@ -202,12 +203,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 +216,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 +225,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 +243,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,14 +251,14 @@ 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);
}
void Screen::drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &drawRect) {
- const byte *source = (const byte*)surface->getBasePtr(0, 0);
+ const byte *source = (const byte*)surface->getPixels();
byte *dest = (byte*)_backScreen->getBasePtr(drawRect.x, drawRect.y);
for (int16 yc = 0; yc < surface->h; yc++) {
@@ -270,13 +271,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 +293,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 +322,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 +332,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 +351,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 +370,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/screen.h b/engines/neverhood/screen.h
index c778066152..a9b5af02f6 100644
--- a/engines/neverhood/screen.h
+++ b/engines/neverhood/screen.h
@@ -79,7 +79,6 @@ public:
void drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect, NRect &clipRect, bool transparent, byte version,
const Graphics::Surface *shadowSurface = NULL);
void drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, NDrawRect &drawRect, NRect &clipRect, bool transparent, byte version);
- void drawShadowSurface(const Graphics::Surface *surface, const Graphics::Surface *shadowSurface, int16 x, int16 y, NDrawRect &drawRect, NRect &clipRect);
void drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &drawRect);
void drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDrawRect &sysRect, NRect &clipRect, bool transparent, byte version);
void drawSurfaceClipRects(const Graphics::Surface *surface, NDrawRect &drawRect, NRect *clipRects, uint clipRectsCount, bool transparent, byte version);
diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp
index b67c8db9fc..187939faee 100644
--- a/engines/neverhood/smackerplayer.cpp
+++ b/engines/neverhood/smackerplayer.cpp
@@ -31,7 +31,7 @@ namespace Neverhood {
// SmackerSurface
SmackerSurface::SmackerSurface(NeverhoodEngine *vm)
- : BaseSurface(vm, 0, 0, 0), _smackerFrame(NULL) {
+ : BaseSurface(vm, 0, 0, 0, "smacker"), _smackerFrame(NULL) {
}
void SmackerSurface::draw() {
@@ -51,6 +51,18 @@ void SmackerSurface::setSmackerFrame(const Graphics::Surface *smackerFrame) {
_smackerFrame = smackerFrame;
}
+void SmackerSurface::unsetSmackerFrame() {
+ _drawRect.x = 0;
+ _drawRect.y = 0;
+ _drawRect.width = 0;
+ _drawRect.height = 0;
+ _sysRect.x = 0;
+ _sysRect.y = 0;
+ _sysRect.width = 0;
+ _sysRect.height = 0;
+ _smackerFrame = NULL;
+}
+
// SmackerDoubleSurface
SmackerDoubleSurface::SmackerDoubleSurface(NeverhoodEngine *vm)
@@ -62,25 +74,27 @@ void SmackerDoubleSurface::draw() {
_vm->_screen->drawDoubleSurface2(_smackerFrame, _drawRect);
}
+// NeverhoodSmackerDecoder
+
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);
}
@@ -92,40 +106,43 @@ SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash,
_drawX(-1), _drawY(-1) {
SetUpdateHandler(&SmackerPlayer::update);
+
+ if (_doubleSurface) {
+ _smackerSurface = new SmackerDoubleSurface(_vm);
+ } else {
+ _smackerSurface = new SmackerSurface(_vm);
+ }
+
open(fileHash, flag);
}
SmackerPlayer::~SmackerPlayer() {
close();
+ delete _smackerSurface;
+ _smackerSurface = NULL;
}
void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) {
debug(0, "SmackerPlayer::open(%08X)", fileHash);
-
+
_fileHash = fileHash;
_keepLastFrame = keepLastFrame;
close();
- if (_doubleSurface) {
- _smackerSurface = new SmackerDoubleSurface(_vm);
- } else {
- _smackerSurface = new SmackerSurface(_vm);
- }
-
_smackerFirst = true;
_stream = _vm->_res->createStream(fileHash);
_smackerDecoder = new NeverhoodSmackerDecoder();
_smackerDecoder->loadStream(_stream);
-
+
_palette = new Palette(_vm);
_palette->usePalette();
if (!_paused)
_smackerDecoder->start();
-
+
}
void SmackerPlayer::close() {
@@ -134,11 +151,10 @@ void SmackerPlayer::close() {
delete _smackerDecoder;
delete _palette;
// NOTE The SmackerDecoder deletes the _stream
- delete _smackerSurface;
_smackerDecoder = NULL;
_palette = NULL;
_stream = NULL;
- _smackerSurface = NULL;
+ _smackerSurface->unsetSmackerFrame();
}
void SmackerPlayer::gotoFrame(int frameNumber) {
@@ -196,10 +212,14 @@ void SmackerPlayer::update() {
_videoDone = false;
}
}
-
+
}
void SmackerPlayer::updateFrame() {
+
+ if (!_smackerDecoder || !_smackerSurface)
+ return;
+
const Graphics::Surface *smackerFrame = _smackerDecoder->decodeNextFrame();
if (_smackerFirst) {
@@ -220,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 26ebff5d33..dd7199dd6d 100644
--- a/engines/neverhood/smackerplayer.h
+++ b/engines/neverhood/smackerplayer.h
@@ -37,6 +37,7 @@ public:
SmackerSurface(NeverhoodEngine *vm);
virtual void draw();
void setSmackerFrame(const Graphics::Surface *smackerFrame);
+ void unsetSmackerFrame();
protected:
const Graphics::Surface *_smackerFrame;
};
@@ -61,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/smackerscene.h b/engines/neverhood/smackerscene.h
index 7ed2e0262b..8e5084512f 100644
--- a/engines/neverhood/smackerscene.h
+++ b/engines/neverhood/smackerscene.h
@@ -36,6 +36,7 @@ public:
void setFileHash(uint32 fileHash);
void setFileHashList(const uint32 *fileHashList);
void nextVideo();
+ uint32 getSmackerFileHash() const { return _fileHash[0]; }
protected:
bool _doubleSurface;
bool _canSkip;
diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp
index c84b751e44..3ea45491a7 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;
@@ -250,14 +250,36 @@ void SoundItem::update() {
// SoundMan
SoundMan::SoundMan(NeverhoodEngine *vm)
- : _vm(vm), _soundIndex1(-1), _soundIndex2(-1), _soundIndex3(-1) {
+ : _vm(vm), _soundIndex1(-1), _soundIndex2(-1), _soundIndex3(-1),
+ _initialCountdown(0), _playOnceAfterCountdown(false),
+ _initialCountdown3(0), _playOnceAfterCountdown3(false) {
}
SoundMan::~SoundMan() {
- for (uint i = 0; i < _soundItems.size(); ++i)
- delete _soundItems[i];
- for (uint i = 0; i < _musicItems.size(); ++i)
- delete _musicItems[i];
+ stopAllMusic();
+ stopAllSounds();
+}
+
+void SoundMan::stopAllMusic() {
+ for (uint i = 0; i < _musicItems.size(); ++i) {
+ if (_musicItems[i]) {
+ _musicItems[i]->stopMusic(0, 0);
+ delete _musicItems[i];
+ _musicItems[i] = NULL;
+ }
+ }
+}
+
+void SoundMan::stopAllSounds() {
+ for (uint i = 0; i < _soundItems.size(); ++i) {
+ if (_soundItems[i]) {
+ _soundItems[i]->stopSound();
+ delete _soundItems[i];
+ _soundItems[i] = NULL;
+ }
+ }
+
+ _soundIndex1 = _soundIndex2 = _soundIndex3 = -1;
}
void SoundMan::addMusic(uint32 groupNameHash, uint32 musicFileHash) {
@@ -345,7 +367,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)
@@ -440,7 +462,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) {
@@ -514,16 +536,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--) {
@@ -557,7 +579,7 @@ AudioResourceManSoundItem::AudioResourceManSoundItem(NeverhoodEngine *vm, uint32
void AudioResourceManSoundItem::loadSound() {
if (!_data && _resourceHandle.isValid() &&
(_resourceHandle.type() == kResTypeSound || _resourceHandle.type() == kResTypeMusic)) {
- _vm->_res->loadResource(_resourceHandle);
+ _vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_data = _resourceHandle.data();
}
}
@@ -607,7 +629,8 @@ bool AudioResourceManSoundItem::isPlaying() {
AudioResourceManMusicItem::AudioResourceManMusicItem(NeverhoodEngine *vm, uint32 fileHash)
: _vm(vm), _fileHash(fileHash), _terminate(false), _canRestart(false),
- _volume(100), _panning(50), _start(false), _isFadingIn(false), _isFadingOut(false), _isPlaying(false) {
+ _volume(100), _panning(50), _start(false), _isFadingIn(false), _isFadingOut(false), _isPlaying(false),
+ _fadeVolume(0), _fadeVolumeStep(0) {
}
@@ -678,7 +701,7 @@ void AudioResourceManMusicItem::update() {
_start = false;
_isPlaying = true;
}
-
+
if (_vm->_mixer->isSoundHandleActive(_soundHandle)) {
if (_isFadingIn) {
_fadeVolume += _fadeVolumeStep;
@@ -708,11 +731,29 @@ AudioResourceMan::AudioResourceMan(NeverhoodEngine *vm)
: _vm(vm) {
}
+void AudioResourceMan::stopAllMusic() {
+ for (uint i = 0; i < _musicItems.size(); ++i) {
+ if (_musicItems[i]) {
+ _musicItems[i]->stopMusic(0);
+ delete _musicItems[i];
+ _musicItems[i] = NULL;
+ }
+ }
+}
+
+void AudioResourceMan::stopAllSounds() {
+ for (uint i = 0; i < _soundItems.size(); ++i) {
+ if (_soundItems[i]) {
+ _soundItems[i]->stopSound();
+ delete _soundItems[i];
+ _soundItems[i] = NULL;
+ }
+ }
+}
+
AudioResourceMan::~AudioResourceMan() {
- for (uint i = 0; i < _soundItems.size(); ++i)
- delete _soundItems[i];
- for (uint i = 0; i < _musicItems.size(); ++i)
- delete _musicItems[i];
+ stopAllMusic();
+ stopAllSounds();
}
int16 AudioResourceMan::addSound(uint32 fileHash) {
@@ -757,11 +798,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 d3318998db..548fe88501 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;
@@ -129,12 +129,15 @@ public:
SoundMan(NeverhoodEngine *vm);
~SoundMan();
+ void stopAllMusic();
+ void stopAllSounds();
+
// Music
void addMusic(uint32 groupNameHash, uint32 musicFileHash);
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);
@@ -146,7 +149,7 @@ public:
void playSoundLooping(uint32 soundFileHash);
void stopSound(uint32 soundFileHash);
void setSoundVolume(uint32 soundFileHash, int volume);
-
+
// Misc
void update();
void deleteGroup(uint32 groupNameHash);
@@ -159,25 +162,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 {
@@ -207,7 +210,7 @@ private:
// TODO Rename these
class AudioResourceManSoundItem {
-public:
+public:
AudioResourceManSoundItem(NeverhoodEngine *vm, uint32 fileHash);
void loadSound();
void unloadSound();
@@ -216,7 +219,7 @@ public:
void playSound(bool looping);
void stopSound();
bool isPlaying();
-protected:
+protected:
NeverhoodEngine *_vm;
uint32 _fileHash;
ResourceHandle _resourceHandle;
@@ -241,7 +244,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;
@@ -261,16 +264,19 @@ class AudioResourceMan {
public:
AudioResourceMan(NeverhoodEngine *vm);
~AudioResourceMan();
-
+
+ void stopAllMusic();
+ void stopAllSounds();
+
int16 addSound(uint32 fileHash);
void removeSound(int16 soundIndex);
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 45d131fd3c..1a432461fb 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) {
@@ -83,7 +83,7 @@ void Sprite::loadDataResource(uint32 fileHash) {
}
void Sprite::createSurface(int surfacePriority, int16 width, int16 height) {
- _surface = new BaseSurface(_vm, surfacePriority, width, height);
+ _surface = new BaseSurface(_vm, surfacePriority, width, height, "sprite");
}
int16 Sprite::defFilterY(int16 y) {
@@ -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 {
@@ -211,6 +211,12 @@ void AnimatedSprite::init() {
_replNewColor = 0;
_animResource.setReplEnabled(false);
_playBackwards = false;
+ _currAnimFileHash = 0;
+ _lastFrameIndex = 0;
+ _plLastFrameIndex = 0;
+ _plFirstFrameHash = 0;
+ _plLastFrameHash = 0;
+ _animStatus = 0;
}
void AnimatedSprite::update() {
@@ -261,7 +267,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 +276,7 @@ void AnimatedSprite::updateAnim() {
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
- _animResource.setRepl(_replOldColor, _replNewColor);
+ _animResource.setRepl(_replOldColor, _replNewColor);
}
_nextAnimFileHash = 0;
if (_animStatus != 0) {
@@ -278,17 +284,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 +307,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 +320,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;
@@ -398,7 +404,7 @@ void AnimatedSprite::updateFrameInfo() {
void AnimatedSprite::createSurface1(uint32 fileHash, int surfacePriority) {
NDimensions dimensions = _animResource.loadSpriteDimensions(fileHash);
- _surface = new BaseSurface(_vm, surfacePriority, dimensions.width, dimensions.height);
+ _surface = new BaseSurface(_vm, surfacePriority, dimensions.width, dimensions.height, "animated sprite");
}
void AnimatedSprite::createShadowSurface1(BaseSurface *shadowSurface, uint32 fileHash, int surfacePriority) {
diff --git a/engines/neverhood/sprite.h b/engines/neverhood/sprite.h
index 80da1768bd..1d17bf0e70 100644
--- a/engines/neverhood/sprite.h
+++ b/engines/neverhood/sprite.h
@@ -30,9 +30,24 @@
namespace Neverhood {
-#define SetSpriteUpdate(callback) _spriteUpdateCb = static_cast <void (Sprite::*)(void)> (callback); debug(2, "SetSpriteUpdate(" #callback ")"); _spriteUpdateCbName = #callback
-#define SetFilterX(callback) _filterXCb = static_cast <int16 (Sprite::*)(int16)> (callback); debug(2, "SetFilterX(" #callback ")")
-#define SetFilterY(callback) _filterYCb = static_cast <int16 (Sprite::*)(int16)> (callback); debug(2, "SetFilterY(" #callback ")")
+#define SetSpriteUpdate(callback) \
+ do { \
+ _spriteUpdateCb = static_cast <void (Sprite::*)(void)> (callback); \
+ debug(2, "SetSpriteUpdate(" #callback ")"); \
+ _spriteUpdateCbName = #callback; \
+ } while (0)
+
+#define SetFilterX(callback) \
+ do { \
+ _filterXCb = static_cast <int16 (Sprite::*)(int16)> (callback); \
+ debug(2, "SetFilterX(" #callback ")"); \
+ } while (0)
+
+#define SetFilterY(callback) \
+ do { \
+ _filterYCb = static_cast <int16 (Sprite::*)(int16)> (callback); \
+ debug(2, "SetFilterY(" #callback ")"); \
+ } while (0)
const int16 kDefPosition = -32768;
@@ -113,7 +128,11 @@ protected:
#define AnimationCallback(callback) static_cast <void (AnimatedSprite::*)()> (callback)
#define GotoState(callback) gotoState(static_cast <void (AnimatedSprite::*)()> (callback))
-#define NextState(callback) _nextStateCb = static_cast <void (AnimatedSprite::*)(void)> (callback); debug(2, "NextState(" #callback ")"); _nextStateCbName = #callback
+#define NextState(callback) \
+ do { \
+ _nextStateCb = static_cast <void (AnimatedSprite::*)(void)> (callback); \
+ debug(2, "NextState(" #callback ")"); _nextStateCbName = #callback; \
+ } while (0)
#define FinalizeState(callback) setFinalizeState(static_cast <void (AnimatedSprite::*)()> (callback));
const int STICK_LAST_FRAME = -2;
diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp
index 3f89c2236f..ec9c852118 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);
@@ -53,6 +53,22 @@ void StaticData::load(const char *filename) {
messageItem.messageValue = fd.readUint32LE();
messageList->push_back(messageItem);
}
+
+ // WORKAROUND for a problem in two of the game's message lists:
+ // the message lists used when Klaymen is drinking the wrong potion
+ // have as a last element the animation itself (message 0x4832).
+ // However, when processMessageList() reaches the last element in a
+ // message list, it allows player input, which means that the player
+ // can erroneously skip these potion drinking animations. We insert
+ // another message at the end of these lists to prevent player input
+ // till the animations are finished
+ if (id == 0x004AF0C8 || id == 0x004B5BD0) { // wrong potion message lists
+ MessageItem messageItem;
+ messageItem.messageNum = 0x4004; // set Klaymen's state to idle
+ messageItem.messageValue = 0;
+ messageList->push_back(messageItem);
+ }
+
_messageLists[id] = messageList;
}
@@ -84,7 +100,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/parallaction/POTFILES b/engines/parallaction/POTFILES
new file mode 100644
index 0000000000..f3b1c45afa
--- /dev/null
+++ b/engines/parallaction/POTFILES
@@ -0,0 +1 @@
+engines/parallaction/saveload.cpp
diff --git a/engines/parallaction/configure.engine b/engines/parallaction/configure.engine
new file mode 100644
index 0000000000..babca4579f
--- /dev/null
+++ b/engines/parallaction/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine parallaction "Parallaction" yes
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 25acac9b06..4a8f8c71d7 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -62,8 +62,8 @@ void Debugger::postEnter() {
bool Debugger::Cmd_Location(int argc, const char **argv) {
- const char *character = _vm->_char.getName();
- const char *location = _vm->_location._name;
+ const char *character; // = _vm->_char.getName();
+ const char *location; // = _vm->_location._name;
char tmp[PATH_LEN];
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 3135c3e8c5..f648f4b9a1 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -225,7 +225,7 @@ void DosDisk_br::loadBitmap(Common::SeekableReadStream &stream, Graphics::Surfac
}
surf.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- stream.read(surf.pixels, width * height);
+ stream.read(surf.getPixels(), width * height);
}
Frames* DosDisk_br::loadPointer(const char *name) {
@@ -449,7 +449,7 @@ void AmigaDisk_br::init() {
void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColor) {
uint size = surf.w * surf.h;
- byte *data = (byte *)surf.pixels;
+ byte *data = (byte *)surf.getPixels();
for (uint i = 0; i < size; i++, data++) {
if (transparentColor == -1 || transparentColor != *data)
*data += 16;
@@ -552,7 +552,7 @@ MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) {
MaskBuffer *buffer = new MaskBuffer;
// surface width was shrunk to 1/4th of the bitmap width due to the pixel packing
buffer->create(decoder.getSurface()->w * 4, decoder.getSurface()->h);
- memcpy(buffer->data, decoder.getSurface()->pixels, buffer->size);
+ memcpy(buffer->data, decoder.getSurface()->getPixels(), buffer->size);
buffer->bigEndian = true;
finalpass(buffer->data, buffer->size);
return buffer;
@@ -612,7 +612,7 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) {
stream->read(shadow, shadowSize);
for (int32 i = 0; i < surf->h; ++i) {
byte *src = shadow + shadowWidth * i;
- byte *dst = (byte *)surf->pixels + surf->pitch * i;
+ byte *dst = (byte *)surf->getPixels() + surf->pitch * i;
for (int32 j = 0; j < surf->w; ++j, ++dst) {
byte bit = src[j/8] & (1 << (7 - (j & 7)));
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 4c4893ec61..ae28e864a9 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -482,7 +482,7 @@ void DosDisk_ns::loadBackground(BackgroundInfo& info, const char *filename) {
// read bitmap, mask and path data and extract them into the 3 buffers
info.bg.create(info.width, info.height, Graphics::PixelFormat::createFormatCLUT8());
createMaskAndPathBuffers(info);
- unpackBackground(stream, (byte *)info.bg.pixels, info._mask->data, info._path->data);
+ unpackBackground(stream, (byte *)info.bg.getPixels(), info._mask->data, info._path->data);
delete stream;
}
@@ -976,7 +976,7 @@ void AmigaDisk_ns::loadMask_internal(BackgroundInfo& info, const char *name) {
info._mask = new MaskBuffer;
// surface width was shrunk to 1/4th of the bitmap width due to the pixel packing
info._mask->create(decoder.getSurface()->w * 4, decoder.getSurface()->h);
- memcpy(info._mask->data, decoder.getSurface()->pixels, info._mask->size);
+ memcpy(info._mask->data, decoder.getSurface()->getPixels(), info._mask->size);
info._mask->bigEndian = true;
}
@@ -998,7 +998,7 @@ void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) {
info._path = new PathBuffer;
// surface width was shrunk to 1/8th of the bitmap width due to the pixel packing
info._path->create(decoder.getSurface()->w * 8, decoder.getSurface()->h);
- memcpy(info._path->data, decoder.getSurface()->pixels, info._path->size);
+ memcpy(info._path->data, decoder.getSurface()->getPixels(), info._path->size);
info._path->bigEndian = true;
}
diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h
index b966d677cd..5968954ba0 100644
--- a/engines/parallaction/exec.h
+++ b/engines/parallaction/exec.h
@@ -62,7 +62,7 @@ struct ProgramContext {
AnimationPtr _anim;
ProgramPtr _program;
InstructionPtr _inst;
- uint32 _ip;
+ uint32 _ip;
uint16 _modCounter;
bool _suspend;
};
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index 3ea4332e50..816f220b1f 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -126,9 +126,7 @@ DECLARE_INSTRUCTION_OPCODE(put) {
inst->_a->getFrameRect(r);
Graphics::Surface v18;
- v18.w = r.width();
- v18.h = r.height();
- v18.pixels = inst->_a->getFrameData();
+ v18.init(r.width(), r.height(), r.width(), inst->_a->getFrameData(), Graphics::PixelFormat::createFormatCLUT8());
int16 x = inst->_opA.getValue();
int16 y = inst->_opB.getValue();
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index 03b1ced8e1..627c6ebe22 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -518,6 +518,9 @@ AmigaFont::AmigaFont(Common::SeekableReadStream &stream) {
_charSpace = 0;
_charKern = 0;
+ _cp = 0;
+ _pitch = 0;
+
if (_font->_charSpace != 0)
_charSpace = (uint16 *)(_data + FROM_BE_32(_font->_charSpace));
if (_font->_charKern != 0)
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index b8a8ceb61f..dca1870cb7 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -218,7 +218,7 @@ void Palette::rotate(uint first, uint last, bool forward) {
-void Gfx::setPalette(Palette pal) {
+void Gfx::setPalette(Palette &pal) {
byte sysPal[256*3];
uint n = pal.fillRGB(sysPal);
@@ -332,7 +332,7 @@ void Gfx::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int
void Gfx::clearScreen() {
if (_doubleBuffering) {
- if (_backBuffer.pixels) {
+ if (_backBuffer.getPixels()) {
Common::Rect r(_backBuffer.w, _backBuffer.h);
_backBuffer.fillRect(r, 0);
}
@@ -419,13 +419,13 @@ void Gfx::updateScreen() {
// is needed
_overlayMode = false;
- bool skipBackground = (_backgroundInfo->bg.pixels == 0); // don't render frame if background is missing
+ bool skipBackground = (_backgroundInfo->bg.getPixels() == 0); // don't render frame if background is missing
if (!skipBackground) {
// background may not cover the whole screen, so adjust bulk update size
uint w = _backgroundInfo->width;
uint h = _backgroundInfo->height;
- byte *backgroundData = (byte *)_backgroundInfo->bg.getBasePtr(0, 0);
+ byte *backgroundData = (byte *)_backgroundInfo->bg.getPixels();
uint16 backgroundPitch = _backgroundInfo->bg.pitch;
copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo->_x, _backgroundInfo->_y, w, h);
}
@@ -450,7 +450,7 @@ void Gfx::applyHalfbriteEffect_NS(Graphics::Surface &surf) {
return;
}
- byte *buf = (byte *)surf.pixels;
+ byte *buf = (byte *)surf.getPixels();
for (int i = 0; i < surf.w*surf.h; i++) {
*buf++ |= 0x20;
}
@@ -493,7 +493,7 @@ void Gfx::patchBackground(Graphics::Surface &surf, int16 x, int16 y, bool mask)
r.moveTo(x, y);
uint16 z = (mask) ? _backgroundInfo->getMaskLayer(y) : LAYER_FOREGROUND;
- blt(r, (byte *)surf.pixels, &_backgroundInfo->bg, z, 100, 0);
+ blt(r, (byte *)surf.getPixels(), &_backgroundInfo->bg, z, 100, 0);
}
void Gfx::fillBackground(const Common::Rect& r, byte color) {
@@ -536,12 +536,12 @@ GfxObj *Gfx::renderFloatingLabel(Font *font, char *text) {
setupLabelSurface(*cnv, w, h);
font->setColor((_gameType == GType_BRA) ? 0 : 7);
- font->drawString((byte *)cnv->pixels + 1, cnv->w, text);
- font->drawString((byte *)cnv->pixels + 1 + cnv->w * 2, cnv->w, text);
- font->drawString((byte *)cnv->pixels + cnv->w, cnv->w, text);
- font->drawString((byte *)cnv->pixels + 2 + cnv->w, cnv->w, text);
+ font->drawString((byte *)cnv->getBasePtr(1, 0), cnv->w, text);
+ font->drawString((byte *)cnv->getBasePtr(1, 2), cnv->w, text);
+ font->drawString((byte *)cnv->getBasePtr(0, 1), cnv->w, text);
+ font->drawString((byte *)cnv->getBasePtr(2, 1), cnv->w, text);
font->setColor((_gameType == GType_BRA) ? 11 : 1);
- font->drawString((byte *)cnv->pixels + 1 + cnv->w, cnv->w, text);
+ font->drawString((byte *)cnv->getBasePtr(1, 1), cnv->w, text);
} else {
w = font->getStringWidth(text);
h = font->height();
@@ -704,7 +704,7 @@ void Gfx::unregisterLabel(GfxObj *label) {
void Gfx::copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst) {
byte *s = (byte *)src.getBasePtr(r.left, r.top);
- byte *d = (byte *)dst.getBasePtr(0, 0);
+ byte *d = (byte *)dst.getPixels();
for (uint16 i = 0; i < r.height(); i++) {
memcpy(d, s, r.width());
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 55c1c0c04e..401e753775 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -138,7 +138,7 @@ public:
}
Cnv(uint16 numFrames, uint16 width, uint16 height, byte* data, bool freeData = false)
- : _count(numFrames), _width(width), _height(height), _data(data), _freeData(freeData) {
+ : _count(numFrames), _width(width), _height(height), _data(data), _freeData(freeData), field_8(0) {
}
@@ -465,7 +465,7 @@ public:
void invertBackground(const Common::Rect& r);
// palette
- void setPalette(Palette palette);
+ void setPalette(Palette &palette);
void setBlackPalette();
void animatePalette();
diff --git a/engines/parallaction/gui.h b/engines/parallaction/gui.h
index a6eed240c4..9f2e96475b 100644
--- a/engines/parallaction/gui.h
+++ b/engines/parallaction/gui.h
@@ -43,7 +43,7 @@ class MenuInputHelper {
MenuInputState *_newState;
public:
- MenuInputHelper() : _state(0) {
+ MenuInputHelper() : _state(0), _newState(0) {
}
~MenuInputHelper();
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index ddbc31d730..2ec5ba6e8d 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -196,6 +196,11 @@ class MainMenuInputState_BR : public MenuInputState {
public:
MainMenuInputState_BR(Parallaction_br *vm, MenuInputHelper *helper) : MenuInputState("mainmenu", helper), _vm(vm) {
memset(_lines, 0, sizeof(_lines));
+
+ _menuStrings = 0;
+ _options = 0;
+ _availItems = 0;
+ _selection = 0;
}
~MainMenuInputState_BR() {
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 082c37f666..ae32a416e3 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -117,6 +117,7 @@ public:
_allowChoice = false;
_nextState = "selectgame";
_label = 0;
+ _blocks = 0;
_dosLanguageSelectBlocks[0] = Common::Rect( 80, 110, 128, 180 ); // Italian
_dosLanguageSelectBlocks[1] = Common::Rect( 129, 85, 177, 155 ); // French
@@ -414,7 +415,7 @@ class SelectCharacterInputState_NS : public MenuInputState {
#define CHAR_DONNA 1
#define CHAR_DOUGH 2
- Common::Rect _codeSelectBlocks[9];
+ Common::Rect _codeSelectBlocks[9];
Common::Rect _codeTrueBlocks[9];
Parallaction_ns *_vm;
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index bf7cdc439d..a445ce0138 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -499,7 +499,7 @@ void Input::initCursors() {
// TODO: scale mouse cursor (see staticres.cpp)
Graphics::Surface *surf2 = new Graphics::Surface;
surf2->create(32, 16, Graphics::PixelFormat::createFormatCLUT8());
- memcpy(surf2->pixels, _resMouseArrow_BR_Amiga, 32*16);
+ memcpy(surf2->getPixels(), _resMouseArrow_BR_Amiga, 32*16);
_mouseArrow = new SurfaceToFrames(surf2);
}
break;
diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h
index a815469ec3..a303eb96c8 100644
--- a/engines/parallaction/input.h
+++ b/engines/parallaction/input.h
@@ -114,7 +114,7 @@ public:
void trackMouse(ZonePtr z);
void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1);
uint32 getLastButtonEvent() { return _mouseButtons; }
- bool getLastKeyDown(uint16 &ascii);
+ bool getLastKeyDown(uint16 &ascii);
void stopHovering();
diff --git a/engines/parallaction/inventory.h b/engines/parallaction/inventory.h
index a3b7bf953f..d5cf8badf0 100644
--- a/engines/parallaction/inventory.h
+++ b/engines/parallaction/inventory.h
@@ -108,7 +108,7 @@ public:
void highlightItem(ItemPosition pos, byte color);
void drawItem(ItemName name, byte *buffer, uint pitch);
- byte* getData() const { return (byte *)_surf.pixels; }
+ byte *getData() { return (byte *)_surf.getPixels(); }
void getRect(Common::Rect &r) const;
int16 getNumLines() const;
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index 81761b2c6b..89e8134431 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -147,7 +147,7 @@ typedef Common::List<CommandPtr> CommandList;
struct Answer {
Common::String _text;
uint16 _mood;
- Common::String _followingName;
+ Common::String _followingName;
CommandList _commands;
uint32 _noFlags;
@@ -188,7 +188,7 @@ struct Dialogue {
~Dialogue();
};
-#define MAX_WALKPOINT_LISTS 20
+#define MAX_WALKPOINT_LISTS 20
#define FREE_HEAR_CHANNEL -1
#define MUSIC_HEAR_CHANNEL -2
@@ -452,7 +452,7 @@ struct Program {
uint16 _numLocals;
uint32 _ip;
- uint32 _loopStart;
+ uint32 _loopStart;
InstructionList _instructions;
uint32 _status;
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index f868abfbf4..e7be1eb8a3 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -59,6 +59,33 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
DebugMan.addDebugChannel(kDebugAudio, "audio", "Audio debug level");
DebugMan.addDebugChannel(kDebugMenu, "menu", "Menu debug level");
DebugMan.addDebugChannel(kDebugInventory, "inventory", "Inventory debug level");
+
+ _screenHeight = 0;
+ _screenSize = 0;
+ _gameType = 0;
+ _gfx = 0;
+ _disk = 0;
+ _input = 0;
+ _debugger = 0;
+ _saveLoad = 0;
+ _menuHelper = 0;
+ _soundMan = 0;
+ _labelFont = 0;
+ _menuFont = 0;
+ _introFont = 0;
+ _dialogueFont = 0;
+ _globalFlagsNames = 0;
+ _objectsNames = 0;
+ _objects = 0;
+ _callableNames = 0;
+ _localFlagNames = 0;
+ _cmdExec = 0;
+ _programExec = 0;
+ _balloonMan = 0;
+ _inventoryRenderer = 0;
+ _inventory = 0;
+ _currentLocationIndex = 0;
+ _numLocations = 0;
}
Parallaction::~Parallaction() {
@@ -882,6 +909,9 @@ void CharacterName::dummify() {
CharacterName::CharacterName() {
dummify();
+
+ _suffix = 0;
+ _prefix = 0;
}
CharacterName::CharacterName(const char *name) {
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 2dbb0227d6..203a0168ea 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -360,7 +360,7 @@ public:
uint32 getLocationFlags();
bool checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y);
bool checkZoneBox(ZonePtr z, uint32 type, uint x, uint y);
- bool checkZoneType(ZonePtr z, uint32 type);
+ bool checkZoneType(ZonePtr z, uint32 type);
bool checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
void runZone(ZonePtr z);
@@ -579,7 +579,7 @@ private:
void freeLocation(bool removeAll);
void loadProgram(AnimationPtr a, const char *filename);
void startGui(bool showSplash);
- void startIngameMenu();
+ void startIngameMenu();
void freeCharacter();
typedef void (Parallaction_br::*Callable)(void *);
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index f9df9d85db..586e4bbd6a 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -45,6 +45,18 @@ const char *Parallaction_br::_partNames[] = {
Parallaction_br::Parallaction_br(OSystem* syst, const PARALLACTIONGameDescription *gameDesc) : Parallaction(syst, gameDesc),
_locationParser(0), _programParser(0), _soundManI(0) {
+ _audioCommandsNamesRes = 0;
+ _part = 0;
+ _nextPart = 0;
+ _subtitleY = 0;
+ _subtitle[0] = 0;
+ _subtitle[1] = 0;
+ _charInventories[0] = 0;
+ _charInventories[1] = 0;
+ _charInventories[2] = 0;
+ _countersNames = 0;
+ _callables = 0;
+ _walker = 0;
}
Common::Error Parallaction_br::init() {
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 49b63dcac3..91e8c78fc2 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -145,6 +145,18 @@ void LocationName::bind(const char *s) {
Parallaction_ns::Parallaction_ns(OSystem* syst, const PARALLACTIONGameDescription *gameDesc) : Parallaction(syst, gameDesc),
_locationParser(0), _programParser(0), _walker(0) {
+ _soundManI = 0;
+ _score = 0;
+ _inTestResult = 0;
+ _callables = 0;
+ num_foglie = 0;
+ _sarcophagusDeltaX = 0;
+ _movingSarcophagus = 0;
+ _freeSarcophagusSlotX = 0;
+ _intro = 0;
+
+ _testResultLabels[0] = 0;
+ _testResultLabels[1] = 0;
}
Common::Error Parallaction_ns::init() {
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index 3e2604eda2..622e507aad 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -207,6 +207,11 @@ protected:
public:
LocationParser_ns(Parallaction_ns *vm) : _vm(vm), _commandsNames(0), _locationStmt(0),
_locationZoneStmt(0), _locationAnimStmt(0) {
+ _script = 0;
+ _parser = 0;
+ _zoneTypeNames = 0;
+ _zoneFlagNames = 0;
+ _zoneProg = 0;
}
virtual void init();
@@ -292,14 +297,14 @@ public:
virtual void parseGetData(ZonePtr z);
virtual void parseDoorData(ZonePtr z);
virtual void parseHearData(ZonePtr z);
- virtual void parseNoneData(ZonePtr z);
+ virtual void parseNoneData(ZonePtr z);
protected:
void parseAnswerCounter(Answer *answer);
virtual Answer *parseAnswer();
public:
LocationParser_br(Parallaction_br *vm) : LocationParser_ns((Parallaction_ns*)vm), _vm(vm),
- _audioCommandsNames(0) {
+ _audioCommandsNames(0), _out(0) {
}
virtual void init();
@@ -363,7 +368,7 @@ protected:
}
public:
- ProgramParser_ns(Parallaction_ns *vm) : _vm(vm), _parser(0), _instructionNames(0) {
+ ProgramParser_ns(Parallaction_ns *vm) : _vm(vm), _parser(0), _instructionNames(0), _script(0), _currentInstruction(0) {
}
virtual void init();
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index e12e50e278..e8dde78ddc 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -103,7 +103,7 @@ protected:
Audio::Mixer *_mixer;
char _musicFile[PATH_LEN];
- bool _sfxLooping;
+ bool _sfxLooping;
int _sfxVolume;
int _sfxRate;
uint _sfxChannel;
@@ -156,7 +156,7 @@ class AmigaSoundMan_ns : public SoundMan_ns {
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle;
- uint32 beepSoundBufferSize;
+ uint32 beepSoundBufferSize;
int8 *beepSoundBuffer;
Channel _channels[NUM_SFX_CHANNELS];
@@ -188,7 +188,7 @@ protected:
Common::String _musicFile;
- bool _sfxLooping;
+ bool _sfxLooping;
int _sfxVolume;
int _sfxRate;
uint _sfxChannel;
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 4a643aaf1d..ea769de9e8 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -207,6 +207,7 @@ public:
void play(Common::SeekableReadStream *stream);
virtual void pause(bool p);
+ virtual void pause() { assert(0); } // overridden
virtual void setVolume(int volume);
virtual void onTimer();
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index 0ee3d73556..ed3031e94e 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -43,6 +43,7 @@ public:
void play(Common::SeekableReadStream *stream);
void pause(bool p);
+ virtual void pause() { assert(0); } // overridden
virtual void onTimer();
private:
diff --git a/engines/pegasus/POTFILES b/engines/pegasus/POTFILES
new file mode 100644
index 0000000000..c06cb07479
--- /dev/null
+++ b/engines/pegasus/POTFILES
@@ -0,0 +1 @@
+engines/pegasus/pegasus.cpp
diff --git a/engines/pegasus/configure.engine b/engines/pegasus/configure.engine
new file mode 100644
index 0000000000..ed7e295287
--- /dev/null
+++ b/engines/pegasus/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit"
diff --git a/engines/pegasus/cursor.cpp b/engines/pegasus/cursor.cpp
index 897d31d7bd..ad0d2c2d7d 100644
--- a/engines/pegasus/cursor.cpp
+++ b/engines/pegasus/cursor.cpp
@@ -85,9 +85,9 @@ void Cursor::setCurrentFrameIndex(int32 index) {
if (_info[index].surface->format.bytesPerPixel == 1) {
CursorMan.replaceCursorPalette(_info[index].palette, 0, _info[index].colorCount);
- CursorMan.replaceCursor(_info[index].surface->pixels, _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, 0);
+ CursorMan.replaceCursor(_info[index].surface->getPixels(), _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, 0);
} else {
- CursorMan.replaceCursor(_info[index].surface->pixels, _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, _info[index].surface->format.RGBToColor(0xFF, 0xFF, 0xFF), false, &_info[index].surface->format);
+ CursorMan.replaceCursor(_info[index].surface->getPixels(), _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, _info[index].surface->format.RGBToColor(0xFF, 0xFF, 0xFF), false, &_info[index].surface->format);
}
((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty();
@@ -203,7 +203,7 @@ void Cursor::loadCursorImage(CursorInfo &cursorInfo) {
// PixMap data
if (pixMap.pixelSize == 8) {
cursorInfo.surface->create(pixMap.rowBytes, pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8());
- cicnStream->read(cursorInfo.surface->pixels, pixMap.rowBytes * pixMap.bounds.height());
+ cicnStream->read(cursorInfo.surface->getPixels(), pixMap.rowBytes * pixMap.bounds.height());
// While this looks sensible, it actually doesn't work for some cursors
// (ie. the 'can grab' hand)
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
index 8dbd678809..5475108abd 100644
--- a/engines/pegasus/graphics.cpp
+++ b/engines/pegasus/graphics.cpp
@@ -318,7 +318,7 @@ void GraphicsManager::shakeTheWorld(TimeValue duration, TimeScale scale) {
}
if (lastOffset.x != 0 || lastOffset.y != 0) {
- g_system->copyRectToScreen((byte *)oldScreen.pixels, oldScreen.pitch, 0, 0, 640, 480);
+ g_system->copyRectToScreen((byte *)oldScreen.getPixels(), oldScreen.pitch, 0, 0, 640, 480);
g_system->updateScreen();
}
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
index 9a378a6728..0b3e1ee040 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
@@ -200,7 +200,7 @@ void Caldoria::start() {
const Graphics::Surface *frame = pullbackMovie->decodeNextFrame();
assert(frame);
assert(frame->format == g_system->getScreenFormat());
- g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h);
+ g_system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 64, 112, frame->w, frame->h);
_vm->_gfx->doFadeInSync(kTwoSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond);
bool saveAllowed = _vm->swapSaveAllowed(false);
@@ -216,7 +216,7 @@ void Caldoria::start() {
frame = pullbackMovie->decodeNextFrame();
if (frame) {
- g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h);
+ g_system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 64, 112, frame->w, frame->h);
g_system->updateScreen();
}
}
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/delta/globegame.cpp b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
index 1416c51c8d..0b95e9bc2b 100644
--- a/engines/pegasus/neighborhood/norad/delta/globegame.cpp
+++ b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
@@ -905,6 +905,11 @@ void GlobeGame::clickGlobe(const Input &input) {
_monitorMovie.start();
_owner->requestSpotSound(kMaximumDeactivationIn, kMaximumDeactivationOut,
kFilterNoInput, kSpotSoundCompletedFlag);
+
+ // This sound was left out of the original.
+ _owner->requestSpotSound(kAllSilosDeactivatedIn, kAllSilosDeactivatedOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+
_gameState = kPlayerWon1;
} else {
_owner->requestDelay(2, 1, kFilterNoInput, kDelayCompletedFlag);
@@ -1060,12 +1065,13 @@ void GlobeGame::doSolve() {
_upperNamesMovie.hide();
_lowerNamesMovie.hide();
_countdown.hide();
- _monitorMovie.setSegment(kMaxDeactivatedStart * _monitorMovie.getScale(), kMaxDeactivatedStop * _monitorMovie.getScale());
- _monitorMovie.setTime(kMaxDeactivatedStart * _monitorMovie.getScale());
+ _monitorMovie.setSegment(kMaxDeactivatedStart * _monitorMovie.getScale() + (kSiloDeactivatedOut - kSiloDeactivatedIn), kMaxDeactivatedStop * _monitorMovie.getScale());
+ _monitorMovie.setTime(kMaxDeactivatedStart * _monitorMovie.getScale() + (kSiloDeactivatedOut - kSiloDeactivatedIn));
_monitorCallBack.setCallBackFlag(kMaxDeactivatedFinished);
_monitorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
_monitorMovie.start();
_owner->requestSpotSound(kMaximumDeactivationIn, kMaximumDeactivationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ _owner->requestSpotSound(kAllSilosDeactivatedIn, kAllSilosDeactivatedOut, kFilterNoInput, kSpotSoundCompletedFlag);
_gameState = kPlayerWon1;
}
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
index f2ea53ff89..1eea2f0156 100644
--- a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
@@ -565,6 +565,11 @@ void NoradDelta::activateHotspots() {
} else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad59, kWest)) {
if (GameState.isCurrentDoorOpen())
_vm->getAllHotspots().deactivateOneHotspot(kNorad59WestSpotID);
+ } else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
+ // WORKAROUND: Make sure the retinal hotspot is disabled after the door opens.
+ // Fixes a bug in the original.
+ if (GameState.isCurrentDoorOpen())
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad68WestSpotID);
}
}
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/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
index 9b843da5d6..99efe10272 100644
--- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
@@ -2653,7 +2653,6 @@ void FullTSA::receiveNotification(Notification *notification, const Notification
GameState.setWSCAnalyzerOn(false);
GameState.setWSCDartInAnalyzer(false);
GameState.setWSCAnalyzedDart(false);
- GameState.setWSCPickedUpAntidote(false);
GameState.setWSCSawMorph(false);
GameState.setWSCDesignedAntidote(false);
GameState.setWSCOfficeMessagesOpen(false);
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
index 4f109620c1..0d11f5d904 100644
--- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
@@ -337,7 +337,6 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification
GameState.setWSCRemovedDart(false);
GameState.setWSCAnalyzerOn(false);
GameState.setWSCAnalyzedDart(false);
- GameState.setWSCPickedUpAntidote(false);
GameState.setWSCSawMorph(false);
GameState.setWSCDesignedAntidote(false);
GameState.setWSCOfficeMessagesOpen(false);
diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp
index 50b7774da4..09e2a48a52 100644
--- a/engines/pegasus/neighborhood/wsc/wsc.cpp
+++ b/engines/pegasus/neighborhood/wsc/wsc.cpp
@@ -2336,13 +2336,16 @@ Hotspot *WSC::getItemScreenSpot(Item *item, DisplayElement *element) {
void WSC::pickedUpItem(Item *item) {
switch (item->getObjectID()) {
case kAntidote:
+ // WORKAROUND: Make sure the poison is cleared separately from deactivating
+ // the synthesizer video.
+ GameState.setWSCPoisoned(false);
+ GameState.setWSCRemovedDart(false);
+ _privateFlags.setFlag(kWSCDraggingAntidoteFlag, false);
+ playSpotSoundSync(kDrinkAntidoteIn, kDrinkAntidoteOut);
+ setUpPoison();
+
if (!GameState.getWSCPickedUpAntidote()) {
- GameState.setWSCPoisoned(false);
- GameState.setWSCRemovedDart(false);
GameState.setWSCPickedUpAntidote(true);
- _privateFlags.setFlag(kWSCDraggingAntidoteFlag, false);
- playSpotSoundSync(kDrinkAntidoteIn, kDrinkAntidoteOut);
- setUpPoison();
startExtraSequence(kW03SouthDeactivate, kExtraCompletedFlag, kFilterNoInput);
}
break;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 463e81e52e..3bd29ce8dd 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -313,7 +313,7 @@ void PegasusEngine::runIntro() {
const Graphics::Surface *frame = video->decodeNextFrame();
if (frame) {
- _system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 0, 0, frame->w, frame->h);
+ _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
_system->updateScreen();
}
}
@@ -1367,7 +1367,7 @@ bool PegasusEngine::playMovieScaled(Video::VideoDecoder *video, uint16 x, uint16
if (frame->w <= 320 && frame->h <= 240) {
drawScaledFrame(frame, x, y);
} else {
- _system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
_system->updateScreen();
}
}
@@ -2270,11 +2270,11 @@ void PegasusEngine::drawScaledFrame(const Graphics::Surface *frame, uint16 x, ui
scaledFrame.create(frame->w * 2, frame->h * 2, frame->format);
if (frame->format.bytesPerPixel == 2)
- scaleFrame<uint16>((uint16 *)frame->pixels, (uint16 *)scaledFrame.pixels, frame->w, frame->h, frame->pitch);
+ scaleFrame<uint16>((const uint16 *)frame->getPixels(), (uint16 *)scaledFrame.getPixels(), frame->w, frame->h, frame->pitch);
else
- scaleFrame<uint32>((uint32 *)frame->pixels, (uint32 *)scaledFrame.pixels, frame->w, frame->h, frame->pitch);
+ scaleFrame<uint32>((const uint32 *)frame->getPixels(), (uint32 *)scaledFrame.getPixels(), frame->w, frame->h, frame->pitch);
- _system->copyRectToScreen((byte *)scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
+ _system->copyRectToScreen((byte *)scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
_system->updateScreen();
scaledFrame.free();
}
diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp
index 50cc9bc6d8..5fb2551e7a 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())
@@ -333,6 +333,7 @@ void TimeBaseCallBack::releaseCallBack() {
void TimeBaseCallBack::disposeCallBack() {
_timeBase = 0;
+ _trigger = kTriggerNone;
_hasBeenTriggered = false;
}
diff --git a/engines/pegasus/transition.cpp b/engines/pegasus/transition.cpp
index 1ae212df85..b736b115ee 100644
--- a/engines/pegasus/transition.cpp
+++ b/engines/pegasus/transition.cpp
@@ -70,7 +70,7 @@ void ScreenFader::setFaderValue(const int32 value) {
if (value != getFaderValue()) {
Fader::setFaderValue(value);
- if (_screen->pixels) {
+ if (_screen->getPixels()) {
// The original game does a gamma fade here using the Mac API. In order to do
// that, it would require an immense amount of CPU processing. This does a
// linear fade instead, which looks fairly well, IMO.
diff --git a/engines/plugins_table.h b/engines/plugins_table.h
deleted file mode 100644
index c68aa05e58..0000000000
--- a/engines/plugins_table.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// This file is being included by "base/plugins.cpp"
-#if PLUGIN_ENABLED_STATIC(SCUMM)
-LINK_PLUGIN(SCUMM)
-#endif
-#if PLUGIN_ENABLED_STATIC(AGI)
-LINK_PLUGIN(AGI)
-#endif
-#if PLUGIN_ENABLED_STATIC(AGOS)
-LINK_PLUGIN(AGOS)
-#endif
-#if PLUGIN_ENABLED_STATIC(CGE)
-LINK_PLUGIN(CGE)
-#endif
-#if PLUGIN_ENABLED_STATIC(CINE)
-LINK_PLUGIN(CINE)
-#endif
-#if PLUGIN_ENABLED_STATIC(COMPOSER)
-LINK_PLUGIN(COMPOSER)
-#endif
-#if PLUGIN_ENABLED_STATIC(CRUISE)
-LINK_PLUGIN(CRUISE)
-#endif
-#if PLUGIN_ENABLED_STATIC(DRACI)
-LINK_PLUGIN(DRACI)
-#endif
-#if PLUGIN_ENABLED_STATIC(DRASCULA)
-LINK_PLUGIN(DRASCULA)
-#endif
-#if PLUGIN_ENABLED_STATIC(DREAMWEB)
-LINK_PLUGIN(DREAMWEB)
-#endif
-#if PLUGIN_ENABLED_STATIC(GOB)
-LINK_PLUGIN(GOB)
-#endif
-#if PLUGIN_ENABLED_STATIC(GROOVIE)
-LINK_PLUGIN(GROOVIE)
-#endif
-#if PLUGIN_ENABLED_STATIC(HOPKINS)
-LINK_PLUGIN(HOPKINS)
-#endif
-#if PLUGIN_ENABLED_STATIC(HUGO)
-LINK_PLUGIN(HUGO)
-#endif
-#if PLUGIN_ENABLED_STATIC(KYRA)
-LINK_PLUGIN(KYRA)
-#endif
-#if PLUGIN_ENABLED_STATIC(LASTEXPRESS)
-LINK_PLUGIN(LASTEXPRESS)
-#endif
-#if PLUGIN_ENABLED_STATIC(LURE)
-LINK_PLUGIN(LURE)
-#endif
-#if PLUGIN_ENABLED_STATIC(MADE)
-LINK_PLUGIN(MADE)
-#endif
-#if PLUGIN_ENABLED_STATIC(MOHAWK)
-LINK_PLUGIN(MOHAWK)
-#endif
-#if PLUGIN_ENABLED_STATIC(NEVERHOOD)
-LINK_PLUGIN(NEVERHOOD)
-#endif
-#if PLUGIN_ENABLED_STATIC(PARALLACTION)
-LINK_PLUGIN(PARALLACTION)
-#endif
-#if PLUGIN_ENABLED_STATIC(PEGASUS)
-LINK_PLUGIN(PEGASUS)
-#endif
-#if PLUGIN_ENABLED_STATIC(QUEEN)
-LINK_PLUGIN(QUEEN)
-#endif
-#if PLUGIN_ENABLED_STATIC(SAGA)
-LINK_PLUGIN(SAGA)
-#endif
-#if PLUGIN_ENABLED_STATIC(SCI)
-LINK_PLUGIN(SCI)
-#endif
-#if PLUGIN_ENABLED_STATIC(SKY)
-LINK_PLUGIN(SKY)
-#endif
-#if PLUGIN_ENABLED_STATIC(SWORD1)
-LINK_PLUGIN(SWORD1)
-#endif
-#if PLUGIN_ENABLED_STATIC(SWORD2)
-LINK_PLUGIN(SWORD2)
-#endif
-#if PLUGIN_ENABLED_STATIC(SWORD25)
-LINK_PLUGIN(SWORD25)
-#endif
-#if PLUGIN_ENABLED_STATIC(TEENAGENT)
-LINK_PLUGIN(TEENAGENT)
-#endif
-#if PLUGIN_ENABLED_STATIC(TESTBED)
-LINK_PLUGIN(TESTBED)
-#endif
-#if PLUGIN_ENABLED_STATIC(TINSEL)
-LINK_PLUGIN(TINSEL)
-#endif
-#if PLUGIN_ENABLED_STATIC(TOLTECS)
-LINK_PLUGIN(TOLTECS)
-#endif
-#if PLUGIN_ENABLED_STATIC(TONY)
-LINK_PLUGIN(TONY)
-#endif
-#if PLUGIN_ENABLED_STATIC(TOON)
-LINK_PLUGIN(TOON)
-#endif
-#if PLUGIN_ENABLED_STATIC(TSAGE)
-LINK_PLUGIN(TSAGE)
-#endif
-#if PLUGIN_ENABLED_STATIC(TOUCHE)
-LINK_PLUGIN(TOUCHE)
-#endif
-#if PLUGIN_ENABLED_STATIC(TUCKER)
-LINK_PLUGIN(TUCKER)
-#endif
-#if PLUGIN_ENABLED_STATIC(VOYEUR)
-LINK_PLUGIN(VOYEUR)
-#endif
-#if PLUGIN_ENABLED_STATIC(WINTERMUTE)
-LINK_PLUGIN(WINTERMUTE)
-#endif
diff --git a/engines/queen/POTFILES b/engines/queen/POTFILES
new file mode 100644
index 0000000000..1baf9c24de
--- /dev/null
+++ b/engines/queen/POTFILES
@@ -0,0 +1 @@
+engines/queen/queen.cpp
diff --git a/engines/queen/configure.engine b/engines/queen/configure.engine
new file mode 100644
index 0000000000..c8766743f9
--- /dev/null
+++ b/engines/queen/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine queen "Flight of the Amazon Queen" yes
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index fd602ff4fb..df8283b4c2 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);
}
@@ -501,7 +501,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
}
anim = getAnimation(animId);
- displayBuffer = (byte *)_vm->_render->getBackGroundSurface()->pixels;
+ displayBuffer = (byte *)_vm->_render->getBackGroundSurface()->getPixels();
if (playing) {
anim->state = ANIM_PLAYING;
diff --git a/engines/saga/configure.engine b/engines/saga/configure.engine
new file mode 100644
index 0000000000..99e2ab367b
--- /dev/null
+++ b/engines/saga/configure.engine
@@ -0,0 +1,5 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine saga "SAGA" yes "ihnm saga2" "ITE"
+add_engine ihnm "IHNM" yes
+add_engine saga2 "SAGA 2 games" no
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index d98cef0740..c5842f4998 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -533,6 +533,7 @@ int Events::handleOneShot(Event *event) {
default:
break;
}
+ break;
#ifdef ENABLE_IHNM
case kCutawayEvent:
switch (event->op) {
@@ -545,6 +546,7 @@ int Events::handleOneShot(Event *event) {
default:
break;
}
+ break;
#endif
case kActorEvent:
switch (event->op) {
@@ -554,6 +556,7 @@ int Events::handleOneShot(Event *event) {
default:
break;
}
+ break;
default:
break;
}
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index c677b76324..c68160e907 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -201,7 +201,7 @@ public:
// Whenever it gets called, the corresponding caller must take care
// to add the corresponding dirty rectangle itself
byte *getBackBufferPixels() {
- return (byte *)_backBuffer.pixels;
+ return (byte *)_backBuffer.getPixels();
}
uint16 getBackBufferWidth() {
diff --git a/engines/saga/introproc_ihnm.cpp b/engines/saga/introproc_ihnm.cpp
index 6015e6757a..7922d56425 100644
--- a/engines/saga/introproc_ihnm.cpp
+++ b/engines/saga/introproc_ihnm.cpp
@@ -212,7 +212,7 @@ bool Scene::playTitle(int title, int time, int mode) {
break;
case 2: // display background
- _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0,
backBufferSurface->w, backBufferSurface->h);
phase++;
startTime = curTime;
@@ -247,7 +247,7 @@ bool Scene::playTitle(int title, int time, int mode) {
frameTime = curTime;
- _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0,
backBufferSurface->w, backBufferSurface->h);
}
@@ -273,8 +273,8 @@ bool Scene::playTitle(int title, int time, int mode) {
_vm->_anim->endVideo();
- memset((byte *)backBufferSurface->pixels, 0, backBufferSurface->w * backBufferSurface->h);
- _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ memset((byte *)backBufferSurface->getPixels(), 0, backBufferSurface->w * backBufferSurface->h);
+ _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0,
backBufferSurface->w, backBufferSurface->h);
return interrupted;
diff --git a/engines/saga/introproc_ite.cpp b/engines/saga/introproc_ite.cpp
index 484ebe1779..ed53e078a0 100644
--- a/engines/saga/introproc_ite.cpp
+++ b/engines/saga/introproc_ite.cpp
@@ -993,7 +993,7 @@ int Scene::ITEIntroTreeHouseProc(int param) {
}
// Queue game credits list
- eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
+ ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2);
// End scene after credit display
@@ -1073,7 +1073,7 @@ int Scene::ITEIntroFairePathProc(int param) {
_vm->_events->chain(eventColumns, event);
// Queue game credits list
- eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
+ ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2);
// End scene after credit display
diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp
index 260eca98e6..e61dfbf161 100644
--- a/engines/saga/introproc_saga2.cpp
+++ b/engines/saga/introproc_saga2.cpp
@@ -108,7 +108,7 @@ void Scene::playMovie(const char *filename) {
if (smkDecoder->needsUpdate()) {
const Graphics::Surface *frame = smkDecoder->decodeNextFrame();
if (frame) {
- _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
if (smkDecoder->hasDirtyPalette())
_vm->_system->getPaletteManager()->setPalette(smkDecoder->getPalette(), 0, 256);
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/saga.h b/engines/saga/saga.h
index 01cab21f5d..645e1c30d0 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -138,7 +138,7 @@ enum GameFileTypes {
enum GameFeatures {
GF_ITE_FLOPPY = 1 << 0,
#if 0
- GF_OLD_ITE_DOS = 1 << 1, // Currently unused
+ GF_OLD_ITE_DOS = 1 << 1, // Currently unused
#endif
GF_EXTRA_ITE_CREDITS = 1 << 2,
GF_8BIT_UNSIGNED_PCM = 1 << 3
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 75876b1c90..eff31cf98b 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -468,7 +468,7 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy
pal = decoder.getPalette();
rect.setWidth(decoder.getSurface()->w);
rect.setHeight(decoder.getSurface()->h);
- _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->pixels);
+ _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->getPixels());
for (int j = 0; j < PAL_ENTRIES; j++) {
cPal[j].red = *pal++;
cPal[j].green = *pal++;
@@ -1120,9 +1120,9 @@ void Scene::draw() {
_vm->_render->getBackGroundSurface()->getRect(rect);
rect.bottom = (_sceneClip.bottom < rect.bottom) ? getHeight() : rect.bottom;
if (_vm->_render->isFullRefresh())
- _vm->_gfx->drawRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->pixels);
+ _vm->_gfx->drawRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->getPixels());
else
- _vm->_gfx->drawBgRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->pixels);
+ _vm->_gfx->drawBgRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->getPixels());
}
}
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 69c27b6a6b..619ffc243e 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -196,11 +196,13 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
break;
case kTypeS16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
+ // fallthrough
case kTypeS16HL:
flags |= Audio::FLAG_16BITS;
break;
case kTypeU16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
+ // fallthrough
case kTypeU16HL:
flags |= Audio::FLAG_16BITS;
flags |= Audio::FLAG_UNSIGNED;
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/saga/sprite.cpp b/engines/saga/sprite.cpp
index 2895c6800c..bf550659e9 100644
--- a/engines/saga/sprite.cpp
+++ b/engines/saga/sprite.cpp
@@ -71,17 +71,7 @@ Sprite::~Sprite() {
}
void Sprite::loadList(int resourceId, SpriteList &spriteList) {
- SpriteInfo *spriteInfo;
ByteArray spriteListData;
- uint16 oldSpriteCount;
- uint16 newSpriteCount;
- uint16 spriteCount;
- uint i;
- int outputLength, inputLength;
- uint32 offset;
- const byte *spritePointer;
- const byte *spriteDataPointer;
-
_vm->_resource->loadResource(_spriteContext, resourceId, spriteListData);
if (spriteListData.empty()) {
@@ -90,19 +80,19 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
ByteArrayReadStreamEndian readS(spriteListData, _spriteContext->isBigEndian());
- spriteCount = readS.readUint16();
+ uint16 spriteCount = readS.readUint16();
debug(9, "Sprites: %d", spriteCount);
- oldSpriteCount = spriteList.size();
- newSpriteCount = oldSpriteCount + spriteCount;
+ uint16 oldSpriteCount = spriteList.size();
+ uint16 newSpriteCount = oldSpriteCount + spriteCount;
spriteList.resize(newSpriteCount);
bool bigHeader = _vm->getGameId() == GID_IHNM || _vm->isMacResources();
- for (i = oldSpriteCount; i < spriteList.size(); i++) {
- spriteInfo = &spriteList[i];
+ for (uint i = oldSpriteCount; i < spriteList.size(); i++) {
+ uint32 offset;
if (bigHeader)
offset = readS.readUint32();
else
@@ -115,9 +105,11 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
return;
}
- spritePointer = spriteListData.getBuffer();
+ const byte *spritePointer = spriteListData.getBuffer();
spritePointer += offset;
+ const byte *spriteDataPointer;
+ SpriteInfo *spriteInfo = &spriteList[i];
if (bigHeader) {
Common::MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian());
@@ -139,8 +131,8 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
spriteDataPointer = spritePointer + readS2.pos();
}
- outputLength = spriteInfo->width * spriteInfo->height;
- inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer());
+ int outputLength = spriteInfo->width * spriteInfo->height;
+ int inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer());
spriteInfo->decodedBuffer.resize(outputLength);
if (outputLength > 0) {
decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
diff --git a/engines/sci/POTFILES b/engines/sci/POTFILES
new file mode 100644
index 0000000000..f076c292d9
--- /dev/null
+++ b/engines/sci/POTFILES
@@ -0,0 +1,2 @@
+engines/sci/detection.cpp
+engines/sci/engine/kfile.cpp
diff --git a/engines/sci/configure.engine b/engines/sci/configure.engine
new file mode 100644
index 0000000000..d1c45a4654
--- /dev/null
+++ b/engines/sci/configure.engine
@@ -0,0 +1,4 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine sci "SCI" yes "sci32" "SCI 0-1.1 games"
+add_engine sci32 "SCI32 games" no
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 50fae61de0..80d8ab8257 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -3840,10 +3840,15 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV
const char *tmp = Common::find(str_objname.begin(), str_objname.end(), '.');
if (tmp != str_objname.end()) {
index = strtol(tmp + 1, &endptr, 16);
- if (*endptr)
- return -1;
- // Chop off the index
- str_objname = Common::String(str_objname.c_str(), tmp);
+ if (*endptr) {
+ // The characters after the dot do not represent an index.
+ // This can happen if an object contains a dot in its name,
+ // like 'dominoes.opt' in Hoyle 3.
+ index = -1;
+ } else {
+ // Valid index found, chop it off
+ str_objname = Common::String(str_objname.c_str(), tmp);
+ }
}
// Replace all underscores in the name with spaces
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 09c348f273..883a4d965b 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -105,9 +105,8 @@ static const PlainGameDescriptor s_sciGameTitles[] = {
// === SCI2.1 games ========================================================
{"chest", "Inside the Chest"}, // aka Behind the Developer's Shield
{"gk2", "The Beast Within: A Gabriel Knight Mystery"},
- // TODO: Inside The Chest/Behind the Developer's Shield
{"kq7", "King's Quest VII: The Princeless Bride"},
- // TODO: King's Questions
+ {"kquestions", "King's Questions"},
{"lsl6hires", "Leisure Suit Larry 6: Shape Up or Slip Out!"},
{"mothergoosehires","Mixed-Up Mother Goose Deluxe"},
{"phantasmagoria", "Phantasmagoria"},
@@ -161,6 +160,7 @@ static const GameIdStrToEnum s_gameIdStrToEnum[] = {
{ "kq5", GID_KQ5 },
{ "kq6", GID_KQ6 },
{ "kq7", GID_KQ7 },
+ { "kquestions", GID_KQUESTIONS },
{ "laurabow", GID_LAURABOW },
{ "laurabow2", GID_LAURABOW2 },
{ "lighthouse", GID_LIGHTHOUSE },
@@ -242,6 +242,7 @@ static const OldNewIdTableEntry s_oldNewTable[] = {
// kq5 is the same
// kq6 is the same
{ "kq7cd", "kq7", SCI_VERSION_NONE },
+ { "quizgame-demo", "kquestions", SCI_VERSION_NONE },
{ "mm1", "laurabow", SCI_VERSION_NONE },
{ "cb1", "laurabow", SCI_VERSION_NONE },
{ "lb2", "laurabow2", SCI_VERSION_NONE },
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index fa7acaf4b8..05af2ff78c 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -50,7 +50,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474},
{"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.005.000"
@@ -62,7 +62,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380},
{"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - German Amiga (from www.back2roots.org, also includes English language)
// Executable scanning reports "1.005.001"
@@ -74,7 +74,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309},
{"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain Macintosh (from omer_mor, bug report #3328251)
{"castlebrain", "", {
@@ -84,7 +84,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e1a6b6f1060f60be9dcb6d28ad7a2a20", 1168310},
{"resource.003", 0, "6c3d1bb26ad532c94046bc9ac49b5ff4", 891295},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.005
@@ -93,7 +93,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "9780f040d58182994e22d2e34fab85b0", 67367},
{"resource.001", 0, "2af49dbd8f2e1db4ab09f9310dc91259", 570553},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS 5.25" Floppy EGA (from omer_mor, bug report #3035349)
{"castlebrain", "EGA", {
@@ -106,7 +106,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "8a5ed3ba96e2eaf18e36fedfaab89419", 297838},
{"resource.006", 0, "dceed92e709cad1bd9582809a235b0a0", 266682},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS 3.5" Floppy EGA (from nozomi77, bug report #3405307)
{"castlebrain", "EGA", {
@@ -116,7 +116,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "de2f182529efaad2c4b510b452ab77ac", 633662},
{"resource.003", 0, "38b4b37febc6b4f5061c461a283df148", 430388},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS Floppy (from jvprat)
// Executable scanning reports "1.000.044", Floppy label reports "1.0, 10.30.91", VERSION file reports "1.000"
@@ -127,7 +127,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832},
{"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS 5.25" Floppy VGA 1.1 (from rnjacobs, bug report #3578286)
{"castlebrain", "", {
@@ -137,7 +137,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "583d348c908f89f94f8551d7fe0a2eca", 991752},
{"resource.003", 0, "6c3d1bb26ad532c94046bc9ac49b5ff4", 728315},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS Floppy 1.1
{"castlebrain", "", {
@@ -146,7 +146,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776},
{"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - English DOS Floppy 1.000
// Reported by graxer in bug report #3037942
@@ -161,7 +161,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "1d778a0c65cac9ddbab65495e50a94ee", 335281},
{"resource.007", 0, "063bb8ce4157c778cf30d1c912c006f1", 335631},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Castle of Dr. Brain - Spanish DOS (also includes english language)
// SCI interpreter version 1.000.510
@@ -170,7 +170,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694},
{"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Inside the Chest / Behind the Developer's Shield
@@ -179,7 +179,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "9dd015e79cac4f91e7de805448f39775", 1912},
{"resource.000", 0, "e4efcd042f86679dd4e1834bb3a38edb", 3770943},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO3(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO3(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI) },
#endif
// Christmas Card 1988 - English DOS
@@ -188,7 +188,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426},
{"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Christmas Card 1990: The Seasoned Professional - English DOS (16 Colors)
// SCI interpreter version 1.000.172
@@ -196,7 +196,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8f656714a05b94423ac6eb10ee8797d0", 600},
{"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 272629},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Christmas Card 1990: The Seasoned Professional - English DOS (256 Colors)
// SCI interpreter version 1.000.174
@@ -204,7 +204,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "44b8f45b841b9b5e17e939a35e443988", 600},
{"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 335362},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Christmas Card 1992 - English DOS
// SCI interpreter version 1.001.055
@@ -212,7 +212,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f1f8c8a8443f523422af70b4ec85b71c", 318},
{"resource.000", 0, "62fb9256f8e7e6e65a6875efdb7939ac", 203396},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.031"
@@ -226,7 +226,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 713382},
{"resource.005", 0, "605b67a9ef199a9bb015745e7c004cf4", 478384},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English DOS Non-Interactive Demo
// Executable scanning reports "0.000.685"
@@ -234,7 +234,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "782974f29d8a824782d2d4aea39964e3", 1056},
{"resource.001", 0, "d4b75e280d1c3a97cfef1b0bebff387c", 573647},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English DOS (from jvprat)
// Executable scanning reports "0.000.685", Floppy label reports "1.033, 6.8.90", VERSION file reports "1.033"
@@ -247,7 +247,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 624303},
{"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 670883},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English DOS (from FRG)
// SCI interpreter version 0.000.668
@@ -259,7 +259,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 622118},
{"resource.004", 0, "64f342463f6f35ba71b3509ef696ae3f", 669188},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English DOS (supplied by ssburnout in bug report #3049193)
// 1.022 9x5.25" (label: Int#0.000.668)
@@ -274,7 +274,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942},
{"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267811},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Codename: Iceman - English DOS 1.023 (from abevi, bug report #2612718)
{"iceman", "", {
@@ -288,7 +288,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942},
{"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267702},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of Camelot - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.030"
@@ -303,7 +303,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "c6e551bdc24f0acc193159038d4ca767", 605882},
{"resource.006", 0, "8f880a536908ab496bbc552f7f5c3738", 585255},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of Camelot - English DOS Non-Interactive Demo
// SCI interpreter version 0.000.668
@@ -311,7 +311,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f4cd75c15be75e04cdca3acda2c0b0ea", 468},
{"resource.001", 0, "4930708722f34bfbaa4945fb08f55f61", 232523},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of Camelot - English DOS (from jvprat)
// Executable scanning reports "0.000.685", Floppy label reports "1.001, 0.000.685", VERSION file reports "1.001.000"
@@ -323,7 +323,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "8e1a3a8c588007404b532b8dfacc1460", 723712},
{"resource.004", 0, "8e1a3a8c588007404b532b8dfacc1460", 729143},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of Camelot - English DOS
// SCI interpreter version 0.000.685
@@ -337,7 +337,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "8e1a3a8c588007404b532b8dfacc1460", 332446},
{"resource.007", 0, "8e1a3a8c588007404b532b8dfacc1460", 358182},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.005.001"
@@ -352,7 +352,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002},
{"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - English DOS
// SCI interpreter version 1.000.510
@@ -366,7 +366,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950},
{"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - English DOS Floppy (from jvprat)
// Executable scanning reports "1.000.168", Floppy label reports "1.1, 1.13.92", VERSION file reports "1.1"
@@ -380,7 +380,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462},
{"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - English DOS
// SCI interpreter version 1.000.510
@@ -393,30 +393,32 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237},
{"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow EGA - English DOS
// SCI interpreter version 1.000.510
{"longbow", "EGA", {
- {"resource.map", 0, "7676ec9f08967d7a9a7724f5170456e0", 6261},
- {"resource.000", 0, "36e8fda5d0b8c49e587c8a9617959f72", 718161},
- {"resource.001", 0, "3c3735caa34fa3f261a9552831bb43ed", 705680},
- {"resource.002", 0, "7025b87e735b1df3f0e9488a621f4333", 700633},
- {"resource.003", 0, "eaca7933e8e56bea22b42f7fd5d7a8a7", 686510},
- {"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631},
- {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243},
- {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158},
- AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ {"resource.map", 0, "7676ec9f08967d7a9a7724f5170456e0", 6261},
+ {"resource.000", 0, "36e8fda5d0b8c49e587c8a9617959f72", 718161},
+ {"resource.001", 0, "3c3735caa34fa3f261a9552831bb43ed", 705680},
+ {"resource.002", 0, "7025b87e735b1df3f0e9488a621f4333", 700633},
+ {"resource.003", 0, "eaca7933e8e56bea22b42f7fd5d7a8a7", 686510},
+ {"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631},
+ {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243},
+ {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow DOS 1.0 EGA (4 x 5.25" disks)
// Provided by ssburnout in bug report #3046802
{"longbow", "EGA", {
- {"resource.map", 0, "0517ca368ec844df0cb21a05020fae01", 6021},
- {"resource.000", 0, "36e8fda5d0b8c49e587c8a9617959f72", 934643},
- {"resource.001", 0, "76c729e563809170e6cc8b2f3f6cf0a4", 1196133},
- {"resource.002", 0, "8c767b3939add63d11274065e46aad04", 1152478},
- {"resource.003", 0, "7025b87e735b1df3f0e9488a621f4333", 1171439},
- AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ {"resource.map", 0, "0517ca368ec844df0cb21a05020fae01", 6021},
+ {"resource.000", 0, "36e8fda5d0b8c49e587c8a9617959f72", 934643},
+ {"resource.001", 0, "76c729e563809170e6cc8b2f3f6cf0a4", 1196133},
+ {"resource.002", 0, "8c767b3939add63d11274065e46aad04", 1152478},
+ {"resource.003", 0, "7025b87e735b1df3f0e9488a621f4333", 1171439},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.510
@@ -424,7 +426,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "cbc5cb73341de1bff1b1e20a640af220", 588},
{"resource.001", 0, "f05a20cc07eee85da8e999d0ac0f596b", 869916},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Conquests of the Longbow - German DOS (suplied by markcoolio in bug report #2727681, also includes english language)
// SCI interpreter version 1.000.510
@@ -438,7 +440,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914},
{"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "x.yyy.zzz"
@@ -447,7 +449,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "c819e171359b7c95f4c13b846d5c034e", 873},
{"resource.001", 0, "baf9393a9bfa73098adb501e5bc5487b", 657518},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - English DOS CD 1.1
// SCI interpreter version 1.001.064
@@ -455,7 +457,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804},
{"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - English DOS CD 1.1
// SCI interpreter version 1.001.064
@@ -465,7 +467,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804},
{"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - English DOS Floppy
// SCI interpreter version 1.000.510
@@ -476,7 +478,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816},
{"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - English DOS Floppy
// SCI interpreter version 1.000.510
@@ -487,7 +489,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316},
{"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - German DOS Floppy (supplied by markcoolio in bug report #2723744, also includes english language)
// SCI interpreter version 1.000.510
@@ -498,7 +500,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581},
{"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - Spanish DOS Floppy (from jvprat, also includes english language)
// Executable scanning reports "1.ECO.013", VERSION file reports "1.000, 11.12.92"
@@ -510,7 +512,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033},
{"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest - French DOS Floppy (from Strangerke, also includes english language)
// SCI interpreter version 1.ECO.013
@@ -521,7 +523,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "b836c6ee9de67d814ac5d1b05f5b9858", 1173872},
{"resource.003", 0, "f8f767f9d6351432621c6e54c1b2ba8c", 1141520},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest 2 - English DOS Non-Interactive Demo
// SCI interpreter version 1.001.055
@@ -529,7 +531,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "607cfa0d8a03b7d348c06ee727e3d939", 1321},
{"resource.000", 0, "dd6f614c43c029f063e93cd243af90a4", 525992},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest 2 - English DOS Floppy (supplied by markcoolio in bug report #2723761)
// SCI interpreter version 1.001.065
@@ -537,7 +539,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "28fb7b6abb9fc1cb8882d7c2e701b63f", 5658},
{"resource.000", 0, "cc1d17e5637528dbe4a812699e1cbfc6", 4208192},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest 2 - French DOS Floppy (from Strangerke)
// SCI interpreter version 1.001.081
@@ -545,7 +547,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "c22ab8b33c339c138b6b1697b77b9e79", 5588},
{"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4231946},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Eco Quest 2 - Spanish DOS Floppy (supplied by umbrio in bug report #3313962)
{"ecoquest2", "Floppy", {
@@ -553,7 +555,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4209150},
{"resource.msg", 0, "eff8be1925d42288de55e405983e9314", 117810},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // Eco Quest 2 - German DOS Floppy (supplied by frankenbuam in bug report #3615072)
+ {"ecoquest2", "Floppy", {
+ {"resource.map", 0, "d8b20073e64f41f6437f73143a186753", 5643},
+ {"resource.000", 0, "cc1d17e5637528dbe4a812699e1cbfc6", 4210876},
+ {"resource.msg", 0, "2f231d31af172ea72ed533fd112f971b", 133458},
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - English DOS demo (from FRG)
// SCI interpreter version 1.001.069
@@ -561,7 +571,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "97aa9fcfe84c9993a64debd28c32393a", 1909},
{"resource.000", 0, "5ea8e7a3ea10cce6efd5c106dc62fd8c", 867724},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - English CD DOS (from FRG)
// SCI interpreter version 1.001.132
@@ -569,7 +579,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "d46b282f228a67ba13bd4b4009e95f8f", 6058},
{"resource.000", 0, "ee3c64ffff0ba9fb08bea2624631c598", 5490246},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - English DOS Floppy (updated information from markcoolio in bug reports #2723773 and #2724720)
// Executable scanning reports "1.cfs.081"
@@ -579,7 +589,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "554f65315d851184f6e38211489fdd8f", -1},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - French DOS Floppy (supplied by misterhands in bug report #3589449)
// Executable scanning reports "1.cfs.081"
@@ -588,7 +598,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "fed4808fdb72486908ac7ad0044b14d8", 5233230},
{"resource.msg", 0, "4dc478f5c73b57e5d690bdfffdcf1c44", 816518},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - Windows (supplied by abevi in bug report #2612718)
// Executable scanning reports "1.cfs.081"
@@ -597,7 +607,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816},
{"resource.000", 0, "fed4808fdb72486908ac7ad0044b14d8", 5233230},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - German DOS Floppy (from Tobis87, updated information from markcoolio in bug reports #2723772 and #2724720)
// Executable scanning reports "1.cfs.081"
@@ -607,7 +617,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "304b5a5781800affd2235152a5794fa8", -1},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - Spanish DOS (from jvprat)
// Executable scanning reports "1.cfs.081", VERSION file reports "1.000, March 30, 1995"
@@ -620,7 +630,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "05acdc256c742e79c50b9fe7ec2cc898", 863310},
{"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - Spanish DOS (from jvprat)
// Executable scanning reports "1.cfs.081", VERSION file reports "1.000, March 30, 1995"
@@ -630,7 +640,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - English DOS CD Demo
// SCI interpreter version 1.001.095
@@ -638,14 +648,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a62a7eae85dd1e6b07f39662b278437e", 1918},
{"resource.000", 0, "4962a3c4dd44e36e78ea4a7a374c2220", 957382},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Freddy Pharkas - English Macintosh
{"freddypharkas", "", {
{"Data1", 0, "ef7cbd62727989818f1cfae69c9fd61d", 3038492},
{"Data2", 0, "2424b418f7d52c385cea4701f529c69a", 4721732},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Fun Seeker's Guide - English DOS
// SCI interpreter version 0.000.506
@@ -653,7 +663,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7ee6859ef74314f6d91938c3595348a9", 282},
{"resource.001", 0, "f1e680095424e31f7fae1255d36bacba", 40692},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English DOS CD Demo
// SCI interpreter version 1.001.092
@@ -661,7 +671,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "39645952ae0ed8072c7e838f31b75464", 2490},
{"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // Gabriel Knight - English DOS CD Demo (from DrMcCoy)
+ // SCI interpreter version 1.001.092
+ {"gk1", "CD Demo", {
+ {"resource.map", 0, "8cad2a256f41463030cbb7ea1bfb2857", 2490},
+ {"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Gabriel Knight - English DOS Floppy
@@ -670,7 +688,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10783},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English DOS Floppy (supplied my markcoolio in bug report #2723777)
// SCI interpreter version 2.000.000
@@ -678,7 +696,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "65e8c14092e4c9b3b3538b7602c8c5ec", 10783},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English DOS Floppy
// SCI interpreter version 2.000.000, VERSION file reports "1.0\nGabriel Knight\n11/22/10:33 pm\n\x1A"
@@ -686,7 +704,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ef41df08cf2c1f680216cdbeed0f8311", 10783},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - German DOS Floppy (supplied my markcoolio in bug report #2723775)
// SCI interpreter version 2.000.000
@@ -694,7 +712,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ad6508b0296b25c07b1f58828dc33696", 10789},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13077029},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - French DOS Floppy (supplied my kervala in bug report #3611487)
// SCI interpreter version 2.000.000
@@ -702,7 +720,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "236e36cc847cdeafdd5e5fa8cba916ed", 10801},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13033072},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English DOS CD (from jvprat)
// Executable scanning reports "2.000.000", VERSION file reports "01.100.000"
@@ -710,7 +728,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English Windows CD (from jvprat)
// Executable scanning reports "2.000.000", VERSION file reports "01.100.000"
@@ -718,7 +736,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - German DOS CD (from Tobis87)
// SCI interpreter version 2.000.000
@@ -726,7 +744,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - Spanish DOS CD (from jvprat)
// Executable scanning reports "2.000.000", VERSION file reports "1.000.000, April 13, 1995"
@@ -734,7 +752,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - French DOS CD (from Hkz)
// VERSION file reports "1.000.000, May 3, 1994"
@@ -742,7 +760,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "55f909ba93a2515042a08d8a2da8414e", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13325145},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - German Windows CD (from Tobis87)
// SCI interpreter version 2.000.000
@@ -750,7 +768,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - Spanish Windows CD (from jvprat)
// Executable scanning reports "2.000.000", VERSION file reports "1.000.000, April 13, 1995"
@@ -758,7 +776,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight - English Macintosh
{"gk1", "", {
@@ -767,7 +785,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data3", 0, "f25068b408b09275d8b698866462f578", 3677599},
{"Data4", 0, "1cceebbe411b26c860a74f91c337fdf3", 3230086},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight 2 - English Windows Non-Interactive Demo
// Executable scanning reports "2.100.002"
@@ -775,7 +793,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "e0effce11c4908f4b91838741716c83d", 1351},
{"resource.000", 0, "d04cfc7f04b6f74d13025378be49ec2b", 4640330},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight 2 - English DOS (GOG version) - ressci.* merged in ressci.000
// using Enrico Rolfi's HD/DVD installer: http://gkpatches.vogons.zetafleet.com/
@@ -783,7 +801,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "b996fa1e57389a1e179a00a0049de1f4", 8110},
{"ressci.000", 0, "a19fc3604c6e5407abcf03d59ee87217", 168522221},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight 2 - English DOS (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.1"
@@ -801,7 +819,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.006", 0, "ce9359037277b7d7976da185c2fa0aad", 2977},
{"ressci.006", 0, "8e44e03890205a7be12f45aaba9644b4", 60659424},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight 2 - French DOS (6-CDs Sierra Originals reedition)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -819,7 +837,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.006", 0, "11b2e722170b8c93fdaa5428e2c7676f", 3001},
{"ressci.006", 0, "4037d941aec39d2e654e20960429aefc", 60568486},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Gabriel Knight 2 - English Macintosh
// NOTE: This only contains disc 1 files (as well as the persistent file:
@@ -831,7 +849,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data4", 0, "8b843c62eb53136a855d6e0087e3cb0d", 5889553},
{"Data5", 0, "f9fcf9ab2eb13b2125c33a1cda03a093", 14349984},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
@@ -843,7 +861,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342149},
{"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328925},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 1 - English DOS (supplied by wibble92 in bug report #2644547)
// SCI interpreter version 0.000.530
@@ -853,7 +871,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342309},
{"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328912},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 1 - English DOS (supplied by merkur in bug report #2719227)
// SCI interpreter version 0.000.530
@@ -861,14 +879,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "1034a218943d12f1f36e753fa10c95b8", 4386},
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518308},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 1 3.5' - English DOS (supplied by eddydrama in bug report #3052366 and dinnerx in bug report #3090841)
{"hoyle1", "", {
{"resource.map", 0, "0af9a3dcd72a091960de070432e1f524", 4386},
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518127},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#if 0 // TODO: unknown if these files are corrupt
// Hoyle 1 - English Amiga (from www.back2roots.org)
@@ -878,7 +896,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 218755},
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 439502},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif
// Hoyle 2 - English DOS
@@ -888,7 +906,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98138},
{"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 196631},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 2 - English DOS (supplied by ssburnout in bug report #3049193)
// 1.000.011 1x3.5" (label:Int#6.21.90)
@@ -896,7 +914,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "db0ba08b953e9904a4960ad99cd29c20", 1356},
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 216315},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 2 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.032"
@@ -905,7 +923,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "62ed48d20c580e5a98f102f7cd93706a", 1356},
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 222704},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 2 - English Macintosh
// Executable scanning reports "x.yyy.zzz"
@@ -913,7 +931,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "1af1d3aa3cf564f93477c9f87e53f495", 1728},
{"resource.001", 0, "b73b8131669d69d41a326415e4519138", 482882},
{NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#if 0 // TODO: unknown if these files are corrupt
// Hoyle 3 - English Amiga (from www.back2roots.org)
@@ -924,7 +942,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791},
{"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif
// Hoyle 3 - English DOS Non-Interactive Demo
@@ -934,7 +952,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735},
{"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 3 - English DOS Floppy (from jvprat)
// Executable scanning reports "x.yyy.zzz", Floppy label reports "1.0, 11.2.91", VERSION file reports "1.000"
@@ -944,7 +962,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845},
{"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 3 - English DOS Floppy (supplied by eddydrama in bug report #3038837)
{"hoyle3", "", {
@@ -955,7 +973,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "97cfd72633f8f9b2a0b1d4116cf3ee81", 346116},
{"resource.004", 0, "2884fb91b225fabd9ca87ea231293b48", 351218},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 3 EGA - English DOS Floppy 1.0 (supplied by abevi in bug report #2612718)
{"hoyle3", "EGA", {
@@ -963,14 +981,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 319905},
{"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 526438},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 4 (Hoyle Classic Card Games) - English DOS Demo
{"hoyle4", "Demo", {
{"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931},
{"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 4 (Hoyle Classic Card Games) - English DOS Demo
// SCI interpreter version 1.001.200 (just a guess)
@@ -979,7 +997,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938},
{"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 4 (Hoyle Classic Card Games) - English DOS/Win
// Supplied by abevi in bug report #3039291
@@ -987,7 +1005,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2b577c975cc8d8d43f61b6a756129fe3", 4352},
{"resource.000", 0, "43e2c15ce436aab611a462ad0603e12d", 2000132},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 4 (Hoyle Classic Card Games) - English Macintosh Floppy
// VERSION file reports "2.0"
@@ -995,7 +1013,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "99575fae4579540a314bbedd72d51e8c", 7682887},
{"Data2", 0, "7d4bf5bdf3c02edbf35cb8471c84ec13", 1539134},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Jones in the Fast Lane EGA - English DOS
// SCI interpreter version 1.000.172 (not 100% sure FIXME)
@@ -1004,14 +1022,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105},
{"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Jones in the Fast Lane EGA - English DOS (supplied by EddyDrama in bug report #3038761)
{"jones", "EGA", {
{"resource.map", 0, "8e92cf319180cc8b5b87b2ce93a4fe22", 1602},
{"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 511528},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Jones in the Fast Lane VGA - English DOS
// SCI interpreter version 1.000.172
@@ -1020,7 +1038,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 313476},
{"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 719747},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Jones in the Fast Lane VGA - English DOS (supplied by omer_mor in bug report #3037054)
// VERSION file reports "1.000.060"
@@ -1028,14 +1046,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "db175ab494ab0666f19ab8f2597a8e49", 1602},
{"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 994487},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Jones in the Fast Lane - English DOS CD
{"jones", "CD", {
{"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878},
{"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO1(GAMEOPTION_JONES_CDAUDIO) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO1(GAMEOPTION_JONES_CDAUDIO) },
// Jones in the Fast Lane - English DOS CD
// Same entry as the DOS version above. This one is used for the alternate
@@ -1044,7 +1062,24 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878},
{"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) },
+
+ // Jones in the Fast Lane - English DOS US CD (alternate version)
+ // Supplied by collector9 in bug #3614668
+ {"jones", "CD", {
+ {"resource.map", 0, "4344ff3f796707843b992adec2c87663", 4878},
+ {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652062},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO1(GAMEOPTION_JONES_CDAUDIO) },
+
+ // Jones in the Fast Lane - English DOS US CD (alternate version)
+ // Same entry as the DOS version above. This one is used for the alternate
+ // General MIDI music tracks in the Windows version
+ {"jones", "CD", {
+ {"resource.map", 0, "4344ff3f796707843b992adec2c87663", 4878},
+ {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652062},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) },
// King's Quest 1 SCI Remake - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.003.007"
@@ -1056,7 +1091,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "9ae2a13708d691cd42f9129173c4b39d", 763224},
{"resource.004", 0, "9ae2a13708d691cd42f9129173c4b39d", 820443},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 1 SCI Remake - English DOS Non-Interactive Demo
// Executable scanning reports "S.old.010"
@@ -1064,7 +1099,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954},
{"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection)
// Executable scanning reports "S.old.010", VERSION file reports "1.000.051"
@@ -1075,7 +1110,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "fed9e0072ffd511d248674e60dee2099", 714062},
{"resource.003", 0, "fed9e0072ffd511d248674e60dee2099", 717478},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 1 SCI Remake - English DOS (supplied by ssburnout in bug report #3049193)
// 1.000.051 9x5.25" (label: INT#9.19.90)
@@ -1089,7 +1124,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "fed9e0072ffd511d248674e60dee2099", 351062},
{"resource.007", 0, "fed9e0072ffd511d248674e60dee2099", 330472},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.032"
@@ -1102,7 +1137,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "fd16c9c223f7dc5b65f06447615224ff", 683016},
{"resource.004", 0, "3fac034c7d130e055d05bc43a1f8d5f8", 549993},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS Non-Interactive Demo
// Executable scanning reports "0.000.494"
@@ -1110,7 +1145,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "992ac7cc31d3717fe53818a9bb6d1dae", 594},
{"resource.001", 0, "143e1c14f15ad0fbfc714f648a65f661", 205330},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS (original boxed release, 3 1/2" disks)
// SCI interpreter version 0.000.247
@@ -1121,7 +1156,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "851a62d00972dc4002f472cc0d84e71d", 683145},
{"resource.004", 0, "851a62d00972dc4002f472cc0d84e71d", 649441},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS (from the King's Quest Collection)
// Executable scanning reports "0.000.502"
@@ -1133,7 +1168,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "77615c595388acf3d1df8e107bfb6b52", 707591},
{"resource.004", 0, "77615c595388acf3d1df8e107bfb6b52", 479562},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS (supplied by ssburnout in bug report #3049193)
// 1.006.003 8x5.25" (label: Int.#0.000.502)
@@ -1147,7 +1182,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "6db7de6f93c6ea62dca78abee677f8c0", 324789},
{"resource.007", 0, "6db7de6f93c6ea62dca78abee677f8c0", 334441},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS
// SCI interpreter version 0.000.274
@@ -1161,7 +1196,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777},
{"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English DOS
// SCI interpreter version 0.000.253
@@ -1175,7 +1210,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288},
{"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 4 - English Atari ST (double-sided diskettes)
// Game version 1.003.006 (January 12, 1989)
@@ -1188,7 +1223,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "a3cdb4848fb859fdd302976fff56490f", 705074},
{"resource.004", 0, "a3cdb4848fb859fdd302976fff56490f", 478366},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.004.018"
@@ -1204,7 +1239,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "26c0c25399b6715fec03fc3e12544fe3", 823048},
{"resource.007", 0, "b914b5901e786327213e779725d30dd1", 778772},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
@@ -1220,7 +1255,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "56546b20db11a4836f900efa6d3a3e74", 672099},
{"resource.007", 0, "56546b20db11a4836f900efa6d3a3e74", 794194},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - Italian Amiga (also includes english language)
// Executable scanning reports "1.004.024"
@@ -1236,7 +1271,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 672527},
{"resource.007", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 794259},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English DOS CD (from the King's Quest Collection)
// Executable scanning reports "x.yyy.zzz", VERSION file reports "1.000.052"
@@ -1246,7 +1281,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368},
{"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English DOS CD (from the King's Quest Collection)
// Executable scanning reports "x.yyy.zzz", VERSION file reports "1.000.052"
@@ -1258,7 +1293,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368},
{"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English DOS Floppy
// SCI interpreter version 1.000.060
@@ -1273,7 +1308,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "672ede1136e9e401658538e51bd5dc22", 1172619},
{"resource.007", 0, "2f48faf27666b58c276dda20f91f4a93", 1240456},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English DOS Floppy
// VERSION file reports "0.000.051"
@@ -1291,7 +1326,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456},
{"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English DOS Floppy (supplied by omer_mor in bug report #3036996)
// VERSION file reports "0.000.051"
@@ -1306,7 +1341,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "06cb3f689836086ebe08b1efc0126592", 921113},
{"resource.007", 0, "252249753c6e850eacceb8af634986d3", 1133608},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 EGA (supplied by markcoolio in bug report #2829470)
// SCI interpreter version 1.000.060
@@ -1322,7 +1357,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666527},
{"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541743},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 EGA 1.2M disk version (from LordHoto)
// VERSION file reports "0.000.055"
@@ -1334,7 +1369,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "53206afb4fd73871a484e83acab80f31", 7608},
{"resource.004", 0, "83568edf7fde18b3eed988bc5d22ceb1", 1188053},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 EGA (supplied by omer_mor in bug report #3035421)
// VERSION file reports "0.000.062"
@@ -1349,7 +1384,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666541},
{"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541762},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest V DOS 0.000.062 EGA (5 x 5.25" disks)
// Supplied by ssburnout in bug report #3046780
@@ -1361,7 +1396,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "3cca5b2dae8afe94532edfdc98d7edbe", 1092325},
{"resource.004", 0, "8e5c1bc4d738cf7316ff506f59d265e2", 1187803},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 DOS Spanish Floppy 0.000.062 VGA (5 x 3.5" disks)
// Supplied by dianiu in bug report #3555646
@@ -1376,7 +1411,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "65b520e60c4217e6a6572d9edf77193b", 1141985},
{"resource.007", 0, "f42b0100f0a1c30806814f8648b6bc28", 1145583},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101, also includes english language)
// SCI interpreter version 1.000.060
@@ -1391,7 +1426,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "d1a75fdc01840664d00366cff6919366", 1208972},
{"resource.007", 0, "c07494f0cce7c05210893938786a955b", 1337361},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - French DOS Floppy (from the King's Quest Collector's Edition 1994, also includes english language)
// Supplied by aroenai in bug report #2812611
@@ -1407,7 +1442,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "f7dc85307632ef657ceb1651204f6f51", 1210081},
{"resource.007", 0, "7db4d0a1d8d547c0019cb7d2a6acbdd4", 1338473},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - Italian DOS Floppy (from glorifindel, includes english language)
// SCI interpreter version 1.000.060
@@ -1422,7 +1457,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "8eeabd92af71e766e323db2100879102", 1209325},
{"resource.007", 0, "dc10c107e0923b902326a040b9c166b9", 1337859},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722)
// SCI interpreter version 1.000.060
@@ -1440,7 +1475,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176},
{"text.000", 0, "601aa35a3ddeb558e1280e0963e955a2", 1517},
AD_LISTEND},
- Common::PL_POL, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - English Macintosh
// VERSION file reports "1.000.055"
@@ -1455,7 +1490,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "3d22904a374c192f51e5665b74364133", 1264079},
{"resource.007", 0, "ffe17e23d5833a79f3695addfc149a56", 1361965},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 5 - FM-Towns (supplied by abevi in bug report #3038720)
{"kq5", "", {
@@ -1463,7 +1498,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "71afd220d46bde1109c58e6acc0f3a01", 469094},
{"resource.001", 0, "72a569f46f1abf2d9d2b1526ad3799c3", 12808839},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO2(GUIO_NOASPECT, GUIO_MIDITOWNS) },
+ Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO2(GUIO_NOASPECT, GUIO_MIDITOWNS) },
{"kq5", "", {
{"resource.map", 0, "20c7cd248ff1a349ed354568eebd972b", 12733},
{"resource.000", 0, "71afd220d46bde1109c58e6acc0f3a01", 469094},
@@ -1481,7 +1516,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "e114ce8f884601c43308fb5cbbea4874", 1174129},
{"resource.005", 0, "349ad9438172265d00680075c5a988d0", 1019669},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - English DOS Non-Interactive Demo
// Executable scanning reports "1.001.055", VERSION file reports "1.000.000"
@@ -1491,7 +1526,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "535b1b920441ec73f42eaa4ccfd47b89", 264116},
{"resource.msg", 0, "54d1fdc936f98c81f9e4c19e04fb1510", 8260},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - English DOS Floppy
// SCI interpreter version 1.001.054
@@ -1500,7 +1535,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
{"resource.msg", 0, "3cf5de44de36191f109d425b8450efc8", 258590},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - French DOS Floppy (supplied by misterhands in bug #3503425)
// SCI interpreter version ???
@@ -1509,7 +1544,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
{"resource.msg", 0, "adc2aa8adbdcc97507d44a6f492fbd77", 265194},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - German DOS Floppy (supplied by markcoolio in bug report #2727156)
// SCI interpreter version 1.001.054
@@ -1518,7 +1553,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
{"resource.msg", 0, "756297b2155db9e43f621c6f6fb763c3", 282822},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - Spanish DOS Floppy (from jvprat)
// Executable scanning reports "1.cfs.158", VERSION file reports "1.000.000, July 5, 1994"
@@ -1528,7 +1563,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260},
{"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - Italian DOS Floppy (supplied by guybrush79 in bug report #3606719)
{"kq6", "", {
@@ -1536,7 +1571,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "d3358ba7306378aed83d02b5c3f11311", 8531908},
{"resource.msg", 0, "b7e8220be596fd6a9287eae5a8fd354a", 279886},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - English DOS CD (from the King's Quest Collection)
// Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G"
@@ -1545,7 +1580,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215},
{"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - English Windows CD (from the King's Quest Collection)
// Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G"
@@ -1554,7 +1589,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215},
{"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ6_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ6_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 6 - English Macintosh Floppy
// VERSION file reports "1.0"
@@ -1562,7 +1597,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "a183fc0c22fcbd9be4c8800d974b5599", 3892124},
{"Data2", 0, "b3722460dfd3097a1fbaf99a21ad8ea5", 15031272},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
@@ -1573,7 +1608,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195},
{"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English Windows (from the King's Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.4"
@@ -1581,7 +1616,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2be9ab94429c721af8e05c507e048a15", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 203882535},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English DOS (from FRG)
// SCI interpreter version 2.100.002, VERSION file reports "2.00b"
@@ -1589,7 +1624,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English Windows (from FRG)
// SCI interpreter version 2.100.002, VERSION file reports "2.00b"
@@ -1597,7 +1632,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - German Windows (supplied by markcoolio in bug report #2727402)
// SCI interpreter version 2.100.002
@@ -1605,7 +1640,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - Spanish DOS (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "2.00"
@@ -1613,7 +1648,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "0b62693cbe87e3aaca3e8655a437f27f", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English DOS Non-Interactive Demo
// SCI interpreter version 2.100.002
@@ -1621,7 +1656,23 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "b44f774108d63faa1d021101221c5a54", 1690},
{"resource.000", 0, "d9659d2cf0c269c6a9dc776707f5bea0", 2433827},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // King's Quest 7 - English Windows Demo (from DrMcCoy)
+ // SCI interpreter version 2.100.002
+ {"kq7", "Demo", {
+ {"resource.map", 0, "38e627a37a975aea40cc72b0518b0709", 18412},
+ {"resource.000", 0, "bad61d50aaa64298fa57a7c6ccd3bccf", 84020382},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // King's Questions mini-game from the King's Quest Collection
+ // SCI interpreter version 2.000.000
+ {"kquestions", "", {
+ {"resource.000", 0, "9b1cddecd4f0720d83661ba7aed28891", 162697},
+ {"resource.map", 0, "93a2251fa64e729d7a7d2fe56b217c8e", 502},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO3(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
@@ -1637,7 +1688,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "aa553977f7e5804081de293800d3bcce", 695067},
{"resource.005", 0, "bfd870d51dc97729f0914095f58e6957", 676881},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow - English Atari ST (from jvprat)
// Executable scanning reports "1.002.030", Floppy label reports "1.000.062, 9.23.90"
@@ -1649,7 +1700,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667365},
{"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683737},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow - English DOS Non-Interactive Demo
// Executable scanning reports "x.yyy.zzz"
@@ -1657,7 +1708,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "e625726268ff4e123ada11f31f0249f3", 768},
{"resource.001", 0, "0c8912290af0890f8d95faeb4ddb2d68", 333031},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow - English DOS 3.5" Floppy (from "The Roberta Williams Anthology"/1996)
// SCI interpreter version 0.000.631
@@ -1668,7 +1719,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667468},
{"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683807},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow - English DOS (from FRG)
// SCI interpreter version 0.000.631
@@ -1682,7 +1733,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390},
{"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "x.yyy.zzz"
@@ -1691,7 +1742,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "24dffc5db1d88c7999f13e8767ed7346", 855},
{"resource.000", 0, "2b2b1b4f7584f9b38fd13f6ab95634d1", 781912},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 - English DOS Floppy
// Executable scanning reports "2.000.274"
@@ -1700,7 +1751,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "610bfd9a852004222f0faaf5fc9e630a", 6489},
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5035964},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 - English DOS CD (from "The Roberta Williams Antology"/1996)
// Executable scanning reports "1.001.072", VERSION file reports "1.1" (from jvprat)
@@ -1709,7 +1760,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a70945e61ba7ac7bfea6b7bd72c6aec5", 7274},
{"resource.000", 0, "82578b8d5a7e09c4c58891ca49fae35b", 5598672},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 v1.1 - French DOS Floppy (from Hkz)
{"laurabow2", "", {
@@ -1717,7 +1768,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "0fceedfbdd85a4bc7851fdd9dd2d2f19", 278253},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 v1.1 - German DOS Floppy (from Tobis87, updated info from markcoolio in bug report #2723787, updated info from #2797962))
// Executable scanning reports "2.000.274"
@@ -1726,7 +1777,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "795c928cd00dfec9fbc62ebcd12e1f65", 303185},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Laura Bow 2 - Spanish DOS CD (from jvprat)
// Executable scanning reports "2.000.274", VERSION file reports "1.000.000, May 10, 1994"
@@ -1735,7 +1786,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "71f1f0cd9f082da2e750c793a8ed9d84", 286141},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 EGA Remake - English DOS (from spookypeanut)
// SCI interpreter version 0.000.510 (or 0.000.577?)
@@ -1746,7 +1797,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "24c958bc922b07f91e25e8c93aa01fcf", 491230},
{"resource.003", 0, "685cd6c1e05a695ab1e0db826337ee2a", 553279},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#if 0
// The resource.002 file, contained in disk 3, is broken in this version
@@ -1764,7 +1815,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041},
{"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif
// Larry 1 VGA Remake - English DOS (from spookypeanut)
@@ -1775,7 +1826,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226},
{"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - English DOS (from FRG)
// SCI interpreter version 1.000.510
@@ -1785,7 +1836,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688},
{"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - English Macintosh (from omer_mor, bug report #3328262)
{"lsl1sci", "SCI", {
@@ -1794,7 +1845,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "aa6f153f70f1e32d1bde465fff08eecf", 1137418},
{"resource.002", 0, "b22c616aa789ebef990290c7ffd86548", 1097477},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.084
@@ -1802,7 +1853,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "434e1f6c39d71647b34f0ee57b2bbd68", 444},
{"resource.001", 0, "0c0768215c562d9dace4a5ca53696cf3", 359913},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - Spanish DOS (from the Leisure Suit Larry Collection, also includes english language)
// Executable scanning reports "1.SQ4.057", VERSION file reports "1.000"
@@ -1815,7 +1866,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908},
{"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - Russian DOS (also includes english language?!)
// Executable scanning reports "1.000.510", VERSION file reports "2.0"
@@ -1826,7 +1877,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759},
{"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160},
AD_LISTEND},
- Common::RU_RUS, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::RU_RUS, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 1 VGA Remake - Polish DOS (from Polish Leisure Suit Larry Collection, official release)
// SCI interpreter version 1.000.577, VERSION file reports "2.1" (this release does NOT include english text)
@@ -1834,7 +1885,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "58330a85767e42a2487129913283ab5b", 3228},
{"resource.000", 0, "b6097ff35cdc8469f02150fe2f824198", 4781210},
AD_LISTEND},
- Common::PL_POL, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::PL_POL, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English Amiga (from www.back2roots.org)
// Executable scanning reports "x.yyy.zzz"
@@ -1846,7 +1897,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "a0d4a625311d307257da7fc43d00459d", 570356},
{"resource.004", 0, "a0d4a625311d307257da7fc43d00459d", 717844},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English DOS Non-Interactive Demo
// Executable scanning reports "x.yyy.zzz"
@@ -1855,7 +1906,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528},
{"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English DOS
// SCI interpreter version 0.000.409
@@ -1868,7 +1919,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732},
{"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English DOS
// SCI interpreter version 0.000.343
@@ -1883,7 +1934,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
//{"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818},
{"resource.006", 0, "96033f57accfca903750413fd09193c8", -1}, // 345818 or 208739
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English DOS (supplied by ssburnout in bug report #3049193)
// 1.000.011 3x3.5" (label: Int. #0.000.343)
@@ -1893,7 +1944,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "96033f57accfca903750413fd09193c8", 407014},
{"resource.003", 0, "96033f57accfca903750413fd09193c8", 592834},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 2 - English DOS (supplied by ssburnout in bug report #3049193)
// 1.002.000 3x3.5" (label: INT#0.000.409)
@@ -1903,7 +1954,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406935},
{"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592533},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.032"
@@ -1917,7 +1968,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "f408e59cbee1457f042e5773b8c53951", 651634},
{"resource.005", 0, "433911eb764089d493aed1f958a5615a", 524259},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English DOS (supplied by ssburnout in bug report #3049193)
// 1.021 8x5.25" (label: Int#5.15.90)
@@ -1931,7 +1982,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "f18441027154292836b973c655fa3175", 282649},
{"resource.007", 0, "f18441027154292836b973c655fa3175", 257178},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English DOS
// SCI interpreter version 0.000.572
@@ -1945,7 +1996,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "f18441027154292836b973c655fa3175", 282465},
{"resource.007", 0, "f18441027154292836b973c655fa3175", 257174},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English DOS
// SCI interpreter version 0.000.572
@@ -1956,7 +2007,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "f18441027154292836b973c655fa3175", 506807},
{"resource.004", 0, "f18441027154292836b973c655fa3175", 513651},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English DOS (supplied by kervala in bug report #3611488)
{"lsl3", "", {
@@ -1966,7 +2017,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "f18441027154292836b973c655fa3175", 506817},
{"resource.004", 0, "f18441027154292836b973c655fa3175", 513337},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - English DOS Non-Interactive Demo
// SCI interpreter version 0.000.530
@@ -1975,7 +2026,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 76525},
{"resource.002", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 268299},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723832, also includes english language)
// Executable scanning reports "S.old.123"
@@ -1987,7 +2038,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 587036},
{"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 691932},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 - French DOS (provided by richiefs in bug report #2670691, also includes english language)
// Executable scanning reports "S.old.123"
@@ -1999,7 +2050,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "65f1bdaa20f6d0470e9d969f22473873", 586921},
{"resource.004", 0, "65f1bdaa20f6d0470e9d969f22473873", 690826},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 3 1.050 Fr/En (9 x 5.25" disks)
// Provided by ssburnout in bug report #3046779
@@ -2013,7 +2064,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "65f1bdaa20f6d0470e9d969f22473873", 325292},
{"resource.007", 0, "65f1bdaa20f6d0470e9d969f22473873", 308982},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - English Amiga
// Executable scanning reports "1.004.023"
@@ -2028,7 +2079,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621},
{"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
@@ -2044,7 +2095,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966},
{"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.000.181
@@ -2052,7 +2103,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "efe8d3f45ce4f6bd9a6643e0ac8d2a97", 504},
{"resource.001", 0, "8bd8d9c0b5f455ee1269d63ce86c50dd", 531380},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - English DOS (from spookypeanut)
// SCI interpreter version 1.000.510
@@ -2067,7 +2118,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - English Macintosh (from omer_mor, bug report #3328257)
{"lsl5", "", {
@@ -2081,7 +2132,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1110043},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 989801},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - German DOS (from Tobis87)
// SCI interpreter version T.A00.196
@@ -2096,7 +2147,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - French DOS (provided by richiefs in bug report #2670691)
// Executable scanning reports "1.lsl5.019"
@@ -2112,7 +2163,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - Spanish DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.ls5.006", VERSION file reports "1.000, 4/21/92"
@@ -2128,7 +2179,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 - Italian DOS Floppy (from glorifindel)
// SCI interpreter version 1.000.510 (just a guess)
@@ -2136,7 +2187,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919},
{"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 1.0 EGA DOS (8 x 3.5" disks)
// Provided by ssburnout in bug report #3046806
@@ -2151,7 +2202,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "f6046a8445422f17d40b1b10ab21ebf3", 568551},
{"resource.007", 0, "640ee65595d40372ef95462f2c1ae28a", 593429},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 5 EGA
// Supplied by omer_mor in bug report #3049771
@@ -2162,7 +2213,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "5a55af4e40728b1a8103dc47ad2afa8d", 1100539},
{"resource.003", 0, "16f4d8fb1b526125edaca4fc6cbb7530", 1064563},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - English DOS (from spookypeanut)
// SCI interpreter version 1.001.113
@@ -2170,7 +2221,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "bb8a39d9e2a77ba449a1e591109ad9a8", 6973},
{"resource.000", 0, "4462fe48c7452d98fddcec327a3e738d", 5789138},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - English/German/French DOS CD - LOWRES
// SCI interpreter version 1.001.115
@@ -2178,7 +2229,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263},
{"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - German DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
@@ -2186,7 +2237,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - French DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
@@ -2194,7 +2245,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - Spanish DOS - LOWRES (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.001.113", VERSION file reports "1.000, 11.06.93, FIVE PATCHES ADDED TO DISK 6 ON 11-18-93"
@@ -2202,7 +2253,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943},
{"resource.000", 0, "7884a8db9253e29e6b37a2651fd90ba3", 5733116},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Crazy Nick's Software Picks: Leisure Suit Larry's Casino - English DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.001.029", VERSION file reports "1.000"
@@ -2210,35 +2261,35 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "194f1578f2624db813c9072359ad1639", 783},
{"resource.001", 0, "3733433b517ec3d14a3331d9ab3842ae", 344830},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Crazy Nick's Software Picks: King Graham's Board Game Challenge
{"cnick-kq", "", {
{"resource.map", 0, "44bc538a5cd24b39ffccc967c0ebf84d", 1137},
{"resource.001", 0, "470e7a4a3504635e70b623c44461e1ac", 451272},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Crazy Nick's Software Picks: Parlor Games with Laura Bow
{"cnick-laurabow", "", {
{"resource.map", 0, "3b826bfe64f8ff1ccf30eef93cd2f727", 999},
{"resource.001", 0, "985ac8db6f636f2b4334c04b0fbb44fb", 336698},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Crazy Nick's Software Picks: Robin Hood's Game of Skill and Chance
{"cnick-longbow", "", {
{"resource.map", 0, "4a5c81f485a2416bde12978506f2fb5f", 897},
{"resource.001", 0, "ef16dc9e867eb8eeb5b13e110b90bd4b", 571466},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Crazy Nick's Software Picks: Roger Wilco's Spaced Out Game Pack
{"cnick-sq", "", {
{"resource.map", 0, "b4d95b02d84e297441bd999d34eaa6b1", 879},
{"resource.001", 0, "82ff2b64a60117886fbcd6a3a8c977c6", 364921},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Larry 6 - English/German DOS CD - HIRES
@@ -2247,7 +2298,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872},
{"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - German DOS CD - HIRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 2.100.002
@@ -2255,7 +2306,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896},
{"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 6 - French DOS CD - HIRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 2.100.002
@@ -2263,7 +2314,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896},
{"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 7 - English DOS Demo (provided by richiefs in bug report #2670691)
// SCI interpreter version 2.100.002
@@ -2271,7 +2322,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878},
{"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI3_GAMES
// Larry 7 - English DOS CD (from spookypeanut)
@@ -2280,7 +2331,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "eae93e1b1d1ccc58b4691c371281c95d", 8188},
{"ressci.000", 0, "89353723488219e25589165d73ed663e", 66965678},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 7 - German DOS (from Tobis87)
// SCI interpreter version 3.000.000
@@ -2288,7 +2339,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "c11e6bfcfc2f2d05da47e5a7df3e9b1a", 8188},
{"ressci.000", 0, "a8c6817bb94f332ff498a71c8b47f893", 66971724},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 7 - French DOS (provided by richiefs in bug report #2670691)
// SCI interpreter version 3.000.000
@@ -2296,7 +2347,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "4407849fd52fe3efb0c30fba60cd5cd4", 8206},
{"ressci.000", 0, "dc37c3055fffbefb494ff22b145d377b", 66964472},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 7 - Italian DOS CD (from glorifindel)
// SCI interpreter version 3.000.000
@@ -2304,7 +2355,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "9852a97141f789413f29bf956052acdb", 8212},
{"ressci.000", 0, "440b9fed89590abb4e4386ed6f948ee2", 67140181},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Larry 7 - Spanish DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "3.000.000", VERSION file reports "1.0s"
@@ -2312,7 +2363,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "8f3d603e1acc834a5d598b30cdfc93f3", 8188},
{"ressci.000", 0, "32792f9bc1bf3633a88b382bb3f6e40d", 67071418},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif
// Lighthouse - English Windows Demo (from jvprat)
@@ -2321,7 +2372,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "543124606352bfa5e07696ddf2a669be", 64},
{"resource.000", 0, "5d7714416b612463d750fb9c5690c859", 28952},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI3_GAMES
// Lighthouse - English Windows Demo
@@ -2330,7 +2381,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "3bdee7a16926975a4729f75cf6b80a92", 1525},
{"ressci.000", 0, "3c585827fa4a82f4c04a56a0bc52ccee", 11494351},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Lighthouse - English DOS (from jvprat)
// Executable scanning reports "3.000.000", VERSION file reports "1.1"
@@ -2340,7 +2391,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.002", 0, "c68db5333f152fea6ca2dfc75cad8b34", 7573},
{"ressci.002", 0, "175468431a979b9f317c294ce3bc1430", 94628315},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Lighthouse - Spanish DOS (from jvprat)
// Executable scanning reports "3.000.000", VERSION file reports "1.1"
@@ -2350,7 +2401,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.002", 0, "e7dc85884a2417e2eff9de0c63dd65fa", 7630},
{"ressci.002", 0, "3c8d627c555b0e3e4f1d9955bc0f0df4", 94631127},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI3_GAMES
#endif // ENABLE_SCI32
@@ -2361,7 +2412,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "8be56a3a88c065ee00c02c0e29199f3a", 14643},
{"resource.001", 0, "9e33566515b18bee7915db448063bba2", 871853},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Fairy Tales - English DOS Floppy EGA (from omer_mor, bug report #3035350)
{"fairytales", "EGA", {
@@ -2372,7 +2423,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "509b2467ba779100d5933ed51a9ae32f", 560255},
{"resource.004", 0, "93afc85d5ffa60ea555d6cc336d22c03", 651109},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Fairy Tales v1.000 - English DOS (supplied by markcoolio in bug report #2723791)
// Executable scanning reports "1.000.145"
@@ -2384,7 +2435,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "b1288e0821ee358d1ffe877e5900c8ec", 1047565},
{"resource.004", 0, "f79daa70390d73746742ffcfc3dc4471", 937580},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Fairy Tales - English DOS Floppy (from jvprat)
// Executable scanning reports "1.000.145", Floppy label reports "1.0, 11.13.91", VERSION file reports "1.000"
@@ -2395,7 +2446,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "564f516d991032e781492592a4eaa275", 1414142},
{"resource.003", 0, "dd6cef0c592eadb7e6be9a25307c57a2", 1344719},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.003.009"
@@ -2405,7 +2456,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "fb552ae550ca1dac19ed8f6a3767612d", 262885},
{"resource.002", 0, "fb552ae550ca1dac19ed8f6a3767612d", 817191},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - English DOS Floppy EGA (from omer_mor, bug report #3035354)
{"mothergoose", "EGA", {
@@ -2413,7 +2464,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "d893892d62b3f061357291d66775e360", 239906},
{"resource.002", 0, "d893892d62b3f061357291d66775e360", 719398},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - English DOS Floppy EGA (supplied by ssburnout in bug report #3049193)
// 1.011 5x5.25" (label: Int#8.2.90)
@@ -2426,7 +2477,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "dbbc22f124533ce308bc386b08956326", 146251},
{"resource.005", 0, "2ba5348e7fad641b9c4c7ff7c7cf4e68", 110979},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose v2.000 - English DOS Floppy (supplied by markcoolio in bug report #2723795)
// Executable scanning reports "1.001.031"
@@ -2434,7 +2485,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "52aae15e493cafd1da7e1c9b657a5bb9", 7026},
{"resource.000", 0, "b7ecd8ae9e254e80310b5a668b276e6e", 2948975},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - English DOS CD (from jvprat)
// Executable scanning reports "x.yyy.zzz"
@@ -2443,7 +2494,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "1c7f311b0a2c927b2fbe81ae341fb2f6", 5790},
{"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 4369438},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - English Windows Interactive Demo
// Executable scanning reports "x.yyy.zzz"
@@ -2451,19 +2502,19 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "87f9dc1cafc4d4fa835fb2f00cf3a6ef", 4560},
{"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 2070072},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose - FM-Towns (supplied by abevi in bug report #3038720)
{"mothergoose256", "", {
{"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
{"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
{"mothergoose256", "", {
{"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
{"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810)
@@ -2472,7 +2523,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "5159a1578c4306bfe070a3e4d8c2e1d3", 4741},
{"resource.000", 0, "1926925c95d82f0999590e93b02887c5", 15150768},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Mixed-Up Mother Goose Deluxe - Multilingual Windows CD (English/French/German/Spanish)
// Executable scanning reports "2.100.002"
@@ -2480,7 +2531,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "ef611af561898dcfea87846919ebf3eb", 4969},
{"ressci.000", 0, "227685bc59d90821978d330713e44a7a", 17205800},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
// Ms. Astro Chicken - English DOS
@@ -2489,7 +2540,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158},
{"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Phantasmagoria - English DOS (from jvprat)
@@ -2510,7 +2561,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.007", 0, "afbd16ea77869a720afa1c5371de107d", 7972},
//{"ressci.007", 0, "3aae6559aa1df273bc542d5ac6330d75", 25859038},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Phantasmagoria - English DOS Demo
// Executable scanning reports "2.100.002"
@@ -2518,7 +2569,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.001", 0, "416138651ea828219ca454cae18341a3", 11518},
{"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 65844612},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Phantasmagoria - English DOS/Windows (GOG version) - ressci.* merged in ressci.000
// Windows executable scanning reports "2.100.002" - "Sep 19 1995 15:09:43"
@@ -2529,7 +2580,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "cd5967f9b9586e3380645961c0765be3", 116822037},
{"resmap.000", 0, "3cafc1c6a53945c1f3babbfd6380c64c", 16468},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Phantasmagoria - English Macintosh
// NOTE: This only contains disc 1 files (as well as the two persistent files:
@@ -2562,7 +2613,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.005", 0, "8bd5ceeedcbe16dfe55d1b90dcd4be84", 1942},
{"ressci.005", 0, "05f9fe2bee749659acb3cd2c90252fc5", 67905112},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Phantasmagoria 2 - English DOS (GOG version) - ressci.* merged in ressci.000
// Executable scanning reports "3.000.000" - "Dec 07 1996 09:29:03"
@@ -2572,7 +2623,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "c54f26d9f43f908151263254b6d97053", 108134481},
{"resmap.000", 0, "de154a223a9ef4ea7358b76adc38ef5b", 2956},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI3_GAMES
#endif // ENABLE_SCI32
@@ -2583,7 +2634,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "72726dc81c1b4c1110c486be77369bc8", 5179},
{"resource.000", 0, "670d0c53622429f4b11275caf7f8d292", 5459574},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Pepper - English DOS Non-Interactive Demo
// Executable scanning reports "1.001.060", VERSION file reports "1.000"
@@ -2591,7 +2642,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "379bb4fb896630b14f2d91ed21e36ba1", 984},
{"resource.000", 0, "118f6c31a93ec7fd9a231c61125229e3", 645494},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Pepper - English DOS/Windows Interactive Demo
// Executable scanning reports "1.001.069", VERSION file reports ".001"
@@ -2599,7 +2650,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "975e8df76106a5c13d12ab674f906a02", 2514},
{"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1698164},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Pepper - English DOS Interactive Demo
// Executable scanning reports "1.001.072", VERSION file reports "1.000"
@@ -2607,7 +2658,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "9c9b7b900651a370dd3fb38d478b1798", 2524},
{"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1713544},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 1 VGA Remake - English DOS (from the Police Quest Collection)
// Executable scanning reports "1.001.029", VERSION file reports "2.000"
@@ -2615,7 +2666,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "35efa814fb994b1cbdac9611e401da67", 5013},
{"resource.000", 0, "e0d5ddf34eda903a38f0837e2aa7145b", 6401433},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - English Amiga (from www.back2roots.org)
// SCI interpreter version 0.000.685 (just a guess)
@@ -2626,7 +2677,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "499737c21a28ac026e11ab817100d610", 511099},
{"resource.003", 0, "e008f5d6e2a7c4d4a0da0173e4fa8f8b", 553970},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - English DOS Non-Interactive Demo
// Executable scanning reports "0.000.413"
@@ -2634,7 +2685,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576},
{"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - English DOS (provided by richiefs in bug report #2670691)
// SCI interpreter version 0.000.395
@@ -2647,7 +2698,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899},
{"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - English DOS (from the Police Quest Collection)
// Executable scanning reports "0.000.490"
@@ -2657,7 +2708,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000},
{"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - English DOS (from FRG)
// SCI interpreter version 0.000.395
@@ -2667,7 +2718,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897},
{"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 English DOS 1.001.006 (supplied by merkur-kun in bug report #3028479)
{"pq2", "", {
@@ -2676,7 +2727,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261},
{"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - Japanese PC-98 (also includes english language)
// SCI interpreter version unknown
@@ -2686,7 +2737,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 637662},
{"resource.003", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 684395},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - English Amiga
// Executable scanning reports "1.004.024"
@@ -2699,7 +2750,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891},
{"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
@@ -2713,7 +2764,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738},
{"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - English DOS (from the Police Quest Collection)
// Executable scanning reports "T.A00.178", VERSION file reports "1.00"
@@ -2726,7 +2777,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791},
{"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - English DOS Non-Interactive Demo
// Executable scanning reports "T.A00.052"
@@ -2736,7 +2787,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150},
{"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - German DOS (supplied by markcoolio in bug report #2723837, also includes english language)
// Executable scanning reports "T.A00.178"
@@ -2749,14 +2800,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956},
{"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - Spanish DOS v1.000 - Supplied by dianiu in bug report #3555647
{"pq3", "", {
{"resource.map", 0, "ffa0b4631c4e36d69631256d19ba29e7", 5421},
{"resource.000", 0, "5ee460af3d70c06a745cc482b6c783ba", 5410263},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 EGA
// Reported by musiclyinspired in bug report #3046573
@@ -2769,7 +2820,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "b96a86ab681769e4cbb439670d967ca6", 449682},
{"resource.005", 0, "9e6c53a0e7eef53694d260fade8b1fc7", 724000},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.096
@@ -2777,7 +2828,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "be56f87a1c4a13062a30a362df860c2f", 1472},
{"resource.000", 0, "527d5684016e6816157cd15d9071b11b", 1121310},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Police Quest 4 - English DOS CD (from the Police Quest Collection)
@@ -2786,7 +2837,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374},
{"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 4 - German DOS CD (German text, English speech)
// Supplied by markcoolio in bug report #3392955
@@ -2794,7 +2845,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a398076371ed0e1e706c8f9fb9fc7ac5", 11386},
{"resource.000", 0, "6ff21954e0a2c5992279e7eb787c8d56", 18918747},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 4 - English DOS
// SCI interpreter version 2.000.000 (a guess?)
@@ -2802,7 +2853,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "aed9643158ccf01b71f359db33137f82", 9895},
{"resource.000", 0, "da383857b3be1e4514daeba2524359e0", 15141432},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 4 - French DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 2.000.000
@@ -2810,7 +2861,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "008030846edcc7c5c7a812c7f4ae4ceb", 9256},
{"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730153},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 4 - German DOS (supplied by markcoolio in bug report #2723840)
// SCI interpreter version 2.000.000 (a guess?)
@@ -2818,7 +2869,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2393ee728ab930b2762cb5889f9b5aff", 9256},
{"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730155},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest: SWAT - English DOS/Windows Demo (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "0.001.200"
@@ -2826,7 +2877,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8c96733ef94c21526792f7ca4e3f2120", 1648},
{"resource.000", 0, "d8892f1b8c56c8f7704325460f49b300", 3676175},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest: SWAT - English DOS (from GOG.com)
// Executable scanning reports "2.100.002", VERSION file reports "1.0c"
@@ -2834,7 +2885,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "1c2563fee189885e29d9348f37306d94", 12175},
{"ressci.000", 0, "b2e1826ca81ce2e7e764587f5a14eee9", 127149181},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest: SWAT - English Windows (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.0c"
@@ -2849,7 +2900,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.004", 0, "4228038906f041623e65789500b22285", 6835},
{"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by merkur in bug report #2718784)
@@ -2862,7 +2913,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203},
{"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by alonzotg in bug report #3206006)
{"qfg1", "", {
@@ -2873,7 +2924,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203},
{"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy v1.102 Int#0.000.629 (suppled by digitoxin1 in bug report #3554611)
{"qfg1", "", {
@@ -2884,7 +2935,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502},
{"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy v1.102 Int#0.000.629 (suppled by digitoxin1 in bug report #3554611)
{"qfg1", "", {
@@ -2898,7 +2949,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "48b2b3c964dcbeccb68e984e6d4e97db", 278473},
{"resource.007", 0, "f0af87c60ec869946da442833aa5afa8", 269237},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843)
// Executable scanning reports "0.000.566"
@@ -2913,7 +2964,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852},
{"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193)
// 1.001 10x5.25" (label: INT.#0.000.566)
@@ -2928,7 +2979,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852},
{"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by ssburnout in bug report #3049193)
// 1.200 10x5.25" (label: INT#9.10.90)
@@ -2943,7 +2994,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "f46690dca714abc8c89357d30e363dd3", 278387},
{"resource.007", 0, "951299a82a8134ed12c5c18118d45c2f", 269173},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 / Hero's Quest - English DOS Demo
// Executable scanning reports "0.000.685"
@@ -2951,7 +3002,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "df34c758cbb9026da175793ff686b0e6", 882},
{"resource.001", 0, "73fbaafdd313b39aeedb80fbf85ecef1", 389884},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
@@ -2961,7 +3012,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1136968},
{"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 769897},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) },
// Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
@@ -2971,7 +3022,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1147121},
{"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 777575},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO3(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER) },
// Quest for Glory 1 - English Amiga
// Executable scanning reports "1.002.020"
@@ -2985,7 +3036,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 689124},
{"resource.005", 0, "5f3386ef2f2b1254e4a066f5d9027324", 609529},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 - English DOS
// SCI interpreter version 0.000.629
@@ -2997,7 +3048,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "951299a82a8134ed12c5c18118d45c2f", 640483},
{"resource.004", 0, "951299a82a8134ed12c5c18118d45c2f", 644443},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 VGA Remake - English DOS
// Executable scanning reports "2.000.411"
@@ -3005,7 +3056,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a731fb6c9c0b282443f7027bc8694d4c", 8469},
{"resource.000", 0, "ecace1a2771846b1a8aa1afdd44111a0", 6570147},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 VGA Remake - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.029
@@ -3013,7 +3064,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ac0257051c95a59c0cdc0be24d9b11fa", 729},
{"resource.000", 0, "ec6f5cf369054dd3e5392995e9975b9e", 768218},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 1 VGA Remake - English Macintosh Floppy
// VERSION file reports "2.0"
@@ -3021,7 +3072,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "106527ff8756e4e1a795d63d23e8b833", 1752358},
{"Data2", 0, "5cdd92033231159c6e9c71d43e9f194d", 6574746},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English Amiga
// Executable scanning reports "1.003.004"
@@ -3037,7 +3088,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "ccf5dba33e5cab6d5872838c0f8db44c", 500039},
{"resource.007", 0, "4c9fc1587545879295cb9627f56a2cb8", 575056},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193)
// 1.000 5x5.25" (label: INT#10.31.90)
@@ -3049,7 +3100,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "0790f67d87642132be515cab05026baa", 972144},
{"resource.004", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 982830},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English (supplied by ssburnout in bug report #3049193)
// 1.000 9x3.5" (label: INT#10.31.90)
@@ -3064,7 +3115,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "5e9deacbdb17198ad844988e04833520", 498593},
{"resource.007", 0, "2ac1e6fea9aa1f5b91a06693a67b9766", 490151},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English (from FRG)
// Executable scanning reports "1.000.072"
@@ -3076,7 +3127,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "b192607c42f6960ecdf2ad2e4f90e9bc", 972804},
{"resource.004", 0, "cd2de58e27665d5853530de93fae7cd6", 983617},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English DOS
// Executable scanning reports "1.000.072"
@@ -3091,7 +3142,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489},
{"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English DOS (supplied by digitoxin1 in bug report #3554614)
// v1.102 9x3.5" (label: Int#11.20.90)
@@ -3106,7 +3157,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489},
{"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 2 - English DOS Non-Interactive Demo
// Executable scanning reports "1.000.046"
@@ -3114,7 +3165,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "e75eb86bdd517b3ef709058249986a87", 906},
{"resource.001", 0, "9b098f9e1008abe30e56c93b896494e6", 362123},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "1.001.021", VERSION file reports "1.000, 0.001.059, 6.12.92"
@@ -3122,7 +3173,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "fd71de9b588a45f085317caacf050e91", 687},
{"resource.000", 0, "b6c69bf6c18bf177492249fe81fc6a6d", 648702},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - English DOS
// SCI interpreter version 1.001.050
@@ -3130,7 +3181,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - English DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 1.001.050
@@ -3138,7 +3189,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "62c185d190363d7df06330fa0cc45b36", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5867442},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - English DOS (supplied by dknute in bug report #3125559)
{"qfg3", "", {
@@ -3146,7 +3197,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042},
{"resource.msg", 0, "27e5419c98ce444253f88c95dced14a9", 246888},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - German DOS (supplied by markcoolio in bug report #2723846)
// Executable scanning reports "L.rry.083"
@@ -3154,7 +3205,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - French DOS v1.1 (supplied by misterhands in bug report #3586214)
// Executable scanning reports "L.rry.083"
@@ -3163,7 +3214,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000},
{"resource.msg", 0, "0fa1047002df904b8d1807bb7bab4fab", 267210},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - Spanish DOS CD (from jvprat)
// Executable scanning reports "L.rry.083", VERSION file reports "1.000.000, June 30, 1994"
@@ -3172,7 +3223,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "ba7ac86155e4c531e46cd73c86daa80a", 5884098},
{"resource.msg", 0, "a63974730d294dec0bea10057c36e506", 256014},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 3 - Italian DOS
// Supplied by ghoost in bug report #3053457
@@ -3181,7 +3232,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000},
{"resource.msg", 0, "5a0a896ff3e4a628db38a75eb6c84114", 259018},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.069 (just a guess)
@@ -3189,7 +3240,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "1ba7c7ae1efb315326d45cb931569b1b", 922},
{"resource.000", 0, "41ba03f0b188b029132daa3ece0d3e14", 623154},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Quest for Glory 4 1.1 Floppy - English DOS (supplied by markcool in bug report #2723852)
@@ -3198,7 +3249,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "685bdb1ed47bbbb0e5e25db392da83ce", 9301},
{"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11004993},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 4 1.1 Floppy - English DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 2.000.000
@@ -3206,7 +3257,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "d10a4cc177d2091d744e2ad8c049b0ae", 9295},
{"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11003589},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 4 1.1 Floppy - German DOS (supplied by markcool in bug report #2723850)
// Executable scanning reports "2.000.000", VERSION file reports "1.1"
@@ -3214,7 +3265,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301},
{"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Quest for Glory 4 CD - English DOS/Windows (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -3222,7 +3273,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246},
{"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// RAMA - English DOS/Windows Demo
// Executable scanning reports "2.100.002", VERSION file reports "000.000.008"
@@ -3230,7 +3281,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.001", 0, "775304e9b2a545156be4d94209550094", 1393},
{"ressci.001", 0, "259437fd75fdf51e8207fda8c01fa4fd", 2334384},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI3_GAMES
// RAMA - English Windows (from jvprat)
@@ -3243,7 +3294,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.003", 0, "31ef4c0621711585d031f0ae81707251", 1636},
{"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6860492},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// RAMA - English Windows (from Quietust, in bug report #2850645)
{"rama", "", {
@@ -3254,7 +3305,18 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.003", 0, "48841e4b84ef1b98b48d43566fda9e13", 1636},
{"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6870356},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // RAMA - German Windows CD (from farmboy0, in pull request 397)
+ {"rama", "", {
+ {"resmap.001", 0, "f68cd73308c46977a9632dfc618e1e38", 8338},
+ {"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70595521},
+ {"resmap.002", 0, "891fc2f5d9e23e7d9a9454acc7aaae52", 12082},
+ {"ressci.002", 0, "2a68edd064e5e4937b5e9c74b38f2082", 128508558},
+ {"resmap.003", 0, "222096000bd83a1d56577114a452cccf", 1636},
+ {"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6954219},
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// RAMA - Italian Windows CD (from glorifindel)
// SCI interpreter version 3.000.000 (a guess?)
@@ -3262,7 +3324,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70611091},
{"resmap.001", 0, "70ba2ff04a2b7fb2c52420ba7fbd47c2", 8338},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI3_GAMES
// Shivers - English Windows (from jvprat)
@@ -3271,14 +3333,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "f2ead37749ed8f6535a2445a7d05a0cc", 46525},
{"ressci.000", 0, "4294c6d7510935f2e0a52e302073c951", 262654836},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Shivers - German Windows (from Tobis87)
{"shivers", "", {
{"resmap.000", 0, "f483d0a1f78334c18052e92785c3086e", 46537},
{"ressci.000", 0, "6751b144671e2deed919eb9d284b07eb", 262390692},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Shivers - English Windows Demo
// Executable scanning reports "2.100.002"
@@ -3286,7 +3348,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "d9e0bc5eddefcbe47f528760085d8927", 1186},
{"ressci.000", 0, "3a93c6340b54e07e65d0e5583354d186", 10505469},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Shivers 2 doesn't contain SCI scripts. The whole game logic has
// been reimplemented from SCI in native code placed in DLL files.
@@ -3304,7 +3366,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "d8659188b84beaef076bd869837cd530", 634},
{"ressci.000", 0, "7fbac0807a044c9543e8ac376d200e59", 4925003},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Shivers 2 - English Windows (from abevi)
// VERSION.TXT Version 1.0 (3/25/97)
@@ -3312,7 +3374,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.001", 0, "a79d03d6eb75be0a79324f14e3d2ace4", 95346793},
{"resmap.001", 0, "a4804d436d90c4ec2e46b537f5e954db", 6268},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif
@@ -3325,7 +3387,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.msg", 0, "1aeafe2b495de288d002109650b66614", 1364},
{"resource.000", 0, "8e10d4f05c1fd9f883384fa38a898489", 377394},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Slater & Charlie Go Camping - English DOS/Windows
{"slater", "", {
@@ -3333,7 +3395,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044},
{"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Slater & Charlie Go Camping - English DOS/Windows (Sierra Originals)
@@ -3342,14 +3404,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044},
{"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Slater & Charlie Go Camping - English Macintosh
{"slater", "", {
{"Data1", 0, "7243b4390e5f0182d8133fbcae4b50c5", 2298853},
{"Data2", 0, "6b6f18f9b502dc0923eeae0ef47f02d5", 2276956},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NONE) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO1(GUIO_NONE) },
// Space Quest 1 VGA Remake - English Amiga (from www.back2roots.org)
// SCI interpreter version 1.000.510 (just a guess)
@@ -3362,7 +3424,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515},
{"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 1 VGA Remake - English DOS (from the Space Quest Collection)
// Executable scanning reports "T.A00.081", VERSION file reports "2.000"
@@ -3375,7 +3437,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262},
{"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 1 VGA Remake - English Mac (from Fingolfin)
{"sq1sci", "SCI", {
@@ -3386,7 +3448,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794},
{"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG)
// SCI interpreter version 1.000.181
@@ -3394,7 +3456,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "5af709ac5e0e923e0b8174f49978c30e", 636},
{"resource.001", 0, "fd99ea43f57576ded7c86036996346cf", 507642},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 1 VGA Remake - Spanish DOS Floppy (from jvprat)
// Executable scanning reports "T.A00.081", VERSION file reports "2.000"
@@ -3408,7 +3470,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325},
{"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest I 2.0 EGA DOS (6 x 3.5" disks)
// Provided by ssburnout in bug report #3046805
@@ -3421,7 +3483,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "975c6e81194ae6b65e960a248129ecaa", 684119},
{"resource.005", 0, "13d96f7905637552c0647175ff816145", 695589},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - English Amiga (from www.back2roots.org)
// SCI interpreter version 0.000.453 (just a guess)
@@ -3432,7 +3494,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496},
{"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - German Amiga (also includes english language)
// Executable scanning reports "1.004.006"
@@ -3453,7 +3515,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612},
{"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - English DOS (provided by richiefs in bug report #2670691)
// SCI interpreter version 0.000.453
@@ -3463,7 +3525,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244},
{"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - English DOS (from the Space Quest Collection)
// Executable scanning reports "0.000.685", VERSION file reports "1.018"
@@ -3473,7 +3535,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 715777},
{"resource.003", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 703370},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - English DOS (from abevi, bug report #2612718)
{"sq3", "", {
@@ -3485,7 +3547,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 328278},
{"resource.006", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 356702},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - English Mac (from Fingolfin)
{"sq3", "", {
@@ -3494,7 +3556,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072},
{"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 - German DOS (from Tobis87, also includes english language)
// SCI interpreter version 0.000.453 (?)
@@ -3508,7 +3570,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643},
{"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 3 v1.052 - German DOS (supplied by markcoolio in bug report #2723860, also includes english language)
// Executable scanning reports "S.old.114"
@@ -3518,7 +3580,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "9107c2aa5398e28b5c5406df13491f85", 596768},
{"resource.003", 0, "9107c2aa5398e28b5c5406df13491f85", 693573},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English Amiga
// Executable scanning reports "1.004.024"
@@ -3533,7 +3595,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296},
{"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - German Amiga (from www.back2roots.org, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
@@ -3547,7 +3609,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745},
{"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English DOS - THIS VERSION IS PIRATED/CRACKED AND REPACKAGED =DO NOT RE-ADD=
// Executable scanning reports "1.000.753"
@@ -3556,7 +3618,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124},
{"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English DOS
// Executable scanning reports "1.000.753"
@@ -3565,7 +3627,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646},
{"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 1.052 - English DOS Floppy (supplied by markcoolio in bug report #2723865)
// Executable scanning reports "1.000.753"
@@ -3579,7 +3641,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631},
{"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 1.000 - French DOS Floppy (supplied by misterhands in bug report #3515247)
{"sq4", "", {
@@ -3592,7 +3654,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "b2cca3afcf2e013b8ce86b64155af766", 1254353},
{"resource.005", 0, "9e520577e035547c4b5149a6d12ef85b", 1098814},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 1.000 - English DOS Floppy (from abevi, bug report #2612718)
{"sq4", "", {
@@ -3604,7 +3666,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368},
{"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest IV DOS 1.060 EGA (6 x 3.5" disks)
// Supplied by ssburnout in bug report #3046781
@@ -3617,7 +3679,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9a673e33c3f6dd560b993ffed77eeb49", 534994},
{"resource.005", 0, "3c4841d0a3ebba4404af588c93620c22", 595465},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - German DOS (from Tobis87, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
@@ -3631,7 +3693,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765},
{"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Italian DOS Floppy (from glorifindel, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
@@ -3644,7 +3706,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000},
{"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language)
// SCI interpreter version 1.000.1068
@@ -3654,7 +3716,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
{"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language)
// SCI interpreter version 1.000.1068
@@ -3664,7 +3726,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
{"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English DOS CD (from the Space Quest Collection)
// Executable scanning reports "1.001.064", VERSION file reports "1.0"
@@ -3672,7 +3734,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054},
{"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English Windows CD (from the Space Quest Collection)
// Executable scanning reports "1.001.064", VERSION file reports "1.0"
@@ -3682,7 +3744,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054},
{"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_MIDIGM, GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_MIDIGM, GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // Space Quest 4 - English DOS CD patch 1.2 (unofficial - NRS) - THIS VERSION IS PIRATED/CRACKED AND REPACKAGED =DO NOT RE-ADD=
+ // In essence, this "patch" includes a mixture the CD and floppy versions (the whole game), without the speech file
+ {"sq4", "CD", {
+ {"resource.map", 0, "38287a646458a1dabded55d094407793", 7139},
+ {"resource.000", 0, "231fd8421e1f211e1bcf9d7b8b6408e7", 9525849},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_PIRATED, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Spanish DOS CD (from jvprat, is still text only, not talkie, also includes english language)
// Executable scanning reports "1.SQ4.057", VERSION file reports "1.000"
@@ -3696,7 +3766,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752},
{"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Spanish DOS Floppy (from jvprat, also includes english language)
// Executable scanning reports "1.SQ4.056", VERSION file reports "1.000"
@@ -3708,7 +3778,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801},
{"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 1.000 - German DOS Floppy (supplied by markcoolio in bug report #2723862, also includes english language)
// Executable scanning reports "1.SQ4.030"
@@ -3722,7 +3792,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368},
{"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English Macintosh
// Executable scanning reports "x.yyy.zzz"
@@ -3737,7 +3807,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "869d16cab6641c80b06f4dcee18f86bc", 1426228},
{"resource.006", 0, "91d23407bc0447a3722fbeb952d7edee", 1402451},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - Russian DOS
// Executable scanning reports "1.000.753", VERSION file reports "1.994"
@@ -3750,7 +3820,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "2763fe4f0cb74df716ec8b0c464b0988", 1217428},
{"resource.005", 0, "d608713197c5ba1cd8c6ed46299c3069", 1057924},
AD_LISTEND},
- Common::RU_RUS, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::RU_RUS, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 - English DOS (from the Space Quest Collection)
// Executable scanning reports "1.001.068", VERSION file reports "1.04"
@@ -3759,7 +3829,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "bb8ad78793c26bdb3f77498b1d6515a9", 125988},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 - English DOS - THIS IS THE UNOFFICIAL BETA VERSION, WHICH IS OBVIOUSLY PIRATED AND CONTAINS MANY BUGS
// refer to http://www.akril15.com/sr/sq5alt/sq5alt.html =DO NOT RE-ADD=
@@ -3768,7 +3838,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8bde0a9adb9a3e9aaa861826874c9834", 6473},
{"resource.000", 0, "f4a48705764544d7cc64a7bb22a610df", 6025184},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_PIRATED, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 v1.04 - German DOS (from Tobis87, updated information by markcool from bug reports #2723935 and #2724762)
// SCI interpreter version 1.001.068
@@ -3777,7 +3847,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "7c71cfc36153cfe07b450423a51f7e68", 146282},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 v1.04 - French DOS (from Hkz, Included in Space Quest Collector's Edition, with chapters I-V)
{"sq5", "", {
@@ -3785,7 +3855,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "877c42380320eb1db7dad83ccd261214", 140374},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 - Italian DOS Floppy (from glorifindel)
// SCI interpreter version 1.001.068 (just a guess)
@@ -3793,7 +3863,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "5040026519f37199f3616fb1d4704dff", 6047170},
{"resource.map", 0, "5b09168baa2f6e2e22787429b2d72f54", 6492},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 - Spanish DOS Floppy (from mirir, bug report #3090664)
{"sq5", "", {
@@ -3801,7 +3871,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "5714a899033bdebf2d61ad333c8c6637", 6492},
{"resource.msg", 0, "46deca7ef9cf057f7d442df98c1a2ae2", 134612},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 5 - Russian DOS
// Executable scanning reports "1.001.068", VERSION file reports "1.994"
@@ -3810,7 +3880,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "6f9ed21e1001526b4137f6703ed476af", 6103778},
{"resource.msg", 0, "0a8931990cd2eac1691602391c68ab85", 147580},
AD_LISTEND},
- Common::RU_RUS, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::RU_RUS, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Space Quest 6 - English DOS/Win3.11 CD (from the Space Quest Collection)
@@ -3819,7 +3889,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "6dddfa3a8f3a3a513ec9dfdfae955005", 10528},
{"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 6 - English DOS/Win3.11 CD ver 1.11 (from FRG)
// SCI interpreter version 2.100.002 (just a guess)
@@ -3827,7 +3897,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "e0615d6e4e10e37ae42e6a2a95aaf145", 10528},
{"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 6 - French DOS/Win3.11 CD (from French magazine Joystick - September 1997)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -3835,7 +3905,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "3c831625931d5079b73ae8c275f52c95", 10534},
{"resource.000", 0, "4195ca940f759424f62b90e262cc1737", 40932397},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 6 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723884)
// SCI interpreter version 2.100.002 (just a guess)
@@ -3843,7 +3913,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "664d797415484f85c90b1b45aedc7686", 10534},
{"resource.000", 0, "ba87ba91e5bdabb4169dd0df75777722", 40933685},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 6 - English DOS/Win3.11 Interactive Demo (from FRG)
// SCI interpreter version 2.100.002 (just a guess)
@@ -3851,7 +3921,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "368f07b07433db3f819fa3fa0e5efee5", 2572},
{"resource.000", 0, "ab12724e078dea34b624e0d2a38dcd7c", 2272050},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
// The Island of Dr. Brain - English DOS CD (from jvprat)
@@ -3860,7 +3930,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2388efef8430b041b0f3b00b9050e4a2", 3281},
{"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 2103560},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// The Island of Dr. Brain - English DOS (from Quietust)
// Executable scanning reports "1.001.053", VERSION file reports "1.1 2.3.93"
@@ -3868,7 +3938,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "3c07da06bdd1689f9d07af78fb94d0ec", 3101},
{"resource.000", 0, "ecc686e0034fb4d41de077ac7167b3cf", 1947866},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// The Island of Dr. Brain - English DOS Non-Interactive Demo
// SCI interpreter version 1.001.053 (just a guess)
@@ -3876,7 +3946,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a8e5ca8ed1996974afa59f4c45e06195", 986},
{"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 586560},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Torin's Passage - English Windows Interactive Demo
@@ -3885,7 +3955,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403},
{"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - English Windows CD
// SCI interpreter version 2.100.002
@@ -3893,7 +3963,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - Spanish Windows CD (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -3902,7 +3972,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
// TODO: depend on one of the patches?
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - French Windows CD
// SCI interpreter version 2.100.002
@@ -3910,7 +3980,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - German Windows CD
// SCI interpreter version 2.100.002
@@ -3918,7 +3988,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - Italian Windows CD (from glorifindel)
// SCI interpreter version 2.100.002
@@ -3926,7 +3996,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage - French Windows (from LePhilousophe)
// SCI interpreter version 2.100.002
@@ -3934,7 +4004,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "66ed46e3e56f487e688d52f05b33d0ba", 9787},
{"ressci.000", 0, "118f9bec04bfe17c4f87bbb5ddb43c18", 56126981},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
// SCI Fanmade Games
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 6005ac50be..c26c787fbd 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -467,9 +467,9 @@ bool GameFeatures::autoDetectSci21KernelType() {
// seen it happen in the RAMA demo, thus we can assume that the
// game is using a SCI2.1 table
- // HACK: The Inside the Chest Demo doesn't have sounds at all, but
- // it's using a SCI2 kernel
- if (g_sci->getGameId() == GID_CHEST) {
+ // HACK: The Inside the Chest Demo and King's Questions minigame
+ // don't have sounds at all, but they're using a SCI2 kernel
+ if (g_sci->getGameId() == GID_CHEST || g_sci->getGameId() == GID_KQUESTIONS) {
_sci21KernelType = SCI_VERSION_2;
return true;
}
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 8d55790ad2..12746e17d6 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -35,8 +35,6 @@ namespace Sci {
Kernel::Kernel(ResourceManager *resMan, SegManager *segMan)
: _resMan(resMan), _segMan(segMan), _invalid("<invalid>") {
- loadSelectorNames();
- mapSelectors(); // Map a few special selectors for later use
}
Kernel::~Kernel() {
@@ -53,6 +51,11 @@ Kernel::~Kernel() {
}
}
+void Kernel::init() {
+ loadSelectorNames();
+ mapSelectors(); // Map a few special selectors for later use
+}
+
uint Kernel::getSelectorNamesSize() const {
return _selectorNames.size();
}
@@ -104,6 +107,11 @@ int Kernel::findSelector(const char *selectorName) const {
return -1;
}
+// used by Script patcher to figure out, if it's okay to initialize signature/patch-table
+bool Kernel::selectorNamesAvailable() {
+ return !_selectorNames.empty();
+}
+
void Kernel::loadSelectorNames() {
Resource *r = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS), 0);
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 8a021073fc..69c3a6d0c9 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -145,6 +145,8 @@ public:
*/
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
+
+ void init();
uint getSelectorNamesSize() const;
const Common::String &getSelectorName(uint selector);
@@ -159,6 +161,8 @@ public:
* @return The appropriate selector ID, or -1 on error
*/
int findSelector(const char *selectorName) const;
+
+ bool selectorNamesAvailable();
// Script dissection/dumping functions
void dissectScript(int scriptNumber, Vocabulary *vocab);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index d7858180f1..39244bd760 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -421,7 +421,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL },
{ MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL },
- { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, kReadNumber_workarounds },
{ MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
#ifdef ENABLE_SCI32
{ "RemapColors", kRemapColors32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", NULL, NULL },
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index c6635f2f27..b940eca6f5 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -718,7 +718,7 @@ reg_t kSave(EngineState *s, int argc, reg_t *argv) {
reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
Common::String game_id;
- int16 virtualId = argv[1].toSint16();
+ int16 virtualId = argv[1].toSint16();
int16 savegameId = -1;
Common::String game_description;
Common::String version;
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/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 9b0cb38f51..3964ccc1f8 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -103,10 +103,10 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) {
if (frame) {
if (scaleBuffer) {
// TODO: Probably should do aspect ratio correction in e.g. GK1 Windows
- g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel);
+ g_sci->_gfxScreen->scale2x((const byte *)frame->getPixels(), scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel);
g_system->copyRectToScreen(scaleBuffer, pitch, x, y, width, height);
} else {
- g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, width, height);
+ g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, width, height);
}
if (videoDecoder->hasDirtyPalette()) {
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index c8076ec819..6955225fe5 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -465,7 +465,7 @@ void Script::syncStringHeap(Common::Serializer &s) {
break;
} while (1);
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1){
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1){
// Strings in SCI1.1 come after the object instances
byte *buf = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
@@ -600,7 +600,10 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint16LE(dataInc);
s.syncAsSint16LE(ticker);
s.syncAsSint16LE(signal, VER(17));
- s.syncAsByte(priority);
+ if (s.getVersion() >= 31) // FE sound/music.h -> priority
+ s.syncAsSint16LE(priority);
+ else
+ s.syncAsByte(priority);
s.syncAsSint16LE(loop, VER(17));
s.syncAsByte(volume);
s.syncAsByte(hold, VER(17));
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 1d899b0d37..f1f02f89f2 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,6 +37,7 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
+ * 31 - priority for sound effects/music is now a signed int16, instead of a byte
* 30 - synonyms
* 29 - system strings
* 28 - heap
@@ -55,7 +56,7 @@ struct EngineState;
*/
enum {
- CURRENT_SAVEGAME_VERSION = 30,
+ CURRENT_SAVEGAME_VERSION = 31,
MINIMUM_SAVEGAME_VERSION = 14
};
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 36d2841b07..6616a0ee13 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -136,7 +136,7 @@ void Script::load(int script_nr, ResourceManager *resMan) {
memcpy(_buf, script->data, script->size);
// Check scripts for matching signatures and patch those, if found
- matchSignatureAndPatch(_nr, _buf, script->size);
+ patcherProcessScript(_nr, _buf, script->size);
if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index 0b499203c2..6a27dc7f64 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -30,7 +30,7 @@ namespace Sci {
struct EngineState;
class ResourceManager;
-struct SciScriptSignature;
+struct SciScriptPatcherEntry;
enum ScriptObjectTypes {
SCI_OBJ_TERMINATOR,
@@ -98,9 +98,11 @@ public:
void freeScript();
void load(int script_nr, ResourceManager *resMan);
- void matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
- int32 findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize);
- void applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset);
+ void patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
+ void patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11);
+ void patcherEnablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription);
+ int32 patcherFindSignature(const SciScriptPatcherEntry *patchEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11);
+ void patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11);
virtual bool isValidOffset(uint16 offset) const;
virtual SegmentRef dereference(reg_t pointer);
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 20c5c52178..6293fb42ae 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -21,6 +21,7 @@
*/
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/script.h"
#include "sci/engine/state.h"
#include "sci/engine/features.h"
@@ -29,98 +30,257 @@
namespace Sci {
-#define PATCH_END 0xFFFF
-#define PATCH_COMMANDMASK 0xF000
-#define PATCH_VALUEMASK 0x0FFF
-#define PATCH_ADDTOOFFSET 0xE000
-#define PATCH_GETORIGINALBYTE 0xD000
-#define PATCH_ADJUSTWORD 0xC000
-#define PATCH_ADJUSTWORD_NEG 0xB000
-#define PATCH_MAGICDWORD(a, b, c, d) CONSTANT_LE_32(a | (b << 8) | (c << 16) | (d << 24))
+// IMPORTANT:
+// every patch entry needs the following:
+// - script number (pretty obvious)
+//
+// - apply count
+// specifies the number of times a patch is supposed to get applied.
+// Most of the time, it should be 1.
+//
+// - magicDWORD + magicOffset
+// please ALWAYS put 0 for those two. Both will get filled out at runtime by the patcher.
+//
+// - signature data (is used to identify certain script code, that needs patching)
+// every signature needs to contain SIG_MAGICDWORD once.
+// The following 4 bytes after SIG_MAGICDWORD - which don't have to be fixed, you may for example
+// use SIG_SELECTOR16, will get used to quickly search for a partly match before verifying that
+// the whole signature actually matches. If it's not included, the script patcher will error() out
+// right when loading up the game.
+// If selector-IDs are included, please use SIG_SELECTOR16 + SIG_SELECTOR8 [1]. Simply
+// specify the selector that way, so that the patcher will search for the specific
+// selector instead of looking for a hardcoded value. Selectors may not be the same
+// between game versions.
+// For UINT16s either use SIG_UINT16 or SIG_SELECTOR16.
+// Macintosh versions of SCI games are using BE ordering instead of LE since SCI1.1 for UINT16s in scripts
+// By using those 2 commands, it's possible to make patches work for PC and Mac versions of the same game.
+// You may also skip bytes by using the SIG_ADDTOOFFSET command
+// Every signature data needs to get terminated using SIGNATURE_END
+//
+// - patch data (is used for actually patching scripts)
+// When a match is found, the patch data will get applied.
+// Patch data is similar to signature data. Just use PATCH_SELECTOR16 + PATCH_SELECTOR8 [1]
+// for patching in selectors.
+// There are also patch specific commands.
+// Those are PATCH_GETORIGINALBYTE, which fetches a byte from the original script
+// and PATCH_GETORIGINALBYTEADJUST, which does the same but gets a second value
+// from the uint16 array and uses that value to adjust the original byte.
+// Every patch data needs to get terminated using PATCH_END
+//
+// - and please always add a comment about why the patch was done and what's causing issues.
+// If possible make sure, that the patch works on localized (or just different) game versions
+// as well in case those need patching too.
+//
+// [1] - selectors need to get specified in selectorTable[] and ScriptPatcherSelectors-enum
+// before they can get used using the SIG_SELECTORx and PATCH_SELECTORx commands.
+// You have to use the exact same order in both the table and the enum, otherwise
+// it won't work.
+
+#define SIG_END 0xFFFF
+#define SIG_MISMATCH 0xFFFE
+#define SIG_COMMANDMASK 0xF000
+#define SIG_VALUEMASK 0x0FFF
+#define SIG_BYTEMASK 0x00FF
+#define SIG_MAGICDWORD 0xF000
+#define SIG_ADDTOOFFSET 0xE000
+#define SIG_SELECTOR16 0x9000
+#define SIG_SELECTOR8 0x8000
+#define SIG_UINT16 0x1000
+#define SIG_BYTE 0x0000
+
+#define PATCH_END SIG_END
+#define PATCH_COMMANDMASK SIG_COMMANDMASK
+#define PATCH_VALUEMASK SIG_VALUEMASK
+#define PATCH_BYTEMASK SIG_BYTEMASK
+#define PATCH_ADDTOOFFSET SIG_ADDTOOFFSET
+#define PATCH_GETORIGINALBYTE 0xD000
+#define PATCH_GETORIGINALBYTEADJUST 0xC000
+#define PATCH_SELECTOR16 SIG_SELECTOR16
+#define PATCH_SELECTOR8 SIG_SELECTOR8
+#define PATCH_UINT16 SIG_UINT16
+#define PATCH_BYTE SIG_BYTE
+
+// defines maximum scratch area for getting original bytes from unpatched script data
#define PATCH_VALUELIMIT 4096
-struct SciScriptSignature {
+struct SciScriptPatcherEntry {
+ bool active;
uint16 scriptNr;
const char *description;
int16 applyCount;
uint32 magicDWord;
int magicOffset;
- const byte *data;
- const uint16 *patch;
+ const uint16 *signatureData;
+ const uint16 *patchData;
+};
+
+#define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, 0, 0, NULL, NULL }
+
+struct SciScriptPatcherSelector {
+ const char *name;
+ int16 id;
+};
+
+SciScriptPatcherSelector selectorTable[] = {
+ { "cycles", -1, }, // system selector
+ { "seconds", -1, }, // system selector
+ { "init", -1, }, // system selector
+ { "dispose", -1, }, // system selector
+ { "new", -1, }, // system selector
+ { "curEvent", -1, }, // system selector
+ { "disable", -1, }, // system selector
+ { "show", -1, }, // system selector
+ { "x", -1, }, // system selector
+ { "cel", -1, }, // system selector
+ { "setMotion", -1, }, // system selector
+ { "deskSarg", -1, }, // Gabriel Knight
+ { "localize", -1, }, // Freddy Pharkas
+ { "put", -1, }, // Police Quest 1 VGA
+ { "solvePuzzle", -1, }, // Quest For Glory 3
+ { "timesShownID", -1, }, // Space Quest 1 VGA
+ { "startText", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
+ { "startAudio", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
+ { "modNum", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
+ { NULL, -1 }
+};
+
+enum ScriptPatcherSelectors {
+ SELECTOR_cycles = 0,
+ SELECTOR_seconds,
+ SELECTOR_init,
+ SELECTOR_dispose,
+ SELECTOR_new,
+ SELECTOR_curEvent,
+ SELECTOR_disable,
+ SELECTOR_show,
+ SELECTOR_x,
+ SELECTOR_cel,
+ SELECTOR_setMotion,
+ SELECTOR_deskSarg,
+ SELECTOR_localize,
+ SELECTOR_put,
+ SELECTOR_solvePuzzle,
+ SELECTOR_timesShownID,
+ SELECTOR_startText,
+ SELECTOR_startAudio,
+ SELECTOR_modNum
};
-#define SCI_SIGNATUREENTRY_TERMINATOR { 0, NULL, 0, 0, 0, NULL, NULL }
+// ===========================================================================
+// Conquests of Camelot
+// At the bazaar in Jerusalem, it's possible to see a girl taking a shower.
+// If you get too close, you get warned by the father - if you don't get away,
+// he will kill you.
+// Instead of walking there manually, it's also possible to enter "look window"
+// and ego will automatically walk to the window. It seems that this is something
+// that wasn't properly implemented, because instead of getting killed, you will
+// get an "Oops" message in Sierra SCI.
+//
+// This is caused by peepingTom in script 169 not getting properly initialized.
+// peepingTom calls the object behind global b9h. This global variable is
+// properly initialized, when walking there manually (method fawaz::doit).
+// When you instead walk there automatically (method fawaz::handleEvent), that
+// global isn't initialized, which then results in the Oops-message in Sierra SCI
+// and an error message in ScummVM/SCI.
+//
+// We fix the script by patching in a jump to the proper code inside fawaz::doit.
+// Responsible method: fawaz::handleEvent
+// Fixes bug: #6402
+const uint16 camelotSignaturePeepingTom[] = {
+ 0x72, SIG_MAGICDWORD, SIG_UINT16 + 0x7e, 0x07, // lofsa fawaz <-- start of proper initializion code
+ 0xa1, 0xb9, // sag b9h
+ SIG_ADDTOOFFSET +571, // skip 571 bytes
+ 0x39, 0x7a, // pushi 7a <-- initialization code when walking automatically
+ 0x78, // push1
+ 0x7a, // push2
+ 0x38, SIG_UINT16 + 0xa9, 0x00, // pushi 00a9 - script 169
+ 0x78, // push1
+ 0x43, 0x02, 0x04, // call kScriptID
+ 0x36, // push
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x06, // send 06
+ 0x32, SIG_UINT16 + 0x20, 0x05, // jmp [end of fawaz::handleEvent]
+ SIG_END
+};
+
+const uint16 camelotPatchPeepingTom[] = {
+ PATCH_ADDTOOFFSET +576,
+ 0x32, PATCH_UINT16 + 0xbd, 0xfd, // jmp to fawaz::doit / properly init peepingTom code
+ PATCH_END
+};
-// signatures are built like this:
-// - first a counter of the bytes that follow
-// - then the actual bytes that need to get matched
-// - then another counter of bytes (0 for EOS)
-// - if not EOS, an adjust offset and the actual bytes
-// - rinse and repeat
+// script, description, signature patch
+SciScriptPatcherEntry camelotSignatures[] = {
+ { true, 62, "fix peepingTom Sierra bug", 1, 0, 0, camelotSignaturePeepingTom, camelotPatchPeepingTom },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
// ===========================================================================
// stayAndHelp::changeState (0) is called when ego swims to the left or right
// boundaries of room 660. Normally a textbox is supposed to get on screen
// but the call is wrong, so not only do we get an error message the script
// is also hanging because the cue won't get sent out
-// This also happens in sierra sci - refer to bug #3038387
-const byte ecoquest1SignatureStayAndHelp[] = {
- 40,
- 0x3f, 0x01, // link 01
- 0x87, 0x01, // lap param[1]
- 0x65, 0x14, // aTop state
- 0x36, // push
- 0x3c, // dup
- 0x35, 0x00, // ldi 00
- 0x1a, // eq?
- 0x31, 0x1c, // bnt [next state]
- 0x76, // push0
- 0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
- 0x38, 0x22, 0x01, // pushi 0122
- 0x78, // push1
- 0x76, // push0
- 0x81, 0x00, // lag global[0]
- 0x4a, 0x06, // send 06 - call ego::setMotion(0)
- 0x39, 0x6e, // pushi 6e (selector init)
- 0x39, 0x04, // pushi 04
- 0x76, // push0
- 0x76, // push0
- 0x39, 0x17, // pushi 17
- 0x7c, // pushSelf
- 0x51, 0x82, // class EcoNarrator
- 0x4a, 0x0c, // send 0c - call EcoNarrator::init(0, 0, 23, self) (BADLY BROKEN!)
- 0x33, // jmp [end]
- 0
+// This also happens in sierra sci
+// Applies to at least: PC-CD
+// Responsible method: stayAndHelp::changeState
+// Fixes bug: #5107
+const uint16 ecoquest1SignatureStayAndHelp[] = {
+ 0x3f, 0x01, // link 01
+ 0x87, 0x01, // lap param[1]
+ 0x65, 0x14, // aTop state
+ 0x36, // push
+ 0x3c, // dup
+ 0x35, 0x00, // ldi 00
+ 0x1a, // eq?
+ 0x31, 0x1c, // bnt [next state]
+ 0x76, // push0
+ 0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
+ SIG_MAGICDWORD,
+ 0x38, SIG_UINT16 + 0x22, 0x01, // pushi 0122
+ 0x78, // push1
+ 0x76, // push0
+ 0x81, 0x00, // lag global[0]
+ 0x4a, 0x06, // send 06 - call ego::setMotion(0)
+ 0x39, SIG_SELECTOR8 + SELECTOR_init, // pushi "init"
+ 0x39, 0x04, // pushi 04
+ 0x76, // push0
+ 0x76, // push0
+ 0x39, 0x17, // pushi 17
+ 0x7c, // pushSelf
+ 0x51, 0x82, // class EcoNarrator
+ 0x4a, 0x0c, // send 0c - call EcoNarrator::init(0, 0, 23, self) (BADLY BROKEN!)
+ 0x33, // jmp [end]
+ SIG_END
};
const uint16 ecoquest1PatchStayAndHelp[] = {
- 0x87, 0x01, // lap param[1]
- 0x65, 0x14, // aTop state
- 0x36, // push
- 0x2f, 0x22, // bt [next state] (this optimization saves 6 bytes)
- 0x39, 0x00, // pushi 0 (wasting 1 byte here)
- 0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
- 0x38, 0x22, 0x01, // pushi 0122
- 0x78, // push1
- 0x76, // push0
- 0x81, 0x00, // lag global[0]
- 0x4a, 0x06, // send 06 - call ego::setMotion(0)
- 0x39, 0x6e, // pushi 6e (selector init)
- 0x39, 0x06, // pushi 06
- 0x39, 0x02, // pushi 02 (additional 2 bytes)
- 0x76, // push0
- 0x76, // push0
- 0x39, 0x17, // pushi 17
- 0x7c, // pushSelf
- 0x38, 0x80, 0x02, // pushi 280 (additional 3 bytes)
- 0x51, 0x82, // class EcoNarrator
- 0x4a, 0x10, // send 10 - call EcoNarrator::init(2, 0, 0, 23, self, 640)
+ 0x87, 0x01, // lap param[1]
+ 0x65, 0x14, // aTop state
+ 0x36, // push
+ 0x2f, 0x22, // bt [next state] (this optimization saves 6 bytes)
+ 0x39, 0x00, // pushi 0 (wasting 1 byte here)
+ 0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
+ 0x38, PATCH_UINT16 + 0x22, 0x01, // pushi 0122
+ 0x78, // push1
+ 0x76, // push0
+ 0x81, 0x00, // lag global[0]
+ 0x4a, 0x06, // send 06 - call ego::setMotion(0)
+ 0x39, PATCH_SELECTOR8 + SELECTOR_init, // pushi "init"
+ 0x39, 0x06, // pushi 06
+ 0x39, 0x02, // pushi 02 (additional 2 bytes)
+ 0x76, // push0
+ 0x76, // push0
+ 0x39, 0x17, // pushi 17
+ 0x7c, // pushSelf
+ 0x38, PATCH_UINT16 + 0x80, 0x02, // pushi 280 (additional 3 bytes)
+ 0x51, 0x82, // class EcoNarrator
+ 0x4a, 0x10, // send 10 - call EcoNarrator::init(2, 0, 0, 23, self, 640)
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature ecoquest1Signatures[] = {
- { 660, "CD: bad messagebox and freeze", 1, PATCH_MAGICDWORD(0x38, 0x22, 0x01, 0x78), -17, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp },
+// script, description, signature patch
+SciScriptPatcherEntry ecoquest1Signatures[] = {
+ { true, 660, "CD: bad messagebox and freeze", 1, 0, 0, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -129,122 +289,124 @@ const SciScriptSignature ecoquest1Signatures[] = {
// ecorder. This is done by reusing temp-space, that was filled on state 1.
// this worked in sierra sci just by accident. In our sci, the temp space
// is resetted every time, which means the previous text isn't available
-// anymore. We have to patch the code because of that - bug #3035386
-const byte ecoquest2SignatureEcorder[] = {
- 35,
- 0x31, 0x22, // bnt [next state]
- 0x39, 0x0a, // pushi 0a
- 0x5b, 0x04, 0x1e, // lea temp[1e]
- 0x36, // push
- 0x39, 0x64, // pushi 64
- 0x39, 0x7d, // pushi 7d
- 0x39, 0x32, // pushi 32
- 0x39, 0x66, // pushi 66
- 0x39, 0x17, // pushi 17
- 0x39, 0x69, // pushi 69
- 0x38, 0x31, 0x26, // pushi 2631
- 0x39, 0x6a, // pushi 6a
- 0x39, 0x64, // pushi 64
- 0x43, 0x1b, 0x14, // call kDisplay
- 0x35, 0x0a, // ldi 0a
- 0x65, 0x20, // aTop ticks
- 0x33, // jmp [end]
- +1, 5, // [skip 1 byte]
- 0x3c, // dup
- 0x35, 0x03, // ldi 03
- 0x1a, // eq?
- 0x31, // bnt [end]
- 0
+// anymore. We have to patch the code because of that.
+// Fixes bug: #4993
+const uint16 ecoquest2SignatureEcorder[] = {
+ 0x31, 0x22, // bnt [next state]
+ 0x39, 0x0a, // pushi 0a
+ 0x5b, 0x04, 0x1e, // lea temp[1e]
+ 0x36, // push
+ SIG_MAGICDWORD,
+ 0x39, 0x64, // pushi 64
+ 0x39, 0x7d, // pushi 7d
+ 0x39, 0x32, // pushi 32
+ 0x39, 0x66, // pushi 66
+ 0x39, 0x17, // pushi 17
+ 0x39, 0x69, // pushi 69
+ 0x38, PATCH_UINT16 + 0x31, 0x26, // pushi 2631
+ 0x39, 0x6a, // pushi 6a
+ 0x39, 0x64, // pushi 64
+ 0x43, 0x1b, 0x14, // call kDisplay
+ 0x35, 0x0a, // ldi 0a
+ 0x65, 0x20, // aTop ticks
+ 0x33, // jmp [end]
+ SIG_ADDTOOFFSET +1, // [skip 1 byte]
+ 0x3c, // dup
+ 0x35, 0x03, // ldi 03
+ 0x1a, // eq?
+ 0x31, // bnt [end]
+ SIG_END
};
const uint16 ecoquest2PatchEcorder[] = {
- 0x2f, 0x02, // bt [to pushi 07]
- 0x3a, // toss
- 0x48, // ret
- 0x38, 0x07, 0x00, // pushi 07 (parameter count) (waste 1 byte)
- 0x39, 0x0b, // push (FillBoxAny)
- 0x39, 0x1d, // pushi 29d
- 0x39, 0x73, // pushi 115d
- 0x39, 0x5e, // pushi 94d
- 0x38, 0xd7, 0x00, // pushi 215d
- 0x78, // push1 (visual screen)
- 0x38, 0x17, 0x00, // pushi 17 (color) (waste 1 byte)
- 0x43, 0x6c, 0x0e, // call kGraph
- 0x38, 0x05, 0x00, // pushi 05 (parameter count) (waste 1 byte)
- 0x39, 0x0c, // pushi 12d (UpdateBox)
- 0x39, 0x1d, // pushi 29d
- 0x39, 0x73, // pushi 115d
- 0x39, 0x5e, // pushi 94d
- 0x38, 0xd7, 0x00, // pushi 215d
- 0x43, 0x6c, 0x0a, // call kGraph
+ 0x2f, 0x02, // bt [to pushi 07]
+ 0x3a, // toss
+ 0x48, // ret
+ 0x38, PATCH_UINT16 + 0x07, 0x00, // pushi 07 (parameter count) (waste 1 byte)
+ 0x39, 0x0b, // push (FillBoxAny)
+ 0x39, 0x1d, // pushi 29d
+ 0x39, 0x73, // pushi 115d
+ 0x39, 0x5e, // pushi 94d
+ 0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+ 0x78, // push1 (visual screen)
+ 0x38, PATCH_UINT16 + 0x17, 0x00, // pushi 17 (color) (waste 1 byte)
+ 0x43, 0x6c, 0x0e, // call kGraph
+ 0x38, PATCH_UINT16 + 0x05, 0x00, // pushi 05 (parameter count) (waste 1 byte)
+ 0x39, 0x0c, // pushi 12d (UpdateBox)
+ 0x39, 0x1d, // pushi 29d
+ 0x39, 0x73, // pushi 115d
+ 0x39, 0x5e, // pushi 94d
+ 0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+ 0x43, 0x6c, 0x0a, // call kGraph
PATCH_END
};
// ===========================================================================
-// Same patch as above for the ecorder introduction. Fixes bug #3092115.
+// Same patch as above for the ecorder introduction.
// Two workarounds are needed for this patch in workarounds.cpp (when calling
// kGraphFillBoxAny and kGraphUpdateBox), as there isn't enough space to patch
// the function otherwise.
-const byte ecoquest2SignatureEcorderTutorial[] = {
- 36,
- 0x30, 0x23, 0x00, // bnt [next state]
- 0x39, 0x0a, // pushi 0a
- 0x5b, 0x04, 0x1f, // lea temp[1f]
- 0x36, // push
- 0x39, 0x64, // pushi 64
- 0x39, 0x7d, // pushi 7d
- 0x39, 0x32, // pushi 32
- 0x39, 0x66, // pushi 66
- 0x39, 0x17, // pushi 17
- 0x39, 0x69, // pushi 69
- 0x38, 0x31, 0x26, // pushi 2631
- 0x39, 0x6a, // pushi 6a
- 0x39, 0x64, // pushi 64
- 0x43, 0x1b, 0x14, // call kDisplay
- 0x35, 0x1e, // ldi 1e
- 0x65, 0x20, // aTop ticks
- 0x32, // jmp [end]
+// Fixes bug: #6467
+const uint16 ecoquest2SignatureEcorderTutorial[] = {
+ 0x30, SIG_UINT16 + 0x23, 0x00, // bnt [next state]
+ 0x39, 0x0a, // pushi 0a
+ 0x5b, 0x04, 0x1f, // lea temp[1f]
+ 0x36, // push
+ SIG_MAGICDWORD,
+ 0x39, 0x64, // pushi 64
+ 0x39, 0x7d, // pushi 7d
+ 0x39, 0x32, // pushi 32
+ 0x39, 0x66, // pushi 66
+ 0x39, 0x17, // pushi 17
+ 0x39, 0x69, // pushi 69
+ 0x38, SIG_UINT16 + 0x31, 0x26, // pushi 2631
+ 0x39, 0x6a, // pushi 6a
+ 0x39, 0x64, // pushi 64
+ 0x43, 0x1b, 0x14, // call kDisplay
+ 0x35, 0x1e, // ldi 1e
+ 0x65, 0x20, // aTop ticks
+ 0x32, // jmp [end]
// 2 extra bytes, jmp offset
- 0
+ SIG_END
};
const uint16 ecoquest2PatchEcorderTutorial[] = {
- 0x31, 0x23, // bnt [next state] (save 1 byte)
+ 0x31, 0x23, // bnt [next state] (save 1 byte)
// The parameter count below should be 7, but we're out of bytes
// to patch! A workaround has been added because of this
- 0x78, // push1 (parameter count)
- //0x39, 0x07, // pushi 07 (parameter count)
- 0x39, 0x0b, // push (FillBoxAny)
- 0x39, 0x1d, // pushi 29d
- 0x39, 0x73, // pushi 115d
- 0x39, 0x5e, // pushi 94d
- 0x38, 0xd7, 0x00, // pushi 215d
- 0x78, // push1 (visual screen)
- 0x39, 0x17, // pushi 17 (color)
- 0x43, 0x6c, 0x0e, // call kGraph
+ 0x78, // push1 (parameter count)
+ //0x39, 0x07, // pushi 07 (parameter count)
+ 0x39, 0x0b, // push (FillBoxAny)
+ 0x39, 0x1d, // pushi 29d
+ 0x39, 0x73, // pushi 115d
+ 0x39, 0x5e, // pushi 94d
+ 0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+ 0x78, // push1 (visual screen)
+ 0x39, 0x17, // pushi 17 (color)
+ 0x43, 0x6c, 0x0e, // call kGraph
// The parameter count below should be 5, but we're out of bytes
// to patch! A workaround has been added because of this
- 0x78, // push1 (parameter count)
- //0x39, 0x05, // pushi 05 (parameter count)
- 0x39, 0x0c, // pushi 12d (UpdateBox)
- 0x39, 0x1d, // pushi 29d
- 0x39, 0x73, // pushi 115d
- 0x39, 0x5e, // pushi 94d
- 0x38, 0xd7, 0x00, // pushi 215d
- 0x43, 0x6c, 0x0a, // call kGraph
+ 0x78, // push1 (parameter count)
+ //0x39, 0x05, // pushi 05 (parameter count)
+ 0x39, 0x0c, // pushi 12d (UpdateBox)
+ 0x39, 0x1d, // pushi 29d
+ 0x39, 0x73, // pushi 115d
+ 0x39, 0x5e, // pushi 94d
+ 0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+ 0x43, 0x6c, 0x0a, // call kGraph
// We are out of bytes to patch at this point,
// so we skip 494 (0x1EE) bytes to reuse this code:
// ldi 1e
// aTop 20
// jmp 030e (jump to end)
- 0x32, 0xee, 0x01, // skip 494 (0x1EE) bytes
+ 0x32, PATCH_UINT16 + 0xee, 0x01, // skip 494 (0x1EE) bytes
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature ecoquest2Signatures[] = {
- { 50, "initial text not removed on ecorder", 1, PATCH_MAGICDWORD(0x39, 0x64, 0x39, 0x7d), -8, ecoquest2SignatureEcorder, ecoquest2PatchEcorder },
- { 333, "initial text not removed on ecorder tutorial",1, PATCH_MAGICDWORD(0x39, 0x64, 0x39, 0x7d), -9, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial },
+// script, description, signature patch
+SciScriptPatcherEntry ecoquest2Signatures[] = {
+ { true, 50, "initial text not removed on ecorder", 1, 0, 0, ecoquest2SignatureEcorder, ecoquest2PatchEcorder },
+ { true, 333, "initial text not removed on ecorder tutorial",1, 0, 0, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -253,27 +415,27 @@ const SciScriptSignature ecoquest2Signatures[] = {
// wrong address when an incorrect word is typed, therefore leading to an
// infinite loop. This script bug was not apparent in SSCI, probably because
// event handling was slightly different there, so it was never discovered.
-// Fixes bug #3038870.
-const byte fanmadeSignatureInfiniteLoop[] = {
- 13,
- 0x38, 0x4c, 0x00, // pushi 004c
- 0x39, 0x00, // pushi 00
- 0x87, 0x01, // lap 01
- 0x4b, 0x04, // send 04
- 0x18, // not
- 0x30, 0x2f, 0x00, // bnt 002f [06a5] --> jmp ffbc [0664] --> BUG! infinite loop
- 0
+// Fixes bug: #5120
+const uint16 fanmadeSignatureInfiniteLoop[] = {
+ 0x38, SIG_UINT16 + 0x4c, 0x00, // pushi 004c
+ 0x39, 0x00, // pushi 00
+ 0x87, 0x01, // lap 01
+ 0x4b, 0x04, // send 04
+ SIG_MAGICDWORD,
+ 0x18, // not
+ 0x30, SIG_UINT16 + 0x2f, 0x00, // bnt 002f [06a5] --> jmp ffbc [0664] --> BUG! infinite loop
+ SIG_END
};
const uint16 fanmadePatchInfiniteLoop[] = {
PATCH_ADDTOOFFSET | +10,
- 0x30, 0x32, 0x00, // bnt 0032 [06a8] --> pushi 004c
+ 0x30, SIG_UINT16 + 0x32, 0x00, // bnt 0032 [06a8] --> pushi 004c
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature fanmadeSignatures[] = {
- { 999, "infinite loop on typo", 1, PATCH_MAGICDWORD(0x18, 0x30, 0x2f, 0x00), -9, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop },
+// script, description, signature patch
+SciScriptPatcherEntry fanmadeSignatures[] = {
+ { true, 999, "infinite loop on typo", 1, 0, 0, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -285,21 +447,23 @@ const SciScriptSignature fanmadeSignatures[] = {
// was already playing in the sound driver. In our case we would also stop
// the sample from playing, so we patch it out
// The "score" code is already buggy and sets volume to 0 when playing
-const byte freddypharkasSignatureScoreDisposal[] = {
- 10,
- 0x67, 0x32, // pTos 32 (selector theAudCount)
- 0x78, // push1
- 0x39, 0x0d, // pushi 0d
- 0x43, 0x75, 0x02, // call kDoAudio
- 0x1c, // ne?
- 0x31, // bnt (-> to skip disposal)
- 0
+// Applies to at least: English PC-CD
+// Responsible method: unknown
+const uint16 freddypharkasSignatureScoreDisposal[] = {
+ 0x67, 0x32, // pTos 32 (selector theAudCount)
+ 0x78, // push1
+ SIG_MAGICDWORD,
+ 0x39, 0x0d, // pushi 0d
+ 0x43, 0x75, 0x02, // call kDoAudio
+ 0x1c, // ne?
+ 0x31, // bnt (-> to skip disposal)
+ SIG_END
};
const uint16 freddypharkasPatchScoreDisposal[] = {
- 0x34, 0x00, 0x00, // ldi 0000
- 0x34, 0x00, 0x00, // ldi 0000
- 0x34, 0x00, 0x00, // ldi 0000
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0000
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0000
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0000
PATCH_END
};
@@ -309,24 +473,26 @@ const uint16 freddypharkasPatchScoreDisposal[] = {
// in IconBar::disable doing endless loops even in sierra sci, because there
// is no enabled icon left. We remove disabling of icon 8 (which is help),
// this fixes the issue.
-const byte freddypharkasSignatureCanisterHang[] = {
- 12,
- 0x38, 0xf1, 0x00, // pushi f1 (selector disable)
- 0x7a, // push2
- 0x39, 0x07, // pushi 07
- 0x39, 0x08, // pushi 08
- 0x81, 0x45, // lag 45
- 0x4a, 0x08, // send 08 - call IconBar::disable(7, 8)
- 0
+// Applies to at least: English PC-CD
+// Responsible method: rm235::init and sEnterFrom500::changeState
+const uint16 freddypharkasSignatureCanisterHang[] = {
+ 0x38, SIG_SELECTOR16 + SELECTOR_disable, // pushi disable
+ 0x7a, // push2
+ SIG_MAGICDWORD,
+ 0x39, 0x07, // pushi 07
+ 0x39, 0x08, // pushi 08
+ 0x81, 0x45, // lag 45
+ 0x4a, 0x08, // send 08 - call IconBar::disable(7, 8)
+ SIG_END
};
const uint16 freddypharkasPatchCanisterHang[] = {
PATCH_ADDTOOFFSET | +3,
- 0x78, // push1
+ 0x78, // push1
PATCH_ADDTOOFFSET | +2,
- 0x33, 0x00, // ldi 00 (waste 2 bytes)
+ 0x33, 0x00, // ldi 00 (waste 2 bytes)
PATCH_ADDTOOFFSET | +3,
- 0x06, // send 06 - call IconBar::disable(7)
+ 0x06, // send 06 - call IconBar::disable(7)
PATCH_END
};
@@ -338,135 +504,132 @@ const uint16 freddypharkasPatchCanisterHang[] = {
// ego, sometimes clicks also won't get registered. Strangely it's not nearly
// as bad as in our sci, but these differences may be caused by timing.
// We just reuse the active event, thus removing the duplicate kGetEvent call.
-const byte freddypharkasSignatureLadderEvent[] = {
- 21,
- 0x39, 0x6d, // pushi 6d (selector new)
- 0x76, // push0
- 0x38, 0xf5, 0x00, // pushi f5 (selector curEvent)
- 0x76, // push0
- 0x81, 0x50, // lag global[50]
- 0x4a, 0x04, // send 04 - read User::curEvent
- 0x4a, 0x04, // send 04 - call curEvent::new
- 0xa5, 0x00, // sat temp[0]
- 0x38, 0x94, 0x00, // pushi 94 (selector localize)
- 0x76, // push0
- 0x4a, 0x04, // send 04 - call curEvent::localize
- 0
+// Applies to at least: English PC-CD, German Floppy, English Mac
+// Responsible method: lowerLadder::doit and highLadder::doit
+const uint16 freddypharkasSignatureLadderEvent[] = {
+ 0x39, SIG_MAGICDWORD,
+ SIG_SELECTOR8 + SELECTOR_new, // pushi new
+ 0x76, // push0
+ 0x38, SIG_SELECTOR16 + SELECTOR_curEvent, // pushi curEvent
+ 0x76, // push0
+ 0x81, 0x50, // lag global[50]
+ 0x4a, 0x04, // send 04 - read User::curEvent
+ 0x4a, 0x04, // send 04 - call curEvent::new
+ 0xa5, 0x00, // sat temp[0]
+ 0x38, SIG_SELECTOR16 + SELECTOR_localize,
+ 0x76, // push0
+ 0x4a, 0x04, // send 04 - call curEvent::localize
+ SIG_END
};
const uint16 freddypharkasPatchLadderEvent[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (waste 3 bytes, overwrites first 2 pushes)
+ 0x34, 0x00, 0x00, // ldi 0000 (waste 3 bytes, overwrites first 2 pushes)
PATCH_ADDTOOFFSET | +8,
- 0xa5, 0x00, // sat temp[0] (waste 2 bytes, overwrites 2nd send)
+ 0xa5, 0x00, // sat temp[0] (waste 2 bytes, overwrites 2nd send)
PATCH_ADDTOOFFSET | +2,
- 0x34, 0x00, 0x00, // ldi 0000
- 0x34, 0x00, 0x00, // ldi 0000 (waste 6 bytes, overwrites last 3 opcodes)
+ 0x34, 0x00, 0x00, // ldi 0000
+ 0x34, 0x00, 0x00, // ldi 0000 (waste 6 bytes, overwrites last 3 opcodes)
PATCH_END
};
// In the Macintosh version of Freddy Pharkas, kRespondsTo is broken for
// property selectors. They hacked the script to work around the issue,
// so we revert the script back to using the values of the DOS script.
-const byte freddypharkasSignatureMacInventory[] = {
- 10,
- 0x39, 0x23, // pushi 23
- 0x39, 0x74, // pushi 74
- 0x78, // push1
- 0x38, 0x01, 0x74, // pushi 0174
- 0x85, 0x15, // lat 15
- 0
+// Applies to at least: English Mac
+// Responsible method: unknown
+const uint16 freddypharkasSignatureMacInventory[] = {
+ SIG_MAGICDWORD,
+ 0x39, 0x23, // pushi 23
+ 0x39, 0x74, // pushi 74
+ 0x78, // push1
+ 0x38, SIG_UINT16 + 0x74, 0x01, // pushi 0174 (on mac it's actually 0x01, 0x74)
+ 0x85, 0x15, // lat 15
+ SIG_END
};
const uint16 freddypharkasPatchMacInventory[] = {
- 0x39, 0x02, // pushi 02 (now matches the DOS version)
- 0x39, 0x74, // pushi 74
- 0x78, // push1
- 0x38, 0x01, 0x74, // pushi 0174
- 0x85, 0x15, // lat 15
- 0x4a, 0x06, // send 06
- 0x31, 0x08, // bnt 08
- 0x38, 0x01, 0x74, // pushi 0174
- 0x76, // push0
- 0x85, 0x15, // lat 15
- 0x4a, 0x04, // send 04
- 0x02, // add
- 0xa5, 0x12, // sat 12
- 0x39, 0x04, // pushi 04 (now matches the DOS version)
+ 0x39, 0x02, // pushi 02 (now matches the DOS version)
+ PATCH_ADDTOOFFSET +23,
+ 0x39, 0x04, // pushi 04 (now matches the DOS version)
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature freddypharkasSignatures[] = {
- { 0, "CD: score early disposal", 1, PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75), -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
- { 15, "Mac: broken inventory", 1, PATCH_MAGICDWORD(0x39, 0x23, 0x39, 0x74), 0, freddypharkasSignatureMacInventory, freddypharkasPatchMacInventory },
- { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
- { 320, "ladder event issue", 2, PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent },
+// script, description, signature patch
+SciScriptPatcherEntry freddypharkasSignatures[] = {
+ { true, 0, "CD: score early disposal", 1, 0, 0, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
+ { true, 15, "Mac: broken inventory", 1, 0, 0, freddypharkasSignatureMacInventory, freddypharkasPatchMacInventory },
+ { true, 235, "CD: canister pickup hang", 3, 0, 0, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
+ { true, 320, "ladder event issue", 2, 0, 0, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent },
SCI_SIGNATUREENTRY_TERMINATOR
};
// ===========================================================================
// daySixBeignet::changeState (4) is called when the cop goes out and sets cycles to 220.
// this is not enough time to get to the door, so we patch that to 23 seconds
-const byte gk1SignatureDay6PoliceBeignet[] = {
- 4,
- 0x35, 0x04, // ldi 04
- 0x1a, // eq?
- 0x30, // bnt [next state check]
- +2, 5, // [skip 2 bytes, offset of bnt]
- 0x38, 0x93, 0x00, // pushi 93 (selector dispose)
- 0x76, // push0
- 0x72, // lofsa deskSarg
- +2, 9, // [skip 2 bytes, offset of lofsa]
- 0x4a, 0x04, 0x00, // send 04
- 0x34, 0xdc, 0x00, // ldi 220
- 0x65, 0x1a, // aTop cycles
- 0x32, // jmp [end]
- 0
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: daySixBeignet::changeState
+const uint16 gk1SignatureDay6PoliceBeignet[] = {
+ 0x35, 0x04, // ldi 04
+ 0x1a, // eq?
+ 0x30, SIG_ADDTOOFFSET +2, // bnt [next state check]
+ 0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
+ 0x76, // push0
+ 0x72, SIG_ADDTOOFFSET +2, // lofsa deskSarg
+ 0x4a, SIG_UINT16 + 0x04, 0x00, // send 04
+ SIG_MAGICDWORD,
+ 0x34, SIG_UINT16 + 0xdc, 0x00, // ldi 220
+ 0x65, SIG_ADDTOOFFSET +1, // aTop cycles (1a for PC, 1c for Mac)
+ 0x32, // jmp [end]
+ SIG_END
};
const uint16 gk1PatchDay6PoliceBeignet[] = {
- PATCH_ADDTOOFFSET | +16,
- 0x34, 0x17, 0x00, // ldi 23
- 0x65, 0x1c, // aTop seconds
+ PATCH_ADDTOOFFSET +16,
+ 0x34, PATCH_UINT16 + 0x17, 0x00, // ldi 23
+ 0x65, PATCH_GETORIGINALBYTEADJUST +20, +2, // aTop seconds (1c for PC, 1e for Mac)
PATCH_END
};
// sargSleeping::changeState (8) is called when the cop falls asleep and sets cycles to 220.
// this is not enough time to get to the door, so we patch it to 42 seconds
-const byte gk1SignatureDay6PoliceSleep[] = {
- 4,
- 0x35, 0x08, // ldi 08
- 0x1a, // eq?
- 0x31, // bnt [next state check]
- +1, 6, // [skip 1 byte, offset of bnt]
- 0x34, 0xdc, 0x00, // ldi 220
- 0x65, 0x1a, // aTop cycles
- 0x32, // jmp [end]
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: sargSleeping::changeState
+const uint16 gk1SignatureDay6PoliceSleep[] = {
+ 0x35, 0x08, // ldi 08
+ 0x1a, // eq?
+ 0x31, SIG_ADDTOOFFSET +1, // bnt [next state check]
+ SIG_MAGICDWORD,
+ 0x34, SIG_UINT16 + 0xdc, 0x00, // ldi 220
+ 0x65, SIG_ADDTOOFFSET +1, // aTop cycles (1a for PC, 1c for Mac)
+ 0x32, // jmp [end]
0
};
const uint16 gk1PatchDay6PoliceSleep[] = {
- PATCH_ADDTOOFFSET | +5,
- 0x34, 0x2a, 0x00, // ldi 42
- 0x65, 0x1c, // aTop seconds
+ PATCH_ADDTOOFFSET +5,
+ 0x34, SIG_UINT16 + 0x2a, 0x00, // ldi 42
+ 0x65, PATCH_GETORIGINALBYTEADJUST +9, +2, // aTop seconds (1c for PC, 1e for Mac)
PATCH_END
};
// startOfDay5::changeState (20h) - when gabriel goes to the phone the script will hang
-const byte gk1SignatureDay5PhoneFreeze[] = {
- 5,
- 0x35, 0x03, // ldi 03
- 0x65, 0x1a, // aTop cycles
- 0x32, // jmp [end]
- +2, 3, // [skip 2 bytes, offset of jmp]
- 0x3c, // dup
- 0x35, 0x21, // ldi 21
- 0
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: startOfDay5::changeState
+const uint16 gk1SignatureDay5PhoneFreeze[] = {
+ 0x4a,
+ SIG_MAGICDWORD, SIG_UINT16 + 0x0c, 0x00, // send 0c
+ 0x35, 0x03, // ldi 03
+ 0x65, SIG_ADDTOOFFSET +1, // aTop cycles
+ 0x32, SIG_ADDTOOFFSET +2, // jmp [end]
+ 0x3c, // dup
+ 0x35, 0x21, // ldi 21
+ SIG_END
};
const uint16 gk1PatchDay5PhoneFreeze[] = {
- 0x35, 0x06, // ldi 06
- 0x65, 0x20, // aTop ticks
+ PATCH_ADDTOOFFSET +3,
+ 0x35, 0x06, // ldi 01
+ 0x65, PATCH_GETORIGINALBYTEADJUST +6, +6, // aTop ticks
PATCH_END
};
@@ -478,63 +641,66 @@ const uint16 gk1PatchDay5PhoneFreeze[] = {
// comparison between a number an an object. In the CD version, the checks are
// in the correct order, thus the comparison is correct, thus we use the code
// from the CD version in the floppy one.
-const byte gk1SignatureInterrogationBug[] = {
- 43,
- 0x65, 0x4c, // aTop 4c
- 0x67, 0x50, // pTos 50
- 0x34, 0x10, 0x27, // ldi 2710
- 0x1e, // gt?
- 0x31, 0x08, // bnt 08 [05a0]
- 0x67, 0x50, // pTos 50
- 0x34, 0x10, 0x27, // ldi 2710
- 0x04, // sub
- 0x65, 0x50, // aTop 50
- 0x63, 0x50, // pToa 50
- 0x31, 0x15, // bnt 15 [05b9]
- 0x39, 0x0e, // pushi 0e
- 0x76, // push0
- 0x4a, 0x04, 0x00, // send 0004
- 0xa5, 0x00, // sat 00
- 0x38, 0x93, 0x00, // pushi 0093
- 0x76, // push0
- 0x63, 0x50, // pToa 50
- 0x4a, 0x04, 0x00, // send 0004
- 0x85, 0x00, // lat 00
- 0x65, 0x50, // aTop 50
- 0
+// Applies to at least: English Floppy
+// Responsible method: Interrogation::dispose
+// TODO: Check, if English Mac is affected too and if this patch applies
+const uint16 gk1SignatureInterrogationBug[] = {
+ SIG_MAGICDWORD,
+ 0x65, 0x4c, // aTop 4c
+ 0x67, 0x50, // pTos 50
+ 0x34, SIG_UINT16 + 0x10, 0x27, // ldi 2710
+ 0x1e, // gt?
+ 0x31, 0x08, // bnt 08 [05a0]
+ 0x67, 0x50, // pTos 50
+ 0x34, SIG_UINT16 + 0x10, 0x27, // ldi 2710
+ 0x04, // sub
+ 0x65, 0x50, // aTop 50
+ 0x63, 0x50, // pToa 50
+ 0x31, 0x15, // bnt 15 [05b9]
+ 0x39, 0x0e, // pushi 0e
+ 0x76, // push0
+ 0x4a, SIG_UINT16 + 0x04, 0x00, // send 0004
+ 0xa5, 0x00, // sat 00
+ 0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
+ 0x76, // push0
+ 0x63, 0x50, // pToa 50
+ 0x4a, SIG_UINT16 + 0x04, 0x00, // send 0004
+ 0x85, 0x00, // lat 00
+ 0x65, 0x50, // aTop 50
+ SIG_END
};
const uint16 gk1PatchInterrogationBug[] = {
- 0x65, 0x4c, // aTop 4c
- 0x63, 0x50, // pToa 50
- 0x31, 0x15, // bnt 15 [05b9]
- 0x39, 0x0e, // pushi 0e
- 0x76, // push0
- 0x4a, 0x04, 0x00, // send 0004
- 0xa5, 0x00, // sat 00
- 0x38, 0x93, 0x00, // pushi 0093
- 0x76, // push0
- 0x63, 0x50, // pToa 50
- 0x4a, 0x04, 0x00, // send 0004
- 0x85, 0x00, // lat 00
- 0x65, 0x50, // aTop 50
- 0x67, 0x50, // pTos 50
- 0x34, 0x10, 0x27, // ldi 2710
- 0x1e, // gt?
- 0x31, 0x08, // bnt 08 [05b9]
- 0x67, 0x50, // pTos 50
- 0x34, 0x10, 0x27, // ldi 2710
- 0x04, // sub
- 0x65, 0x50, // aTop 50
+ 0x65, 0x4c, // aTop 4c
+ 0x63, 0x50, // pToa 50
+ 0x31, 0x15, // bnt 15 [05b9]
+ 0x39, 0x0e, // pushi 0e
+ 0x76, // push0
+ 0x4a, 0x04, 0x00, // send 0004
+ 0xa5, 0x00, // sat 00
+ 0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
+ 0x76, // push0
+ 0x63, 0x50, // pToa 50
+ 0x4a, 0x04, 0x00, // send 0004
+ 0x85, 0x00, // lat 00
+ 0x65, 0x50, // aTop 50
+ 0x67, 0x50, // pTos 50
+ 0x34, PATCH_UINT16 + 0x10, 0x27, // ldi 2710
+ 0x1e, // gt?
+ 0x31, 0x08, // bnt 08 [05b9]
+ 0x67, 0x50, // pTos 50
+ 0x34, PATCH_UINT16 + 0x10, 0x27, // ldi 2710
+ 0x04, // sub
+ 0x65, 0x50, // aTop 50
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature gk1Signatures[] = {
- { 51, "interrogation bug", 1, PATCH_MAGICDWORD(0x65, 0x4c, 0x67, 0x50), 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug },
- { 212, "day 5 phone freeze", 1, PATCH_MAGICDWORD(0x35, 0x03, 0x65, 0x1a), 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
- { 230, "day 6 police beignet timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
- { 230, "day 6 police sleep timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
+// script, description, signature patch
+SciScriptPatcherEntry gk1Signatures[] = {
+ { true, 51, "interrogation bug", 1, 0, 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug },
+ { true, 212, "day 5 phone freeze", 1, 0, 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
+ { true, 230, "day 6 police beignet timer issue", 1, 0, 0, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
+ { true, 230, "day 6 police sleep timer issue", 1, 0, 0, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -544,47 +710,47 @@ const SciScriptSignature gk1Signatures[] = {
// is later used to set master volume. This issue makes sierra sci set
// the volume to max. We fix the export, so volume won't get modified in
// those cases.
-const byte kq5SignatureCdHarpyVolume[] = {
- 34,
- 0x80, 0x91, 0x01, // lag global[191h]
- 0x18, // not
- 0x30, 0x2c, 0x00, // bnt [jump further] (jumping, if global 191h is 1)
- 0x35, 0x01, // ldi 01
- 0xa0, 0x91, 0x01, // sag global[191h] (setting global 191h to 1)
- 0x38, 0x7b, 0x01, // pushi 017b
- 0x76, // push0
- 0x81, 0x01, // lag global[1]
- 0x4a, 0x04, // send 04 - read KQ5::masterVolume
- 0xa5, 0x03, // sat temp[3] (store volume in temp 3)
- 0x38, 0x7b, 0x01, // pushi 017b
- 0x76, // push0
- 0x81, 0x01, // lag global[1]
- 0x4a, 0x04, // send 04 - read KQ5::masterVolume
- 0x36, // push
- 0x35, 0x04, // ldi 04
- 0x20, // ge? (followed by bnt)
- 0
+const uint16 kq5SignatureCdHarpyVolume[] = {
+ SIG_MAGICDWORD,
+ 0x80, SIG_UINT16 + 0x91, 0x01, // lag global[191h]
+ 0x18, // not
+ 0x30, SIG_UINT16 + 0x2c, 0x00, // bnt [jump further] (jumping, if global 191h is 1)
+ 0x35, 0x01, // ldi 01
+ 0xa0, SIG_UINT16 + 0x91, 0x01, // sag global[191h] (setting global 191h to 1)
+ 0x38, SIG_UINT16 + 0x7b, 0x01, // pushi 017b
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1]
+ 0x4a, 0x04, // send 04 - read KQ5::masterVolume
+ 0xa5, 0x03, // sat temp[3] (store volume in temp 3)
+ 0x38, SIG_UINT16 + 0x7b, 0x01, // pushi 017b
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1]
+ 0x4a, 0x04, // send 04 - read KQ5::masterVolume
+ 0x36, // push
+ 0x35, 0x04, // ldi 04
+ 0x20, // ge? (followed by bnt)
+ SIG_END
};
const uint16 kq5PatchCdHarpyVolume[] = {
- 0x38, 0x2f, 0x02, // pushi 022f (selector theVol) (3 new bytes)
- 0x76, // push0 (1 new byte)
- 0x51, 0x88, // class SpeakTimer (2 new bytes)
- 0x4a, 0x04, // send 04 (2 new bytes) -> read SpeakTimer::theVol
- 0xa5, 0x03, // sat temp[3] (2 new bytes) -> write to temp 3
- 0x80, 0x91, 0x01, // lag global[191h]
+ 0x38, PATCH_UINT16 + 0x2f, 0x02, // pushi 022f (selector theVol) (3 new bytes)
+ 0x76, // push0 (1 new byte)
+ 0x51, 0x88, // class SpeakTimer (2 new bytes)
+ 0x4a, 0x04, // send 04 (2 new bytes) -> read SpeakTimer::theVol
+ 0xa5, 0x03, // sat temp[3] (2 new bytes) -> write to temp 3
+ 0x80, PATCH_UINT16 + 0x91, 0x01, // lag global[191h]
// saving 1 byte due optimization
- 0x2e, 0x23, 0x00, // bt [jump further] (jumping, if global 191h is 1)
- 0x35, 0x01, // ldi 01
- 0xa0, 0x91, 0x01, // sag global[191h] (setting global 191h to 1)
- 0x38, 0x7b, 0x01, // pushi 017b
- 0x76, // push0
- 0x81, 0x01, // lag global[1]
- 0x4a, 0x04, // send 04 - read KQ5::masterVolume
- 0xa5, 0x03, // sat temp[3] (store volume in temp 3)
+ 0x2e, PATCH_UINT16 + 0x23, 0x00, // bt [jump further] (jumping, if global 191h is 1)
+ 0x35, 0x01, // ldi 01
+ 0xa0, PATCH_UINT16 + 0x91, 0x01, // sag global[191h] (setting global 191h to 1)
+ 0x38, PATCH_UINT16 + 0x7b, 0x01, // pushi 017b
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1]
+ 0x4a, 0x04, // send 04 - read KQ5::masterVolume
+ 0xa5, 0x03, // sat temp[3] (store volume in temp 3)
// saving 8 bytes due removing of duplicate code
- 0x39, 0x04, // pushi 04 (saving 1 byte due swapping)
- 0x22, // lt? (because we switched values)
+ 0x39, 0x04, // pushi 04 (saving 1 byte due swapping)
+ 0x22, // lt? (because we switched values)
PATCH_END
};
@@ -596,30 +762,32 @@ const uint16 kq5PatchCdHarpyVolume[] = {
// Additionally its top,left,bottom,right properties are set to 0 rather
// than the right values. We fix the object by setting the right values.
// If they are all zero, this causes an impossible position check in
-// witch::cantBeHere and an infinite loop when entering room 22 (bug #3034714).
+// witch::cantBeHere and an infinite loop when entering room 22.
//
// This bug is accidentally not triggered in SSCI because the invalid number
// of variables effectively hides witchCage::doit, causing this position check
// to be bypassed entirely.
// See also the warning+comment in Object::initBaseObject
-const byte kq5SignatureWitchCageInit[] = {
- 16,
- 0x00, 0x00, // top
- 0x00, 0x00, // left
- 0x00, 0x00, // bottom
- 0x00, 0x00, // right
- 0x00, 0x00, // extra property #1
- 0x7a, 0x00, // extra property #2
- 0xc8, 0x00, // extra property #3
- 0xa3, 0x00, // extra property #4
- 0
+//
+// Fixes bug: #4964
+const uint16 kq5SignatureWitchCageInit[] = {
+ SIG_UINT16 + 0x00, 0x00, // top
+ SIG_UINT16 + 0x00, 0x00, // left
+ SIG_UINT16 + 0x00, 0x00, // bottom
+ SIG_UINT16 + 0x00, 0x00, // right
+ SIG_UINT16 + 0x00, 0x00, // extra property #1
+ SIG_MAGICDWORD,
+ SIG_UINT16 + 0x7a, 0x00, // extra property #2
+ SIG_UINT16 + 0xc8, 0x00, // extra property #3
+ SIG_UINT16 + 0xa3, 0x00, // extra property #4
+ SIG_END
};
const uint16 kq5PatchWitchCageInit[] = {
- 0x00, 0x00, // top
- 0x7a, 0x00, // left
- 0xc8, 0x00, // bottom
- 0xa3, 0x00, // right
+ PATCH_UINT16 + 0x00, 0x00, // top
+ PATCH_UINT16 + 0x7a, 0x00, // left
+ PATCH_UINT16 + 0xc8, 0x00, // bottom
+ PATCH_UINT16 + 0xa3, 0x00, // right
PATCH_END
};
@@ -637,31 +805,25 @@ const uint16 kq5PatchWitchCageInit[] = {
// changes to GameFeatures::detectsetCursorType() ) and breaking savegame
// compatibilty between the DOS and Windows CD versions of KQ5.
// TODO: Investigate these side effects more closely.
-const byte kq5SignatureWinGMSignals[] = {
- 9,
- 0x80, 0x90, 0x01, // lag 0x190
- 0x18, // not
- 0x30, 0x1b, 0x00, // bnt +0x001B
- 0x89, 0x57, // lsg 0x57
- 0
+const uint16 kq5SignatureWinGMSignals[] = {
+ SIG_MAGICDWORD,
+ 0x80, SIG_UINT16 + 0x90, 0x01, // lag 0x190
+ 0x18, // not
+ 0x30, SIG_UINT16 + 0x1b, 0x00, // bnt +0x001B
+ 0x89, 0x57, // lsg 0x57
+ SIG_END
};
const uint16 kq5PatchWinGMSignals[] = {
- 0x34, 0x01, 0x00, // ldi 0x0001
+ 0x34, PATCH_UINT16 + 0x01, 0x00, // ldi 0x0001
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature kq5Signatures[] = {
- { 0, "CD: harpy volume change", 1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18), 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
- { 200, "CD: witch cage init", 1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00), -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
- SCI_SIGNATUREENTRY_TERMINATOR
-};
-
-const SciScriptSignature kq5WinGMSignatures[] = {
- { 0, "CD: harpy volume change", 1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18), 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
- { 200, "CD: witch cage init", 1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00), -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
- { 124, "Win: GM Music signal checks", 4, PATCH_MAGICDWORD(0x80, 0x90, 0x01, 0x18), 0, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
+// script, description, signature patch
+SciScriptPatcherEntry kq5Signatures[] = {
+ { true, 0, "CD: harpy volume change", 1, 0, 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+ { true, 200, "CD: witch cage init", 1, 0, 0, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+ { false, 124, "Win: GM Music signal checks", 4, 0, 0, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -673,25 +835,203 @@ const SciScriptSignature kq5WinGMSignatures[] = {
// sound is played twice, squelching all other sounds. We just rip the
// unnecessary cryMusic::check method out, thereby stopping the sound from
// constantly restarting (since it's being looped anyway), thus the normal
-// game speech can work while the baby cry sound is heard. Fixes bug #3034579.
-const byte kq6SignatureDuplicateBabyCry[] = {
- 10,
- 0x83, 0x00, // lal 00
- 0x31, 0x1e, // bnt 1e [07f4]
- 0x78, // push1
- 0x39, 0x04, // pushi 04
- 0x43, 0x75, 0x02, // callk DoAudio[75] 02
- 0
+// game speech can work while the baby cry sound is heard.
+// Fixes bug: #4955
+const uint16 kq6SignatureDuplicateBabyCry[] = {
+ SIG_MAGICDWORD,
+ 0x83, 0x00, // lal 00
+ 0x31, 0x1e, // bnt 1e [07f4]
+ 0x78, // push1
+ 0x39, 0x04, // pushi 04
+ 0x43, 0x75, 0x02, // callk DoAudio[75] 02
+ SIG_END
};
const uint16 kq6PatchDuplicateBabyCry[] = {
- 0x48, // ret
+ 0x48, // ret
+ PATCH_END
+};
+
+// The inventory of King's Quest 6 is buggy. When it grows too large,
+// it will get split into 2 pages. Switching between those pages will
+// grow the stack, because it's calling itself per switch.
+// Which means after a while ScummVM will bomb out because the stack frame
+// will be too large. This patch fixes the buggy script.
+// Applies to at least: PC-CD, English PC floppy, German PC floppy, English Mac
+// Responsible method: KqInv::showSelf
+// Fixes bug: #5681
+const uint16 kq6SignatureInventoryStackFix[] = {
+ 0x67, 0x30, // pTos state
+ 0x34, SIG_UINT16 + 0x00, 0x20, // ldi 2000
+ 0x12, // and
+ 0x18, // not
+ 0x31, 0x04, // bnt [not first refresh]
+ 0x35, 0x00, // ldi 00
+ SIG_MAGICDWORD,
+ 0x65, 0x1e, // aTop curIcon
+ 0x67, 0x30, // pTos state
+ 0x34, SIG_UINT16 + 0xff, 0xdf, // ldi dfff
+ 0x12, // and
+ 0x65, 0x30, // aTop state
+ 0x38, SIG_SELECTOR16 + SELECTOR_show, // pushi "show" ("show" is e1h for KQ6CD)
+ 0x78, // push1
+ 0x87, 0x00, // lap param[0]
+ 0x31, 0x04, // bnt [use global for show]
+ 0x87, 0x01, // lap param[1]
+ 0x33, 0x02, // jmp [use param for show]
+ 0x81, 0x00, // lag global[0]
+ 0x36, // push
+ 0x54, 0x06, // self 06 (KqInv::show)
+ 0x31, SIG_ADDTOOFFSET + 1, // bnt [exit menu code] (0x08 for PC, 0x07 for mac)
+ 0x39, 0x39, // pushi 39
+ 0x76, // push0
+ 0x54, 0x04, // self 04 (KqInv::doit)
+ SIG_END // followed by jmp (0x32 for PC, 0x33 for mac)
+};
+
+const uint16 kq6PatchInventoryStackFix[] = {
+ 0x67, 0x30, // pTos state
+ 0x3c, // dup (1 more byte, needed for patch)
+ 0x3c, // dup (1 more byte, saves 1 byte later)
+ 0x34, PATCH_UINT16 + 0x00, 0x20, // ldi 2000
+ 0x12, // and
+ 0x2f, 0x02, // bt [not first refresh] - saves 3 bytes in total
+ 0x65, 0x1e, // aTop curIcon
+ 0x00, // neg (either 2000 or 0000 in acc, this will create dfff or ffff) - saves 2 bytes
+ 0x12, // and
+ 0x65, 0x30, // aTop state
+ 0x38, // pushi "show"
+ PATCH_GETORIGINALBYTE +22,
+ PATCH_GETORIGINALBYTE +23,
+ 0x78, // push1
+ 0x87, 0x00, // lap param[0]
+ 0x31, 0x04, // bnt [call show using global 0]
+ 0x8f, 0x01, // lsp param[1], save 1 byte total with lsg global[0] combined
+ 0x33, 0x02, // jmp [call show using param 1]
+ 0x89, 0x00, // lsg global[0], save 1 byte total, see above
+ 0x54, 0x06, // self 06 (call x::show)
+ 0x31, // bnt [menu exit code]
+ PATCH_GETORIGINALBYTEADJUST +39, +6,// dynamic offset must be 0x0E for PC and 0x0D for mac
+ 0x34, PATCH_UINT16 + 0x00, 0x20, // ldi 2000
+ 0x12, // and
+ 0x2f, 0x05, // bt [to return]
+ 0x39, 0x39, // pushi 39
+ 0x76, // push0
+ 0x54, 0x04, // self 04 (self::doit)
+ 0x48, // ret (saves 2 bytes for PC, 1 byte for mac)
+ PATCH_END
+};
+
+// Audio + subtitles support - SHARED! - used for King's Quest 6 and Laura Bow 2
+// this patch gets enabled, when the user selects "both" in the ScummVM "Speech + Subtitles" menu
+// We currently use global 98d to hold a kMemory pointer.
+// Patched method: Messager::sayNext / lb2Messager::sayNext (always use text branch)
+const uint16 kq6laurabow2CDSignatureAudioTextSupport1[] = {
+ 0x89, 0x5a, // lsg global[5a]
+ 0x35, 0x02, // ldi 02
+ 0x12, // and
+ SIG_MAGICDWORD,
+ 0x31, 0x13, // bnt [audio call]
+ 0x38, SIG_SELECTOR16 + SELECTOR_modNum, // pushi modNum
+ SIG_END
+};
+
+const uint16 kq6laurabow2CDPatchAudioTextSupport1[] = {
+ PATCH_ADDTOOFFSET +5,
+ 0x33, 0x13, // jmp [audio call]
+ PATCH_END
+};
+
+// Patched method: Messager::sayNext / lb2Messager::sayNext (allocate audio memory)
+const uint16 kq6laurabow2CDSignatureAudioTextSupport2[] = {
+ 0x7a, // push2
+ 0x78, // push1
+ 0x39, 0x0c, // pushi 0c
+ 0x43, SIG_MAGICDWORD, 0x72, 0x04, // kMemory
+ 0xa5, 0xc9, // sat global[c9]
+ SIG_END
+};
+
+const uint16 kq6laurabow2CDPatchAudioTextSupport2[] = {
+ PATCH_ADDTOOFFSET +7,
+ 0xa1, 98, // sag global[98d]
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature kq6Signatures[] = {
- { 481, "duplicate baby cry", 1, PATCH_MAGICDWORD(0x83, 0x00, 0x31, 0x1e), 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
+// Patched method: Messager::sayNext / lb2Messager::sayNext (release audio memory)
+const uint16 kq6laurabow2CDSignatureAudioTextSupport3[] = {
+ 0x7a, // push2
+ 0x39, 0x03, // pushi 03
+ SIG_MAGICDWORD,
+ 0x8d, 0xc9, // lst temp[c9]
+ 0x43, 0x72, 0x04, // kMemory
+ SIG_END
+};
+
+const uint16 kq6laurabow2CDPatchAudioTextSupport3[] = {
+ PATCH_ADDTOOFFSET +3,
+ 0x89, 98, // lsg global[98d]
+ PATCH_END
+};
+
+// Patched method: Narrator::say (use audio memory)
+const uint16 kq6laurabow2CDSignatureAudioTextSupport4[] = {
+ 0x89, 0x5a, // lsg global[5a]
+ 0x35, 0x01, // ldi 01
+ 0x12, // and
+ 0x31, 0x08, // bnt [skip code]
+ 0x38, SIG_SELECTOR16 + SELECTOR_startText, // pushi startText
+ 0x78, // push1
+ 0x8f, 0x01, // lsp param[1]
+ 0x54, 0x06, // self 06
+ 0x89, 0x5a, // lsg global[5a]
+ 0x35, 0x02, // ldi 02
+ 0x12, // and
+ 0x31, 0x08, // bnt [skip code]
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16 + SELECTOR_startAudio, // pushi startAudio
+ 0x78, // push1
+ 0x8f, 0x01, // lsp param[1]
+ 0x54, 0x06, // self 06
+ SIG_END
+};
+
+const uint16 kq6laurabow2CDPatchAudioTextSupport4[] = {
+ PATCH_ADDTOOFFSET +5,
+ 0x18, // not (never jump here)
+ 0x18, // not (never jump here)
+ PATCH_ADDTOOFFSET +19,
+ 0x89, 98, // lsp global[98d]
+ PATCH_END
+};
+
+// Patched method: Talker::display/Narrator::say (remove reset saved mouse cursor code)
+// code would screw over mouse cursor
+const uint16 kq6laurabow2CDSignatureAudioTextSupport5[] = {
+ SIG_MAGICDWORD,
+ 0x35, 0x00, // ldi 00
+ 0x65, 0x82, // aTop saveCursor
+ SIG_END
+};
+
+const uint16 kq6laurabow2CDPatchAudioTextSupport5[] = {
+ 0x18, 0x18, 0x18, 0x18, // waste bytes, do nothing
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry kq6Signatures[] = {
+ { true, 481, "duplicate baby cry", 1, 0, 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
+ { true, 907, "inventory stack fix", 1, 0, 0, kq6SignatureInventoryStackFix, kq6PatchInventoryStackFix },
+ // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support
+ // *** King's Quest 6 audio + text support - CURRENTLY DISABLED ***
+ // TODO: fix window placement (currently part of the text windows go off-screen)
+ // TODO: fix hi-res portraits mode graphic glitches
+ { false, 924, "CD: audio + text support 1", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 },
+ { false, 924, "CD: audio + text support 2", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 },
+ { false, 924, "CD: audio + text support 3", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 },
+ { false, 928, "CD: audio + text support 4", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 },
+ { false, 928, "CD: audio + text support 5", 2, 0, 0, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -704,40 +1044,111 @@ const SciScriptSignature kq6Signatures[] = {
// the function is undefined, thus kStrCat() that is called inside the function
// reads a random pointer and crashes. We patch all of the 5 function calls
// (one for each letter typed from "R", "O", "B", "I", "N") so that they are
-// the same as the English version. Fixes bug #3048054.
-const byte longbowSignatureShowHandCode[] = {
- 3,
- 0x78, // push1
- 0x78, // push1
- 0x72, // lofsa
- +2, 2, // skip 2 bytes, offset of lofsa (the letter typed)
- 0x36, // push
- 0x40, // call
- +2, 3, // skip 2 bytes, offset of call
- 0x02, // perform the call above with 2 parameters
- 0x36, // push
- 0x40, // call
- +2, 8, // skip 2 bytes, offset of call
- 0x02, // perform the call above with 2 parameters
- 0x38, 0x1c, 0x01, // pushi 011c (setMotion)
- 0x39, 0x04, // pushi 04 (x)
- 0x51, 0x1e, // class MoveTo
- 0
+// the same as the English version.
+// Applies to at least: German floppy
+// Responsible method: unknown
+// Fixes bug: #5264
+const uint16 longbowSignatureShowHandCode[] = {
+ 0x78, // push1
+ 0x78, // push1
+ 0x72, SIG_ADDTOOFFSET +2, // lofsa (letter, that was typed)
+ 0x36, // push
+ 0x40, SIG_ADDTOOFFSET +2, // call
+ 0x02, // perform the call above with 2 parameters
+ 0x36, // push
+ 0x40, SIG_ADDTOOFFSET +2, // call
+ SIG_MAGICDWORD,
+ 0x02, // perform the call above with 2 parameters
+ 0x38, SIG_SELECTOR16 + SELECTOR_setMotion, // pushi "setMotion" (0x11c in Longbow German)
+ 0x39, SIG_SELECTOR8 + SELECTOR_x, // pushi "x" (0x04 in Longbow German)
+ 0x51, 0x1e, // class MoveTo
+ SIG_END
};
const uint16 longbowPatchShowHandCode[] = {
- 0x39, 0x01, // pushi 1 (combine the two push1's in one, like in the English version)
- PATCH_ADDTOOFFSET | +3, // leave the lofsa call untouched
+ 0x39, 0x01, // pushi 1 (combine the two push1's in one, like in the English version)
+ PATCH_ADDTOOFFSET +3, // leave the lofsa call untouched
// The following will remove the duplicate call
- 0x32, 0x02, 0x00, // jmp 02 - skip 2 bytes (the remainder of the first call)
- 0x48, // ret (dummy, should never be reached)
- 0x48, // ret (dummy, should never be reached)
+ 0x32, PATCH_UINT16 + 0x02, 0x00, // jmp 02 - skip 2 bytes (the remainder of the first call)
+ 0x48, // ret (dummy, should never be reached)
+ 0x48, // ret (dummy, should never be reached)
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature longbowSignatures[] = {
- { 210, "hand code crash", 5, PATCH_MAGICDWORD(0x02, 0x38, 0x1c, 0x01), -14, longbowSignatureShowHandCode, longbowPatchShowHandCode },
+// script, description, signature patch
+SciScriptPatcherEntry longbowSignatures[] = {
+ { true, 210, "hand code crash", 5, 0, 0, longbowSignatureShowHandCode, longbowPatchShowHandCode },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// Leisure Suit Larry 2
+// On the plane, Larry is able to wear the parachute. This grants 4 points.
+// In early versions of LSL2, it was possible to get "unlimited" points by
+// simply wearing it multiple times.
+// They fixed it in later versions by remembering, if the parachute was already
+// used before.
+// But instead of adding it properly, it seems they hacked the script / forgot
+// to replace script 0 as well, which holds information about how many global
+// variables are allocated at the start of the game.
+// The script tries to read an out-of-bounds global variable, which somewhat
+// "worked" in SSCI, but ScummVM/SCI doesn't allow that.
+// That's why those points weren't granted here at all.
+// We patch the script to use global 90, which seems to be unused in the whole game.
+// Applies to at least: English floppy
+// Responsible method: rm63Script::handleEvent
+// Fixes bug: #6346
+const uint16 larry2SignatureWearParachutePoints[] = {
+ 0x35, 0x01, // ldi 01
+ 0xa1, SIG_MAGICDWORD, 0x8e, // sag 8e
+ 0x80, SIG_UINT16 + 0xe0, 0x01, // lag 1e0
+ 0x18, // not
+ 0x30, SIG_UINT16 + 0x0f, 0x00, // bnt [don't give points]
+ 0x35, 0x01, // ldi 01
+ 0xa0, 0xe0, 0x01, // sag 1e0
+ SIG_END
+};
+
+const uint16 larry2PatchWearParachutePoints[] = {
+ PATCH_ADDTOOFFSET +4,
+ 0x80, PATCH_UINT16 + 0x5a, 0x00, // lag 5a (global 90)
+ PATCH_ADDTOOFFSET +6,
+ 0xa0, PATCH_UINT16 + 0x5a, 0x00, // sag 5a (global 90)
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry larry2Signatures[] = {
+ { true, 63, "plane: no points for wearing plane", 1, 0, 0, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// Leisure Suit Larry 5
+// In one of the conversations near the end (to be exact - room 380 and the text
+// about using champagne on Reverse Biaz - only used when you actually did that
+// in the game), the German text is too large, causing the textbox to get too large.
+// Because of that the talking head of Patti is drawn over the textbox. A translation oversight.
+// Applies to at least: German floppy
+// Responsible method: none, position of talker object on screen needs to get modified
+const uint16 larry5SignatureGermanEndingPattiTalker[] = {
+ SIG_MAGICDWORD,
+ SIG_UINT16 + 0x6e, 0x00, // object pattiTalker::x (110)
+ SIG_UINT16 + 0xb4, 0x00, // object pattiTalker::y (180)
+ SIG_ADDTOOFFSET + 469, // verify that it's really the German version
+ 0x59, 0x6f, 0x75, // (object name) "You"
+ 0x23, 0x47, 0x44, 0x75, // "#GDu"
+ SIG_END
+};
+
+const uint16 larry5PatchGermanEndingPattiTalker[] = {
+ PATCH_UINT16 + 0x5a, 0x00, // change pattiTalker::x to 90
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry larry5Signatures[] = {
+ { true, 380, "German-only: Enlarge Patti Textbox", 1, 0, 0, larry5SignatureGermanEndingPattiTalker, larry5PatchGermanEndingPattiTalker },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -749,77 +1160,177 @@ const SciScriptSignature longbowSignatures[] = {
// doesn't happen anymore. We would otherwise get a crash
// calling for invalid views (this happens of course also
// in sierra sci)
-const byte larry6SignatureDeathDialog[] = {
- 7,
- 0x3e, 0x33, 0x01, // link 0133 (offset 0x20)
- 0x35, 0xff, // ldi ff
- 0xa3, 0x00, // sal 00
- +255, 0,
- +255, 0,
- +170, 12, // [skip 680 bytes]
- 0x8f, 0x01, // lsp 01 (offset 0x2cf)
- 0x7a, // push2
- 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
- 0x36, // push
- 0x43, 0x7c, 0x0e, // kMessage[7c] 0e
- +90, 10, // [skip 90 bytes]
- 0x38, 0xd6, 0x00, // pushi 00d6 (offset 0x335)
- 0x78, // push1
- 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
- 0x36, // push
- +76, 11, // [skip 76 bytes]
- 0x38, 0xcd, 0x00, // pushi 00cd (offset 0x38b)
- 0x39, 0x03, // pushi 03
- 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
+// Applies to at least: German PC-CD
+// Responsible method: unknown
+const uint16 larry6SignatureDeathDialog[] = {
+ SIG_MAGICDWORD,
+ 0x3e, SIG_UINT16 + 0x33, 0x01, // link 0133 (offset 0x20)
+ 0x35, 0xff, // ldi ff
+ 0xa3, 0x00, // sal 00
+ SIG_ADDTOOFFSET +680, // [skip 680 bytes]
+ 0x8f, 0x01, // lsp 01 (offset 0x2cf)
+ 0x7a, // push2
+ 0x5a, SIG_UINT16 + 0x04, 0x00, SIG_UINT16 + 0x0e, 0x01, // lea 0004 010e
+ 0x36, // push
+ 0x43, 0x7c, 0x0e, // kMessage[7c] 0e
+ SIG_ADDTOOFFSET +90, // [skip 90 bytes]
+ 0x38, SIG_UINT16 + 0xd6, 0x00, // pushi 00d6 (offset 0x335)
+ 0x78, // push1
+ 0x5a, SIG_UINT16 + 0x04, 0x00, SIG_UINT16 + 0x0e, 0x01, // lea 0004 010e
+ 0x36, // push
+ SIG_ADDTOOFFSET +76, // [skip 76 bytes]
+ 0x38, SIG_UINT16 + 0xcd, 0x00, // pushi 00cd (offset 0x38b)
+ 0x39, 0x03, // pushi 03
+ 0x5a, SIG_UINT16 + 0x04, 0x00, SIG_UINT16 + 0x0e, 0x01, // lea 0004 010e
0x36,
- 0
+ SIG_END
};
const uint16 larry6PatchDeathDialog[] = {
- 0x3e, 0x00, 0x02, // link 0200
- PATCH_ADDTOOFFSET | +687,
- 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
- PATCH_ADDTOOFFSET | +98,
- 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
- PATCH_ADDTOOFFSET | +82,
- 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
+ 0x3e, 0x00, 0x02, // link 0200
+ PATCH_ADDTOOFFSET +687,
+ 0x5a, PATCH_UINT16 + 0x04, 0x00, PATCH_UINT16 + 0x40, 0x01, // lea 0004 0140
+ PATCH_ADDTOOFFSET +98,
+ 0x5a, PATCH_UINT16 + 0x04, 0x00, PATCH_UINT16 + 0x40, 0x01, // lea 0004 0140
+ PATCH_ADDTOOFFSET +82,
+ 0x5a, PATCH_UINT16 + 0x04, 0x00, PATCH_UINT16 + 0x40, 0x01, // lea 0004 0140
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature larry6Signatures[] = {
- { 82, "death dialog memory corruption", 1, PATCH_MAGICDWORD(0x3e, 0x33, 0x01, 0x35), 0, larry6SignatureDeathDialog, larry6PatchDeathDialog },
+// script, description, signature patch
+SciScriptPatcherEntry larry6Signatures[] = {
+ { true, 82, "death dialog memory corruption", 1, 0, 0, larry6SignatureDeathDialog, larry6PatchDeathDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
// ===========================================================================
-// rm560::doit was supposed to close the painting, when Heimlich enters the
-// room. The code is buggy, so it actually closes the painting, when heimlich
-// is not in the room. We fix that.
-const byte laurabow2SignaturePaintingClosing[] = {
- 17,
- 0x4a, 0x04, // send 04 - read aHeimlich::room
- 0x36, // push
- 0x81, 0x0b, // lag global[11d] -> current room
- 0x1c, // ne?
- 0x31, 0x0e, // bnt [don't close]
- 0x35, 0x00, // ldi 00
- 0xa3, 0x00, // sal local[0]
- 0x38, 0x92, 0x00, // pushi 0092
- 0x78, // push1
- 0x72, // lofsa sDumpSafe
- 0
+// Laura Bow 2
+//
+// Moving away the painting in the room with the hidden safe is problematic
+// for the CD version of the game. safePic::doVerb gets triggered by the mouse-click.
+// This method sets local 0 as signal, which is only meant to get handled, when
+// the player clicks again to move the painting back. This signal is processed by
+// the room doit-script.
+// That doit-script checks safePic::cel to be not equal 0 and would then skip over
+// the "close painting" trigger code. On very fast computers this script may
+// get called too early (which is the case when running under ScummVM and when
+// running the game using Sierra SCI in DOS-Box with cycles 15000) and thinks
+// that it's supposed to move the painting back. Which then results in the painting
+// getting moved to its original position immediately (which means it won't be possible
+// to access the safe behind it).
+//
+// We patch the script, so that we check for cel to be not equal 4 (the final cel) and
+// we also reset the safePic-signal immediately as well.
+//
+// In the floppy version Laura's coordinates are checked directly in rm560::doit
+// and as soon as she moves, the painting will automatically move to its original position.
+// This is not the case for the CD version of the game. The painting will only "move" back,
+// when the player actually exits the room and re-enters.
+//
+// Applies to at least: English PC-CD
+// Responsible method: rm560::doit
+// Fixes bug: #6460
+const uint16 laurabow2CDSignaturePaintingClosing[] = {
+ 0x39, 0x04, // pushi 04 (cel)
+ 0x76, // push0
+ SIG_MAGICDWORD,
+ 0x7a, // push2
+ 0x38, SIG_UINT16 + 0x31, 0x02, // pushi 0231h (561)
+ 0x76, // push0
+ 0x43, 0x02, 0x04, // kScriptID (get export 0 of script 561)
+ 0x4a, 0x04, // send 04 (gets safePicture::cel)
+ 0x18, // not
+ 0x31, 0x21, // bnt [exit]
+ 0x38, SIG_UINT16 + 0x83, 0x02, // pushi 0283h
+ 0x76, // push0
+ 0x7a, // push2
+ 0x39, 0x20, // pushi 20
+ 0x76, // push0
+ 0x43, 0x02, 0x04, // kScriptID (get export 0 of script 32)
+ 0x4a, 0x04, // send 04 (get sHeimlich::room)
+ 0x36, // push
+ 0x81, 0x0b, // lag global[b] (current room)
+ 0x1c, // ne?
+ 0x31, 0x0e, // bnt [exit]
+ 0x35, 0x00, // ldi 00
+ 0xa3, 0x00, // sal local[0] -> reset safePic signal
+ SIG_END
+};
+
+const uint16 laurabow2CDPatchPaintingClosing[] = {
+ PATCH_ADDTOOFFSET +2,
+ 0x3c, // dup (1 additional byte)
+ 0x76, // push0
+ 0x3c, // dup (1 additional byte)
+ 0xab, 0x00, // ssl local[0] -> reset safePic signal
+ 0x7a, // push2
+ 0x38, PATCH_UINT16 + 0x31, 0x02, // pushi 0231h (561)
+ 0x76, // push0
+ 0x43, 0x02, 0x04, // kScriptID (get export 0 of script 561)
+ 0x4a, 0x04, // send 04 (gets safePicture::cel)
+ 0x1a, // eq?
+ 0x31, 0x1d, // bnt [exit]
+ 0x38, PATCH_UINT16 + 0x83, 0x02, // pushi 0283h
+ 0x76, // push0
+ 0x7a, // push2
+ 0x39, 0x20, // pushi 20
+ 0x76, // push0
+ 0x43, 0x02, 0x04, // kScriptID (get export 0 of script 32)
+ 0x4a, 0x04, // send 04 (get sHeimlich::room)
+ 0x36, // push
+ 0x81, 0x0b, // lag global[b] (current room)
+ 0x1a, // eq? (2 opcodes changed, to save 2 bytes)
+ 0x2f, 0x0a, // bt [exit]
+ PATCH_END
};
-const uint16 laurabow2PatchPaintingClosing[] = {
- PATCH_ADDTOOFFSET | +6,
- 0x2f, 0x0e, // bt [don't close]
+// In the CD version the system menu is disabled for certain rooms. LB2::handsOff is called,
+// when leaving the room (and in other cases as well). This method remembers the disabled
+// icons of the icon bar. In the new room LB2::handsOn will get called, which then enables
+// all icons, but also disabled the ones, that were disabled before.
+//
+// Because of this behaviour certain rooms, that should have the system menu enabled, have
+// it disabled, when entering those rooms from rooms, where the menu is supposed to be
+// disabled.
+//
+// We patch this by injecting code into LB2::newRoom (which is called right after a room change)
+// and reset the global variable there, that normally holds the disabled buttons.
+//
+// This patch may cause side-effects and it's difficult to test, because it affects every room
+// in the game. At least for the intro, the speakeasy and plenty of rooms in the beginning it
+// seems to work correctly.
+//
+// Applies to at least: English PC-CD
+// Responsible method: LB2::newRoom, LB2::handsOff, LB2::handsOn
+// Fixes bug: #6440
+const uint16 laurabow2CDSignatureFixProblematicIconBar[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_UINT16 + 0xf1, 0x00, // pushi 00f1 (disable) - hardcoded, we only want to patch the CD version
+ 0x76, // push0
+ 0x81, 0x45, // lag global[45]
+ 0x4a, 0x04, // send 04
+ SIG_END
+};
+
+const uint16 laurabow2CDPatchFixProblematicIconBar[] = {
+ 0x35, 0x00, // ldi 00
+ 0xa1, 0x74, // sag 74h
+ 0x35, 0x00, // ldi 00 (waste bytes)
+ 0x35, 0x00, // ldi 00
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature laurabow2Signatures[] = {
- { 560, "painting closing immediately", 1, PATCH_MAGICDWORD(0x36, 0x81, 0x0b, 0x1c), -2, laurabow2SignaturePaintingClosing, laurabow2PatchPaintingClosing },
+
+// script, description, signature patch
+SciScriptPatcherEntry laurabow2Signatures[] = {
+ { true, 560, "CD: painting closing immediately", 1, 0, 0, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing },
+ { true, 0, "CD: fix problematic icon bar", 1, 0, 0, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar },
+ // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support
+ { false, 924, "CD: audio + text support 1", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 },
+ { false, 924, "CD: audio + text support 2", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 },
+ { false, 924, "CD: audio + text support 3", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 },
+ { false, 928, "CD: audio + text support 4", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 },
+ { false, 928, "CD: audio + text support 5", 2, 0, 0, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -828,29 +1339,27 @@ const SciScriptSignature laurabow2Signatures[] = {
// MG::replay somewhat calculates the savedgame-id used when saving again
// this doesn't work right and we remove the code completely.
// We set the savedgame-id directly right after restoring in kRestoreGame.
-const byte mothergoose256SignatureReplay[] = {
- 6,
- 0x36, // push
- 0x35, 0x20, // ldi 20
- 0x04, // sub
- 0xa1, 0xb3, // sag global[b3]
- 0
+const uint16 mothergoose256SignatureReplay[] = {
+ 0x36, // push
+ 0x35, SIG_MAGICDWORD, 0x20, // ldi 20
+ 0x04, // sub
+ 0xa1, 0xb3, // sag global[b3]
+ SIG_END
};
const uint16 mothergoose256PatchReplay[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0000 (dummy)
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0000 (dummy)
PATCH_END
};
// when saving, it also checks if the savegame ID is below 13.
// we change this to check if below 113 instead
-const byte mothergoose256SignatureSaveLimit[] = {
- 5,
- 0x89, 0xb3, // lsg global[b3]
- 0x35, 0x0d, // ldi 0d
- 0x20, // ge?
- 0
+const uint16 mothergoose256SignatureSaveLimit[] = {
+ 0x89, SIG_MAGICDWORD, 0xb3, // lsg global[b3]
+ 0x35, 0x0d, // ldi 0d
+ 0x20, // ge?
+ SIG_END
};
const uint16 mothergoose256PatchSaveLimit[] = {
@@ -859,11 +1368,74 @@ const uint16 mothergoose256PatchSaveLimit[] = {
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature mothergoose256Signatures[] = {
- { 0, "replay save issue", 1, PATCH_MAGICDWORD(0x20, 0x04, 0xa1, 0xb3), -2, mothergoose256SignatureReplay, mothergoose256PatchReplay },
- { 0, "save limit dialog (SCI1.1)", 1, PATCH_MAGICDWORD(0xb3, 0x35, 0x0d, 0x20), -1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
- { 994, "save limit dialog (SCI1)", 1, PATCH_MAGICDWORD(0xb3, 0x35, 0x0d, 0x20), -1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
+// script, description, signature patch
+SciScriptPatcherEntry mothergoose256Signatures[] = {
+ { true, 0, "replay save issue", 1, 0, 0, mothergoose256SignatureReplay, mothergoose256PatchReplay },
+ { true, 0, "save limit dialog (SCI1.1)", 1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
+ { true, 994, "save limit dialog (SCI1)", 1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// Police Quest 1 VGA
+// When at the police station, you can put or get your gun from your locker.
+// The script, that handles this, is buggy. It disposes the gun as soon as
+// you click, but then waits 2 seconds before it also closes the locker.
+// Problem is that it's possible to click again, which then results in a
+// disposed object getting accessed. This happened to work by pure luck in
+// SSCI.
+// This patch changes the code, so that the gun is actually given away
+// when the 2 seconds have passed and the locker got closed.
+// Applies to at least: English floppy
+// Responsible method: putGun::changeState (script 341)
+// Fixes bug: #5705 / #6400
+const uint16 pq1vgaSignaturePutGunInLockerBug[] = {
+ 0x35, 0x00, // ldi 00
+ 0x1a, // eq?
+ 0x31, 0x25, // bnt [next state check]
+ SIG_ADDTOOFFSET +22, // [skip 22 bytes]
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16 + SELECTOR_put, // pushi "put"
+ 0x78, // push1
+ 0x76, // push0
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x06, // send 06 - ego::put(0)
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1c, // aTop 1c (set timer to 2 seconds)
+ 0x33, 0x0e, // jmp [end of method]
+ 0x3c, // dup --- next state check target
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x31, 0x08, // bnt [end of method]
+ 0x39, SIG_SELECTOR8 + SELECTOR_dispose, // pushi "dispose"
+ 0x76, // push0
+ 0x72, SIG_UINT16 + 0x88, 0x00, // lofsa 0088
+ 0x4a, 0x04, // send 04 - locker::dispose
+ SIG_END
+};
+
+const uint16 pq1vgaPatchPutGunInLockerBug[] = {
+ PATCH_ADDTOOFFSET +3,
+ 0x31, 0x1c, // bnt [next state check]
+ PATCH_ADDTOOFFSET +22,
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1c, // aTop 1c (set timer to 2 seconds)
+ 0x33, 0x17, // jmp [end of method]
+ 0x3c, // dup --- next state check target
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x31, 0x11, // bnt [end of method]
+ 0x38, PATCH_SELECTOR16 + SELECTOR_put, // pushi "put"
+ 0x78, // push1
+ 0x76, // push0
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x06, // send 06 - ego::put(0)
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry pq1vgaSignatures[] = {
+ { true, 341, "put gun in locker bug", 1, 0, 0, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -876,43 +1448,45 @@ const SciScriptSignature mothergoose256Signatures[] = {
// not nearly as bad as in our sci, but these differences may be caused by
// timing.
// We just reuse the active event, thus removing the duplicate kGetEvent call.
-const byte qfg1vgaSignatureFightEvents[] = {
- 25,
- 0x39, 0x6d, // pushi 6d (selector new)
- 0x76, // push0
- 0x51, 0x07, // class Event
- 0x4a, 0x04, // send 04 - call Event::new
- 0xa5, 0x00, // sat temp[0]
- 0x78, // push1
- 0x76, // push0
- 0x4a, 0x04, // send 04 - read Event::x
- 0xa5, 0x03, // sat temp[3]
- 0x76, // push0 (selector y)
- 0x76, // push0
- 0x85, 0x00, // lat temp[0]
- 0x4a, 0x04, // send 04 - read Event::y
- 0x36, // push
- 0x35, 0x0a, // ldi 0a
- 0x04, // sub (poor mans localization) ;-)
- 0
+// Applies to at least: English floppy
+// Responsible method: pointBox::doit
+const uint16 qfg1vgaSignatureFightEvents[] = {
+ 0x39, SIG_MAGICDWORD,
+ SIG_SELECTOR8 + SELECTOR_new, // pushi "new"
+ 0x76, // push0
+ 0x51, 0x07, // class Event
+ 0x4a, 0x04, // send 04 - call Event::new
+ 0xa5, 0x00, // sat temp[0]
+ 0x78, // push1
+ 0x76, // push0
+ 0x4a, 0x04, // send 04 - read Event::x
+ 0xa5, 0x03, // sat temp[3]
+ 0x76, // push0 (selector y)
+ 0x76, // push0
+ 0x85, 0x00, // lat temp[0]
+ 0x4a, 0x04, // send 04 - read Event::y
+ 0x36, // push
+ 0x35, 0x0a, // ldi 0a
+ 0x04, // sub (poor mans localization) ;-)
+ SIG_END
};
const uint16 qfg1vgaPatchFightEvents[] = {
- 0x38, 0x5a, 0x01, // pushi 15a (selector curEvent)
- 0x76, // push0
- 0x81, 0x50, // lag global[50]
- 0x4a, 0x04, // send 04 - read User::curEvent -> needs one byte more than previous code
- 0xa5, 0x00, // sat temp[0]
- 0x78, // push1
- 0x76, // push0
- 0x4a, 0x04, // send 04 - read Event::x
- 0xa5, 0x03, // sat temp[3]
- 0x76, // push0 (selector y)
- 0x76, // push0
- 0x85, 0x00, // lat temp[0]
- 0x4a, 0x04, // send 04 - read Event::y
- 0x39, 0x00, // pushi 00
- 0x02, // add (waste 3 bytes) - we don't need localization, User::doit has already done it
+ 0x38, PATCH_SELECTOR16 + SELECTOR_curEvent, // pushi 15a (selector curEvent)
+ 0x76, // push0
+ 0x81, 0x50, // lag global[50]
+ 0x4a, 0x04, // send 04 - read User::curEvent -> needs one byte more than previous code
+ 0xa5, 0x00, // sat temp[0]
+ 0x78, // push1
+ 0x76, // push0
+ 0x4a, 0x04, // send 04 - read Event::x
+ 0xa5, 0x03, // sat temp[3]
+ 0x76, // push0 (selector y)
+ 0x76, // push0
+ 0x85, 0x00, // lat temp[0]
+ 0x4a, 0x04, // send 04 - read Event::y
+ 0x39, 0x00, // pushi 00
+ 0x02, // add (waste 3 bytes) - we don't need localization, User::doit has already done it
PATCH_END
};
@@ -923,66 +1497,150 @@ const uint16 qfg1vgaPatchFightEvents[] = {
// window text, which erases the window header text because of its length. To
// fix that, we allocate more temp space and move the pointer used for the
// window header a little bit, wherever it's used in script 814.
-// Fixes bug #3568431.
+// Fixes bug: #6139.
// Patch 1: Increase temp space
-const byte qfg1vgaSignatureTempSpace[] = {
- 4,
- 0x3f, 0xba, // link 0xba
- 0x87, 0x00, // lap 0
- 0
+const uint16 qfg1vgaSignatureTempSpace[] = {
+ SIG_MAGICDWORD,
+ 0x3f, 0xba, // link 0xba
+ 0x87, 0x00, // lap 0
+ SIG_END
};
const uint16 qfg1vgaPatchTempSpace[] = {
- 0x3f, 0xca, // link 0xca
+ 0x3f, 0xca, // link 0xca
PATCH_END
};
// Patch 2: Move the pointer used for the window header a little bit
-const byte qfg1vgaSignatureDialogHeader[] = {
- 4,
- 0x5b, 0x04, 0x80, // lea temp[0x80]
- 0x36, // push
- 0
+const uint16 qfg1vgaSignatureDialogHeader[] = {
+ SIG_MAGICDWORD,
+ 0x5b, 0x04, 0x80, // lea temp[0x80]
+ 0x36, // push
+ SIG_END
};
const uint16 qfg1vgaPatchDialogHeader[] = {
- 0x5b, 0x04, 0x90, // lea temp[0x90]
+ 0x5b, 0x04, 0x90, // lea temp[0x90]
PATCH_END
};
// When clicking on the crusher in room 331, Ego approaches him to talk to him,
// an action that is handled by moveToCrusher::changeState in script 331. The
-// scripts set Ego to move close to the crusher, but when Ego is running instead
+// scripts set Ego to move close to the crusher, but when Ego is sneaking instead
// of walking, the target coordinates specified by script 331 are never reached,
// as Ego is making larger steps, and never reaches the required spot. This is an
-// edge case that can occur when Ego is set to run. Normally, when clicking on
+// edge case that can occur when Ego is set to sneak. Normally, when clicking on
// the crusher, ego is supposed to move close to position 79, 165. We change it
// to 85, 165, which is not an edge case thus the freeze is avoided.
-// Fixes bug #3585189.
-const byte qfg1vgaSignatureMoveToCrusher[] = {
- 9,
- 0x51, 0x1f, // class Motion
- 0x36, // push
- 0x39, 0x4f, // pushi 4f (79 - x)
- 0x38, 0xa5, 0x00, // pushi 00a5 (165 - y)
- 0x7c, // pushSelf
- 0
+// Fixes bug: #6180
+const uint16 qfg1vgaSignatureMoveToCrusher[] = {
+ SIG_MAGICDWORD,
+ 0x51, 0x1f, // class Motion
+ 0x36, // push
+ 0x39, 0x4f, // pushi 4f (79 - x)
+ 0x38, SIG_UINT16 + 0xa5, 0x00, // pushi 00a5 (165 - y)
+ 0x7c, // pushSelf
+ SIG_END
};
const uint16 qfg1vgaPatchMoveToCrusher[] = {
- PATCH_ADDTOOFFSET | +3,
- 0x39, 0x55, // pushi 55 (85 - x)
+ PATCH_ADDTOOFFSET +3,
+ 0x39, 0x55, // pushi 55 (85 - x)
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature qfg1vgaSignatures[] = {
- { 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
- { 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
- { 814, "window text temp space", 1, PATCH_MAGICDWORD(0x3f, 0xba, 0x87, 0x00), 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace },
- { 814, "dialog header offset", 3, PATCH_MAGICDWORD(0x5b, 0x04, 0x80, 0x36), 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader },
- { 331, "moving to crusher", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher },
+// Same pathfinding bug as above, where Ego is set to move to an impossible
+// spot when sneaking. In GuardsTrumpet::changeState, we change the final
+// location where Ego is moved from 111, 111 to 114, 114.
+// Fixes bug: #6248
+const uint16 qfg1vgaSignatureMoveToCastleGate[] = {
+ SIG_MAGICDWORD,
+ 0x51, 0x1f, // class MoveTo
+ 0x36, // push
+ 0x39, 0x6f, // pushi 6f (111 - x)
+ 0x3c, // dup (111 - y)
+ 0x7c, // pushSelf
+ SIG_END
+};
+
+const uint16 qfg1vgaPatchMoveToCastleGate[] = {
+ PATCH_ADDTOOFFSET +3,
+ 0x39, 0x72, // pushi 72 (114 - x)
+ PATCH_END
+};
+
+// Typo in the original Sierra scripts
+// Looking at a cheetaur resulted in a text about a Saurus Rex
+// The code treats both monster types the same.
+// Applies to at least: English floppy
+// Responsible method: smallMonster::doVerb
+// Fixes bug #6249
+const uint16 qfg1vgaSignatureCheetaurDescription[] = {
+ SIG_MAGICDWORD,
+ 0x34, SIG_UINT16 + 0xb8, 0x01, // ldi 01b8
+ 0x1a, // eq?
+ 0x31, 0x16, // bnt 16
+ 0x38, SIG_UINT16 + 0x27, 0x01, // pushi 0127
+ 0x39, 0x06, // pushi 06
+ 0x39, 0x03, // pushi 03
+ 0x78, // push1
+ 0x39, 0x12, // pushi 12 -> monster type Saurus Rex
+ SIG_END
+};
+
+const uint16 qfg1vgaPatchCheetaurDescription[] = {
+ PATCH_ADDTOOFFSET +14,
+ 0x39, 0x11, // pushi 11 -> monster type cheetaur
+ PATCH_END
+};
+
+// In the "funny" room (Yorick's room) in QfG1 VGA, pulling the chain and
+// then pressing the button on the right side of the room results in
+// a broken game. This also happens in SSCI.
+// Problem is that the Sierra programmers forgot to disable the door, that
+// gets opened by pulling the chain. So when ego falls down and then
+// rolls through the door, one method thinks that the player walks through
+// it and acts that way and the other method is still doing the roll animation.
+// Local 5 of that room is a timer, that closes the door (object door11).
+// Setting it to 1 during happyFace::changeState(0) stops door11::doit from
+// calling goTo6::init, so the whole issue is stopped from happening.
+// Applies to at least: English floppy
+// Responsible method: happyFace::changeState, door11::doit
+// Fixes bug #6181
+const uint16 qfg1vgaSignatureFunnyRoomFix[] = {
+ 0x65, 0x14, // aTop 14 (state)
+ 0x36, // push
+ 0x3c, // dup
+ 0x35, 0x00, // ldi 00
+ 0x1a, // eq?
+ 0x30, SIG_UINT16 + 0x25, 0x00, // bnt 0025 [-> next state]
+ SIG_MAGICDWORD,
+ 0x35, 0x01, // ldi 01
+ 0xa3, 0x4e, // sal 4e
+ SIG_END
+};
+
+const uint16 qfg1vgaPatchFunnyRoomFix[] = {
+ PATCH_ADDTOOFFSET +3,
+ 0x2e, PATCH_UINT16 + 0x29, 0x00, // bt 0029 [-> next state] - saves 4 bytes
+ 0x35, 0x01, // ldi 01
+ 0xa3, 0x4e, // sal 4e
+ 0xa3, 0x05, // sal 05 (sets local 5 to 1)
+ 0xa3, 0x05, // and again to make absolutely sure (actually to waste 2 bytes)
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry qfg1vgaSignatures[] = {
+ { true, 215, "fight event issue", 1, 0, 0, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
+ { true, 216, "weapon master event issue", 1, 0, 0, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
+ { true, 814, "window text temp space", 1, 0, 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace },
+ { true, 814, "dialog header offset", 3, 0, 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader },
+ { true, 331, "moving to crusher", 1, 0, 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher },
+ { true, 41, "moving to castle gate", 1, 0, 0, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate },
+ { true, 210, "cheetaur description fixed", 1, 0, 0, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription },
+ { true, 96, "funny room script bug fixed", 1, 0, 0, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -998,58 +1656,56 @@ const SciScriptSignature qfg1vgaSignatures[] = {
// deleted entries. We don't allow the user to change the directory, thus the
// contents of the file list are constant, so we can avoid the constant file
// and text entry refreshes whenever a button is pressed, and prevent possible
-// crashes because of these constant quick object reallocations. Fixes bug
-// #3037996.
-const byte qfg2SignatureImportDialog[] = {
- 16,
- 0x63, 0x20, // pToa text
- 0x30, 0x0b, 0x00, // bnt [next state]
- 0x7a, // push2
- 0x39, 0x03, // pushi 03
- 0x36, // push
- 0x43, 0x72, 0x04, // callk Memory 4
- 0x35, 0x00, // ldi 00
- 0x65, 0x20, // aTop text
- 0
+// crashes because of these constant quick object reallocations.
+// Fixes bug: #5096
+const uint16 qfg2SignatureImportDialog[] = {
+ 0x63, SIG_MAGICDWORD, 0x20, // pToa text
+ 0x30, SIG_UINT16 + 0x0b, 0x00, // bnt [next state]
+ 0x7a, // push2
+ 0x39, 0x03, // pushi 03
+ 0x36, // push
+ 0x43, 0x72, 0x04, // callk Memory 4
+ 0x35, 0x00, // ldi 00
+ 0x65, 0x20, // aTop text
+ SIG_END
};
const uint16 qfg2PatchImportDialog[] = {
- PATCH_ADDTOOFFSET | +5,
- 0x48, // ret
+ PATCH_ADDTOOFFSET +5,
+ 0x48, // ret
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature qfg2Signatures[] = {
- { 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x20, 0x30, 0x0b, 0x00), -1, qfg2SignatureImportDialog, qfg2PatchImportDialog },
+// script, description, signature patch
+SciScriptPatcherEntry qfg2Signatures[] = {
+ { true, 944, "import dialog continuous calls", 1, 0, 0, qfg2SignatureImportDialog, qfg2PatchImportDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
// ===========================================================================
// Patch for the import screen in QFG3, same as the one for QFG2 above
-const byte qfg3SignatureImportDialog[] = {
- 15,
- 0x63, 0x2a, // pToa text
- 0x31, 0x0b, // bnt [next state]
- 0x7a, // push2
- 0x39, 0x03, // pushi 03
- 0x36, // push
- 0x43, 0x72, 0x04, // callk Memory 4
- 0x35, 0x00, // ldi 00
- 0x65, 0x2a, // aTop text
- 0
+const uint16 qfg3SignatureImportDialog[] = {
+ 0x63, SIG_MAGICDWORD, 0x2a, // pToa text
+ 0x31, 0x0b, // bnt [next state]
+ 0x7a, // push2
+ 0x39, 0x03, // pushi 03
+ 0x36, // push
+ 0x43, 0x72, 0x04, // callk Memory 4
+ 0x35, 0x00, // ldi 00
+ 0x65, 0x2a, // aTop text
+ SIG_END
};
const uint16 qfg3PatchImportDialog[] = {
- PATCH_ADDTOOFFSET | +4,
- 0x48, // ret
+ PATCH_ADDTOOFFSET +4,
+ 0x48, // ret
PATCH_END
};
// ===========================================================================
-// Patch for the Woo dialog option in Uhura's conversation. Bug #3040722
+// Patch for the Woo dialog option in Uhura's conversation.
// Problem: The Woo dialog option (0xffb5) is negative, and therefore
// treated as an option opening a submenu. This leads to uhuraTell::doChild
// being called, which calls hero::solvePuzzle and then proceeds with
@@ -1061,38 +1717,40 @@ const uint16 qfg3PatchImportDialog[] = {
// hero::solvePuzzle (0xfffc) which does a ret afterwards without going to
// Teller::doChild. We jump to this call of hero::solvePuzzle to get that same
// behaviour.
-
-const byte qfg3SignatureWooDialog[] = {
- 30,
- 0x67, 0x12, // pTos 12 (query)
- 0x35, 0xb6, // ldi b6
- 0x1a, // eq?
- 0x2f, 0x05, // bt 05
- 0x67, 0x12, // pTos 12 (query)
- 0x35, 0x9b, // ldi 9b
- 0x1a, // eq?
- 0x31, 0x0c, // bnt 0c
- 0x38, 0x97, 0x02, // pushi 0297
- 0x7a, // push2
- 0x38, 0x0c, 0x01, // pushi 010c
- 0x7a, // push2
- 0x81, 0x00, // lag 00
- 0x4a, 0x08, // send 08
- 0x67, 0x12, // pTos 12 (query)
- 0x35, 0xb5, // ldi b5
- 0
+// Applies to at least: English, German, Italian, French, Spanish Floppy
+// Responsible method: unknown
+// Fixes bug: #5172
+const uint16 qfg3SignatureWooDialog[] = {
+ SIG_MAGICDWORD,
+ 0x67, 0x12, // pTos 12 (query)
+ 0x35, 0xb6, // ldi b6
+ 0x1a, // eq?
+ 0x2f, 0x05, // bt 05
+ 0x67, 0x12, // pTos 12 (query)
+ 0x35, 0x9b, // ldi 9b
+ 0x1a, // eq?
+ 0x31, 0x0c, // bnt 0c
+ 0x38, SIG_SELECTOR16 + SELECTOR_solvePuzzle, // pushi 0297
+ 0x7a, // push2
+ 0x38, SIG_UINT16 + 0x0c, 0x01, // pushi 010c
+ 0x7a, // push2
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x08, // send 08
+ 0x67, 0x12, // pTos 12 (query)
+ 0x35, 0xb5, // ldi b5
+ SIG_END
};
const uint16 qfg3PatchWooDialog[] = {
- PATCH_ADDTOOFFSET | +0x29,
- 0x33, 0x11, // jmp to 0x6a2, the call to hero::solvePuzzle for 0xFFFC
+ PATCH_ADDTOOFFSET +0x29,
+ 0x33, 0x11, // jmp to 0x6a2, the call to hero::solvePuzzle for 0xFFFC
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature qfg3Signatures[] = {
- { 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a), -1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
- { 440, "dialog crash when asking about Woo", 1, PATCH_MAGICDWORD(0x67, 0x12, 0x35, 0xb5), -26, qfg3SignatureWooDialog, qfg3PatchWooDialog },
+// script, description, signature patch
+SciScriptPatcherEntry qfg3Signatures[] = {
+ { true, 944, "import dialog continuous calls", 1, 0, 0, qfg3SignatureImportDialog, qfg3PatchImportDialog },
+ { true, 440, "dialog crash when asking about Woo", 1, 0, 0, qfg3SignatureWooDialog, qfg3PatchWooDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -1102,31 +1760,21 @@ const SciScriptSignature qfg3Signatures[] = {
// adds it to nest::x. The problem is that the script also checks if x exceeds
// we never reach that of course, so the pterodactyl-flight will go endlessly
// we could either calculate property count differently somehow fixing this
-// but I think just patching it out is cleaner (bug #3037938)
-const byte sq4FloppySignatureEndlessFlight[] = {
- 8,
- 0x39, 0x04, // pushi 04 (selector x)
- 0x78, // push1
- 0x67, 0x08, // pTos 08 (property x)
- 0x63, 0x44, // pToa 44 (invalid property)
- 0x02, // add
- 0
-};
-
-// Similar to the above, for the German version (bug #3110215)
-const byte sq4FloppySignatureEndlessFlightGerman[] = {
- 8,
- 0x39, 0x04, // pushi 04 (selector x)
- 0x78, // push1
- 0x67, 0x08, // pTos 08 (property x)
- 0x63, 0x4c, // pToa 4c (invalid property)
- 0x02, // add
- 0
+// but I think just patching it out is cleaner.
+// Fixes bug: #5093
+const uint16 sq4FloppySignatureEndlessFlight[] = {
+ 0x39, 0x04, // pushi 04 (selector x)
+ SIG_MAGICDWORD,
+ 0x78, // push1
+ 0x67, 0x08, // pTos 08 (property x)
+ 0x63, SIG_ADDTOOFFSET + 1, // pToa (invalid property) - 44h for English floppy, 4ch for German floppy
+ 0x02, // add
+ SIG_END
};
const uint16 sq4FloppyPatchEndlessFlight[] = {
- PATCH_ADDTOOFFSET | +5,
- 0x35, 0x03, // ldi 03 (which would be the content of the property)
+ PATCH_ADDTOOFFSET +5,
+ 0x35, 0x03, // ldi 03 (which would be the content of the property)
PATCH_END
};
@@ -1136,40 +1784,40 @@ const uint16 sq4FloppyPatchEndlessFlight[] = {
// Patch 1: iconTextSwitch::show, called when the text options button is shown.
// This is patched to add the "Both" text resource (i.e. we end up with
// "Speech", "Text" and "Both")
-const byte sq4CdSignatureTextOptionsButton[] = {
- 11,
- 0x35, 0x01, // ldi 0x01
- 0xa1, 0x53, // sag 0x53
- 0x39, 0x03, // pushi 0x03
- 0x78, // push1
- 0x39, 0x09, // pushi 0x09
- 0x54, 0x06, // self 0x06
- 0
+const uint16 sq4CdSignatureTextOptionsButton[] = {
+ SIG_MAGICDWORD,
+ 0x35, 0x01, // ldi 0x01
+ 0xa1, 0x53, // sag 0x53
+ 0x39, 0x03, // pushi 0x03
+ 0x78, // push1
+ 0x39, 0x09, // pushi 0x09
+ 0x54, 0x06, // self 0x06
+ SIG_END
};
const uint16 sq4CdPatchTextOptionsButton[] = {
- PATCH_ADDTOOFFSET | +7,
- 0x39, 0x0b, // pushi 0x0b
+ PATCH_ADDTOOFFSET +7,
+ 0x39, 0x0b, // pushi 0x0b
PATCH_END
};
// Patch 2: Adjust a check in babbleIcon::init, which handles the babble icon
// (e.g. the two guys from Andromeda) shown when dying/quitting.
-// Fixes bug #3538418.
-const byte sq4CdSignatureBabbleIcon[] = {
- 7,
- 0x89, 0x5a, // lsg 5a
- 0x35, 0x02, // ldi 02
- 0x1a, // eq?
- 0x31, 0x26, // bnt 26 [02a7]
- 0
+// Fixes bug: #6068
+const uint16 sq4CdSignatureBabbleIcon[] = {
+ SIG_MAGICDWORD,
+ 0x89, 0x5a, // lsg 5a
+ 0x35, 0x02, // ldi 02
+ 0x1a, // eq?
+ 0x31, 0x26, // bnt 26 [02a7]
+ SIG_END
};
const uint16 sq4CdPatchBabbleIcon[] = {
- 0x89, 0x5a, // lsg 5a
- 0x35, 0x01, // ldi 01
- 0x1a, // eq?
- 0x2f, 0x26, // bt 26 [02a7]
+ 0x89, 0x5a, // lsg 5a
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x2f, 0x26, // bt 26 [02a7]
PATCH_END
};
@@ -1177,111 +1825,198 @@ const uint16 sq4CdPatchBabbleIcon[] = {
// when the text options button is clicked: "Speech", "Text" and "Both".
// Refer to the patch above for additional details.
// iconTextSwitch::doit (called when the text options button is clicked)
-const byte sq4CdSignatureTextOptions[] = {
- 32,
- 0x89, 0x5a, // lsg 0x5a (load global 90 to stack)
- 0x3c, // dup
- 0x35, 0x01, // ldi 0x01
- 0x1a, // eq? (global 90 == 1)
- 0x31, 0x06, // bnt 0x06 (0x0691)
- 0x35, 0x02, // ldi 0x02
- 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
- 0x33, 0x0a, // jmp 0x0a (0x69b)
- 0x3c, // dup
- 0x35, 0x02, // ldi 0x02
- 0x1a, // eq? (global 90 == 2)
- 0x31, 0x04, // bnt 0x04 (0x069b)
- 0x35, 0x01, // ldi 0x01
- 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
- 0x3a, // toss
- 0x38, 0xd9, 0x00, // pushi 0x00d9
- 0x76, // push0
- 0x54, 0x04, // self 0x04
- 0x48, // ret
- 0
+const uint16 sq4CdSignatureTextOptions[] = {
+ SIG_MAGICDWORD,
+ 0x89, 0x5a, // lsg 0x5a (load global 90 to stack)
+ 0x3c, // dup
+ 0x35, 0x01, // ldi 0x01
+ 0x1a, // eq? (global 90 == 1)
+ 0x31, 0x06, // bnt 0x06 (0x0691)
+ 0x35, 0x02, // ldi 0x02
+ 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
+ 0x33, 0x0a, // jmp 0x0a (0x69b)
+ 0x3c, // dup
+ 0x35, 0x02, // ldi 0x02
+ 0x1a, // eq? (global 90 == 2)
+ 0x31, 0x04, // bnt 0x04 (0x069b)
+ 0x35, 0x01, // ldi 0x01
+ 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
+ 0x3a, // toss
+ 0x38, SIG_SELECTOR16 + SELECTOR_show, // pushi 0x00d9
+ 0x76, // push0
+ 0x54, 0x04, // self 0x04
+ 0x48, // ret
+ SIG_END
};
const uint16 sq4CdPatchTextOptions[] = {
- 0x89, 0x5a, // lsg 0x5a (load global 90 to stack)
- 0x3c, // dup
- 0x35, 0x03, // ldi 0x03 (acc = 3)
- 0x1a, // eq? (global 90 == 3)
- 0x2f, 0x07, // bt 0x07
- 0x89, 0x5a, // lsg 0x5a (load global 90 to stack again)
- 0x35, 0x01, // ldi 0x01 (acc = 1)
- 0x02, // add: acc = global 90 (on stack) + 1 (previous acc value)
- 0x33, 0x02, // jmp 0x02
- 0x35, 0x01, // ldi 0x01 (reset acc to 1)
- 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
- 0x33, 0x03, // jmp 0x03 (jump over the wasted bytes below)
- 0x34, 0x00, 0x00, // ldi 0x0000 (waste 3 bytes)
- 0x3a, // toss
+ 0x89, 0x5a, // lsg 0x5a (load global 90 to stack)
+ 0x3c, // dup
+ 0x35, 0x03, // ldi 0x03 (acc = 3)
+ 0x1a, // eq? (global 90 == 3)
+ 0x2f, 0x07, // bt 0x07
+ 0x89, 0x5a, // lsg 0x5a (load global 90 to stack again)
+ 0x35, 0x01, // ldi 0x01 (acc = 1)
+ 0x02, // add: acc = global 90 (on stack) + 1 (previous acc value)
+ 0x33, 0x02, // jmp 0x02
+ 0x35, 0x01, // ldi 0x01 (reset acc to 1)
+ 0xa1, 0x5a, // sag 0x5a (save acc to global 90)
+ 0x33, 0x03, // jmp 0x03 (jump over the wasted bytes below)
+ 0x34, PATCH_UINT16 + 0x00, 0x00, // ldi 0x0000 (waste 3 bytes)
+ 0x3a, // toss
// (the rest of the code is the same)
PATCH_END
};
-// script, description, magic DWORD, adjust
-const SciScriptSignature sq4Signatures[] = {
- { 298, "Floppy: endless flight", 1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x44), -3, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight },
- { 298, "Floppy (German): endless flight", 1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x4c), -3, sq4FloppySignatureEndlessFlightGerman, sq4FloppyPatchEndlessFlight },
- { 818, "CD: Speech and subtitles option", 1, PATCH_MAGICDWORD(0x89, 0x5a, 0x3c, 0x35), 0, sq4CdSignatureTextOptions, sq4CdPatchTextOptions },
- { 0, "CD: Babble icon speech and subtitles fix", 1, PATCH_MAGICDWORD(0x89, 0x5a, 0x35, 0x02), 0, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon },
- { 818, "CD: Speech and subtitles option button", 1, PATCH_MAGICDWORD(0x35, 0x01, 0xa1, 0x53), 0, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton },
+// script, description, signature patch
+SciScriptPatcherEntry sq4Signatures[] = {
+ { true, 298, "Floppy: endless flight", 1, 0, 0, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight },
+ { true, 818, "CD: Speech and subtitles option", 1, 0, 0, sq4CdSignatureTextOptions, sq4CdPatchTextOptions },
+ { true, 0, "CD: Babble icon speech and subtitles fix", 1, 0, 0, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon },
+ { true, 818, "CD: Speech and subtitles option button", 1, 0, 0, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton },
SCI_SIGNATUREENTRY_TERMINATOR
};
-const byte sq1vgaSignatureEgoShowsCard[] = {
- 25,
- 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
- 0x78, // push1
- 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
- 0x76, // push0
- 0x51, 0x7c, // class DeltaurRegion
- 0x4a, 0x04, // send 0x04 (get timesShownID)
- 0x36, // push
- 0x35, 0x01, // ldi 1
- 0x02, // add
- 0x36, // push
- 0x51, 0x7c, // class DeltaurRegion
- 0x4a, 0x06, // send 0x06 (set timesShownID)
- 0x36, // push (wrong, acc clobbered by class, above)
- 0x35, 0x03, // ldi 0x03
- 0x22, // lt?
- 0};
+// ===========================================================================
+// When you leave Ulence Flats, another timepod is supposed to appear.
+// On fast machines, that timepod appears fully immediately and then
+// starts to appear like it should be. That first appearance is caused
+// by the scripts setting an invalid cel number and the machine being
+// so fast that there is no time for another script to actually fix
+// the cel number. On slower machines, the cel number gets fixed
+// by the cycler and that's why only fast machines are affected.
+// The same issue happens in Sierra SCI.
+// We simply set the correct starting cel number to fix the bug.
+// Responsible method: robotIntoShip::changeState(9)
+const uint16 sq1vgaSignatureUlenceFlatsTimepodGfxGlitch[] = {
+ 0x39,
+ SIG_MAGICDWORD, SIG_SELECTOR8 + SELECTOR_cel, // pushi "cel"
+ 0x78, // push1
+ 0x39, 0x0a, // pushi 0x0a (set ship::cel to 10)
+ 0x38, SIG_UINT16 + 0xa0, 0x00, // pushi 0x00a0 (ship::setLoop)
+ SIG_END
+};
+
+const uint16 sq1vgaPatchUlenceFlatsTimepodGfxGlitch[] = {
+ PATCH_ADDTOOFFSET +3,
+ 0x39, 0x09, // pushi 0x09 (set ship::cel to 9)
+ PATCH_END
+};
+
+const uint16 sq1vgaSignatureEgoShowsCard[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
+ 0x78, // push1
+ 0x38, SIG_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
+ 0x76, // push0
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
+ 0x36, // push
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x36, // push (wrong, acc clobbered by class, above)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ SIG_END
+};
// Note that this script patch is merely a reordering of the
// instructions in the original script.
const uint16 sq1vgaPatchEgoShowsCard[] = {
- 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
- 0x76, // push0
- 0x51, 0x7c, // class DeltaurRegion
- 0x4a, 0x04, // send 0x04 (get timesShownID)
- 0x36, // push
- 0x35, 0x01, // ldi 1
- 0x02, // add
- 0x36, // push (this push corresponds to the wrong one above)
- 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
- 0x78, // push1
- 0x36, // push
- 0x51, 0x7c, // class DeltaurRegion
- 0x4a, 0x06, // send 0x06 (set timesShownID)
- 0x35, 0x03, // ldi 0x03
- 0x22, // lt?
- PATCH_END};
-
-
-// script, description, magic DWORD, adjust
-const SciScriptSignature sq1vgaSignatures[] = {
- { 58, "Sarien armory droid zapping ego first time", 1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70,
- sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
+ 0x38, PATCH_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
+ 0x76, // push0
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
+ 0x36, // push
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push (this push corresponds to the wrong one above)
+ 0x38, PATCH_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
+ 0x78, // push1
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry sq1vgaSignatures[] = {
+ { true, 45, "Ulence Flats: timepod graphic glitch", 1, 0, 0, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch },
+ { true, 58, "Sarien armory droid zapping ego first time", 1, 0, 0, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
SCI_SIGNATUREENTRY_TERMINATOR};
+// ===========================================================================
+// The toolbox in sq5 is buggy. When you click on the upper part of the "put
+// in inventory"-button (some items only - for example the hole puncher - at the
+// upper left), points will get awarded correctly and the item will get put into
+// the player's inventory, but you will then get a "not here" message and the
+// item will also remain to be the current mouse cursor.
+// The bug report also says that items may get lost. I wasn't able to reproduce
+// that part.
+// This is caused by the mouse-click event getting reprocessed (which wouldn't
+// be a problem by itself) and during this reprocessing coordinates are not
+// processed the same as during the first click (script 226 includes a local
+// subroutine, which checks coordinates in a hardcoded way w/o port-adjustment).
+// Because of this, the hotspot for the button is lower than it should be, which
+// then results in the game thinking that the user didn't click on the button
+// and also results in the previously mentioned message.
+// This happened in Sierra SCI as well (of course).
+// We fix it by combining state 0 + 1 of takeTool::changeState and so stopping
+// the event to get reprocessed. This was the only way possible, because everything
+// else is done in SCI system scripts and I don't want to touch those.
+// Applies to at least: English/German/French PC floppy
+// Responsible method: takeTool::changeState
+// Fixes bug: #6457
+const uint16 sq5SignatureToolboxFix[] = {
+ 0x31, 0x13, // bnt [check for state 1]
+ SIG_MAGICDWORD,
+ 0x38, SIG_UINT16 + 0xaa, 0x00, // pushi 00aa
+ 0x39, 0x05, // pushi 05
+ 0x39, 0x16, // pushi 16
+ 0x76, // push0
+ 0x39, 0x03, // pushi 03
+ 0x76, // push0
+ 0x7c, // pushSelf
+ 0x81, 0x5b, // lag 5b
+ 0x4a, 0x0e, // send 0e
+ 0x32, SIG_UINT16 + 0x88, 0x00, // jmp [end-of-method]
+ 0x3c, // dup
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x31, 0x28, // bnt [check for state 2]
+ SIG_END
+};
+
+const uint16 sq5PatchToolboxFix[] = {
+ 0x31, 0x41, // bnt [check for state 2]
+ PATCH_ADDTOOFFSET +16, // skip to jmp offset
+ 0x35, 0x01, // ldi 01
+ 0x65, 0x14, // aTop [state]
+ 0x36, 0x00, 0x00, // ldi 0000 (waste 3 bytes)
+ 0x35, 0x00, // ldi 00 (waste 2 bytes)
+ PATCH_END
+};
+
+// script, description, signature patch
+SciScriptPatcherEntry sq5Signatures[] = {
+ { true, 226, "toolbox fix", 1, 0, 0, sq5SignatureToolboxFix, sq5PatchToolboxFix },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+
// will actually patch previously found signature area
-void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) {
+void Script::patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, const bool isMacSci11) {
+ const uint16 *patchData = patchEntry->patchData;
byte orgData[PATCH_VALUELIMIT];
int32 offset = signatureOffset;
- uint16 patchWord = *patch;
+ uint16 patchWord = *patchEntry->patchData;
+ uint16 patchSelector = 0;
// Copy over original bytes from script
uint32 orgDataSize = scriptSize - offset;
@@ -1290,74 +2025,179 @@ void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scri
memcpy(&orgData, &scriptData[offset], orgDataSize);
while (patchWord != PATCH_END) {
+ uint16 patchCommand = patchWord & PATCH_COMMANDMASK;
uint16 patchValue = patchWord & PATCH_VALUEMASK;
- switch (patchWord & PATCH_COMMANDMASK) {
- case PATCH_ADDTOOFFSET:
+ switch (patchCommand) {
+ case PATCH_ADDTOOFFSET: {
// add value to offset
- offset += patchValue & ~PATCH_ADDTOOFFSET;
+ offset += patchValue;
break;
- case PATCH_GETORIGINALBYTE:
+ }
+ case PATCH_GETORIGINALBYTE: {
// get original byte from script
if (patchValue >= orgDataSize)
- error("patching: can not get requested original byte from script");
+ error("Script-Patcher: can not get requested original byte from script");
scriptData[offset] = orgData[patchValue];
offset++;
break;
- case PATCH_ADJUSTWORD: {
- // Adjust word right before current position
- byte *adjustPtr = &scriptData[offset - 2];
- uint16 adjustWord = READ_LE_UINT16(adjustPtr);
- adjustWord += patchValue;
- WRITE_LE_UINT16(adjustPtr, adjustWord);
+ }
+ case PATCH_GETORIGINALBYTEADJUST: {
+ // get original byte from script and adjust it
+ if (patchValue >= orgDataSize)
+ error("Script-Patcher: can not get requested original byte from script");
+ byte orgByte = orgData[patchValue];
+ int16 adjustValue;
+ patchData++; adjustValue = (int16)(*patchData);
+ scriptData[offset] = orgByte + adjustValue;
+ offset++;
+ break;
+ }
+ case PATCH_UINT16:
+ case PATCH_SELECTOR16: {
+ byte byte1;
+ byte byte2;
+
+ switch (patchCommand) {
+ case PATCH_UINT16: {
+ byte1 = patchValue & PATCH_BYTEMASK;
+ patchData++; patchWord = *patchData;
+ if (patchWord & PATCH_COMMANDMASK)
+ error("Script-Patcher: Patch inconsistent");
+ byte2 = patchWord & PATCH_BYTEMASK;
+ break;
+ }
+ case PATCH_SELECTOR16: {
+ patchSelector = selectorTable[patchValue].id;
+ byte1 = patchSelector & 0xFF;
+ byte2 = patchSelector >> 8;
+ break;
+ }
+ default:
+ byte1 = 0; byte2 = 0;
+ }
+ if (!isMacSci11) {
+ scriptData[offset++] = byte1;
+ scriptData[offset++] = byte2;
+ } else {
+ // SCI1.1+ on macintosh had uint16s in script in BE-order
+ scriptData[offset++] = byte2;
+ scriptData[offset++] = byte1;
+ }
break;
}
- case PATCH_ADJUSTWORD_NEG: {
- // Adjust word right before current position (negative way)
- byte *adjustPtr = &scriptData[offset - 2];
- uint16 adjustWord = READ_LE_UINT16(adjustPtr);
- adjustWord -= patchValue;
- WRITE_LE_UINT16(adjustPtr, adjustWord);
+ case PATCH_SELECTOR8: {
+ patchSelector = selectorTable[patchValue].id;
+ if (patchSelector & 0xFF00)
+ error("Script-Patcher: 8 bit selector required, game uses 16 bit selector");
+ scriptData[offset] = patchSelector & 0xFF;
+ offset++;
break;
}
- default:
- scriptData[offset] = patchValue & 0xFF;
+ case PATCH_BYTE:
+ scriptData[offset] = patchValue & PATCH_BYTEMASK;
offset++;
}
- patch++;
- patchWord = *patch;
+ patchData++;
+ patchWord = *patchData;
}
}
// will return -1 if no match was found, otherwise an offset to the start of the signature match
-int32 Script::findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize) {
+int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, const byte *scriptData, const uint32 scriptSize, const bool isMacSci11) {
if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay
return -1;
- const uint32 magicDWord = signature->magicDWord; // is platform-specific BE/LE form, so that the later match will work
+ const uint32 magicDWord = patchEntry->magicDWord; // is platform-specific BE/LE form, so that the later match will work
const uint32 searchLimit = scriptSize - 3;
uint32 DWordOffset = 0;
// first search for the magic DWORD
while (DWordOffset < searchLimit) {
if (magicDWord == READ_UINT32(scriptData + DWordOffset)) {
// magic DWORD found, check if actual signature matches
- uint32 offset = DWordOffset + signature->magicOffset;
+ uint32 offset = DWordOffset + patchEntry->magicOffset;
uint32 byteOffset = offset;
- const byte *signatureData = signature->data;
- byte matchAdjust = 1;
- while (matchAdjust) {
- byte matchBytesCount = *signatureData++;
- if ((byteOffset + matchBytesCount) > scriptSize) // Out-Of-Bounds?
+ const uint16 *signatureData = patchEntry->signatureData;
+ uint16 sigSelector = 0;
+
+ uint16 sigWord = *signatureData;
+ while (sigWord != SIG_END) {
+ uint16 sigCommand = sigWord & SIG_COMMANDMASK;
+ uint16 sigValue = sigWord & SIG_VALUEMASK;
+ switch (sigCommand) {
+ case SIG_ADDTOOFFSET: {
+ // add value to offset
+ byteOffset += sigValue;
+ break;
+ }
+ case SIG_UINT16:
+ case SIG_SELECTOR16: {
+ if ((byteOffset + 1) < scriptSize) {
+ byte byte1;
+ byte byte2;
+
+ switch (sigCommand) {
+ case SIG_UINT16: {
+ byte1 = sigValue & SIG_BYTEMASK;
+ signatureData++; sigWord = *signatureData;
+ if (sigWord & SIG_COMMANDMASK)
+ error("Script-Patcher: signature inconsistent\nFaulty patch: '%s'", patchEntry->description);
+ byte2 = sigWord & SIG_BYTEMASK;
+ break;
+ }
+ case SIG_SELECTOR16: {
+ sigSelector = selectorTable[sigValue].id;
+ byte1 = sigSelector & 0xFF;
+ byte2 = sigSelector >> 8;
+ break;
+ }
+ default:
+ byte1 = 0; byte2 = 0;
+ }
+ if (!isMacSci11) {
+ if ((scriptData[byteOffset] != byte1) || (scriptData[byteOffset + 1] != byte2))
+ sigWord = SIG_MISMATCH;
+ } else {
+ // SCI1.1+ on macintosh had uint16s in script in BE-order
+ if ((scriptData[byteOffset] != byte2) || (scriptData[byteOffset + 1] != byte1))
+ sigWord = SIG_MISMATCH;
+ }
+ byteOffset += 2;
+ } else {
+ sigWord = SIG_MISMATCH;
+ }
break;
- if (memcmp(signatureData, &scriptData[byteOffset], matchBytesCount)) // Byte-Mismatch?
+ }
+ case SIG_SELECTOR8: {
+ if (byteOffset < scriptSize) {
+ sigSelector = selectorTable[sigValue].id;
+ if (sigSelector & 0xFF00)
+ error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", patchEntry->description);
+ if (scriptData[byteOffset] != (sigSelector & 0xFF))
+ sigWord = SIG_MISMATCH;
+ byteOffset++;
+ } else {
+ sigWord = SIG_MISMATCH; // out of bounds
+ }
+ break;
+ }
+ case SIG_BYTE:
+ if (byteOffset < scriptSize) {
+ if (scriptData[byteOffset] != sigWord)
+ sigWord = SIG_MISMATCH;
+ byteOffset++;
+ } else {
+ sigWord = SIG_MISMATCH; // out of bounds
+ }
+ }
+
+ if (sigWord == SIG_MISMATCH)
break;
- // those bytes matched, adjust offsets accordingly
- signatureData += matchBytesCount;
- byteOffset += matchBytesCount;
- // get offset...
- matchAdjust = *signatureData++;
- byteOffset += matchAdjust;
+
+ signatureData++;
+ sigWord = *signatureData;
}
- if (!matchAdjust) // all matches worked?
+
+ if (sigWord == SIG_END) // signature fully matched?
return offset;
}
DWordOffset++;
@@ -1366,9 +2206,164 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
return -1;
}
-void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
- const SciScriptSignature *signatureTable = NULL;
- switch (g_sci->getGameId()) {
+// This method calculates the magic DWORD for each entry in the signature table
+// and it also initializes the selector table for selectors used in the signatures/patches of the current game
+void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11) {
+ SciScriptPatcherEntry *curEntry = patchTable;
+ SciScriptPatcherSelector *curSelector = NULL;
+ int step;
+ int magicOffset;
+ byte magicDWord[4];
+ int magicDWordLeft = 0;
+ const uint16 *curData;
+ uint16 curWord;
+ uint16 curCommand;
+ uint32 curValue;
+ byte byte1;
+ byte byte2;
+
+ while (curEntry->signatureData) {
+ // process signature
+ memset(magicDWord, 0, sizeof(magicDWord));
+
+ for (step = 0; step < 2; step++) {
+ switch (step) {
+ case 0: curData = curEntry->signatureData; break;
+ case 1: curData = curEntry->patchData; break;
+ }
+
+ curWord = *curData;
+ magicOffset = 0;
+ while (curWord != SIG_END) {
+ curCommand = curWord & SIG_COMMANDMASK;
+ curValue = curWord & SIG_VALUEMASK;
+ switch (curCommand) {
+ case SIG_MAGICDWORD: {
+ if (step == 0) {
+ if ((curEntry->magicDWord) || (magicDWordLeft))
+ error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", curEntry->description);
+ magicDWordLeft = 4;
+ curEntry->magicOffset = magicOffset;
+ }
+ break;
+ }
+ case SIG_ADDTOOFFSET: {
+ magicOffset -= curValue;
+ if (magicDWordLeft)
+ error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", curEntry->description);
+ break;
+ }
+ case SIG_UINT16:
+ case SIG_SELECTOR16: {
+ // UINT16 or 1
+ switch (curCommand) {
+ case SIG_UINT16: {
+ curData++; curWord = *curData;
+ if (curWord & SIG_COMMANDMASK)
+ error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", curEntry->description);
+ if (!isMacSci11) {
+ byte1 = curValue;
+ byte2 = curWord & SIG_BYTEMASK;
+ } else {
+ byte1 = curWord & SIG_BYTEMASK;
+ byte2 = curValue;
+ }
+ break;
+ }
+ case SIG_SELECTOR16: {
+ curSelector = &selectorTable[curValue];
+ if (curSelector->id == -1)
+ curSelector->id = g_sci->getKernel()->findSelector(curSelector->name);
+ if (!isMacSci11) {
+ byte1 = curSelector->id & 0x00FF;
+ byte2 = curSelector->id >> 8;
+ } else {
+ byte1 = curSelector->id >> 8;
+ byte2 = curSelector->id & 0x00FF;
+ }
+ break;
+ }
+ }
+ magicOffset -= 2;
+ if (magicDWordLeft) {
+ // Remember current word for Magic DWORD
+ magicDWord[4 - magicDWordLeft] = byte1;
+ magicDWordLeft--;
+ if (magicDWordLeft) {
+ magicDWord[4 - magicDWordLeft] = byte2;
+ magicDWordLeft--;
+ }
+ if (!magicDWordLeft) {
+ curEntry->magicDWord = READ_LE_UINT32(magicDWord);
+ }
+ }
+ break;
+ }
+ case SIG_BYTE:
+ case SIG_SELECTOR8: {
+ if (curCommand == SIG_SELECTOR8) {
+ curSelector = &selectorTable[curValue];
+ if (curSelector->id == -1) {
+ curSelector->id = g_sci->getKernel()->findSelector(curSelector->name);
+ if (curSelector->id != -1) {
+ if (curSelector->id & 0xFF00)
+ error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", curEntry->description);
+ }
+ }
+ curValue = curSelector->id;
+ }
+ magicOffset--;
+ if (magicDWordLeft) {
+ // Remember current byte for Magic DWORD
+ magicDWord[4 - magicDWordLeft] = (byte)curValue;
+ magicDWordLeft--;
+ if (!magicDWordLeft) {
+ curEntry->magicDWord = READ_LE_UINT32(magicDWord);
+ }
+ }
+ }
+ }
+ curData++;
+ curWord = *curData;
+ }
+ }
+ if (magicDWordLeft)
+ error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", curEntry->description);
+ if (!curEntry->magicDWord)
+ error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", curEntry->description);
+
+ curEntry++;
+ }
+}
+
+// This method enables certain patches
+// It's used for patches, which are not meant to get applied all the time
+void Script::patcherEnablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription) {
+ SciScriptPatcherEntry *curEntry = patchTable;
+ int searchDescriptionLen = strlen( searchDescription );
+ int matchCount = 0;
+
+ while (curEntry->signatureData) {
+ if (strncmp(curEntry->description, searchDescription, searchDescriptionLen) == 0) {
+ // match found, enable patch
+ curEntry->active = true;
+ matchCount++;
+ }
+ curEntry++;
+ }
+
+ if (!matchCount)
+ error("Script-Patcher: no patch found to enable");
+}
+
+void Script::patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
+ SciScriptPatcherEntry *signatureTable = NULL;
+ const Sci::SciGameId gameId = g_sci->getGameId();
+
+ switch (gameId) {
+ case GID_CAMELOT:
+ signatureTable = camelotSignatures;
+ break;
case GID_ECOQUEST:
signatureTable = ecoquest1Signatures;
break;
@@ -1385,11 +2380,7 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
signatureTable = gk1Signatures;
break;
case GID_KQ5:
- // See the explanation in the kq5SignatureWinGMSignals comment
- if (g_sci->_features->useAltWinGMSound())
- signatureTable = kq5WinGMSignatures;
- else
- signatureTable = kq5Signatures;
+ signatureTable = kq5Signatures;
break;
case GID_KQ6:
signatureTable = kq6Signatures;
@@ -1400,12 +2391,21 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_LONGBOW:
signatureTable = longbowSignatures;
break;
+ case GID_LSL2:
+ signatureTable = larry2Signatures;
+ break;
+ case GID_LSL5:
+ signatureTable = larry5Signatures;
+ break;
case GID_LSL6:
signatureTable = larry6Signatures;
break;
case GID_MOTHERGOOSE256:
signatureTable = mothergoose256Signatures;
break;
+ case GID_PQ1:
+ signatureTable = pq1vgaSignatures;
+ break;
case GID_QFG1VGA:
signatureTable = qfg1vgaSignatures;
break;
@@ -1421,21 +2421,53 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_SQ4:
signatureTable = sq4Signatures;
break;
+ case GID_SQ5:
+ signatureTable = sq5Signatures;
+ break;
default:
break;
}
if (signatureTable) {
- while (signatureTable->data) {
- if (scriptNr == signatureTable->scriptNr) {
+ bool isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1);
+
+ if (!signatureTable->magicDWord) {
+ // Abort, in case selectors are not yet initialized (happens for games w/o selector-dictionary)
+ if (!g_sci->getKernel()->selectorNamesAvailable())
+ return;
+
+ // signature table needs to get initialized (Magic DWORD set, selector table set)
+ patcherInitSignature(signatureTable, isMacSci11);
+
+ // Do additional game-specific initialization
+ switch (gameId) {
+ case GID_KQ5:
+ if (g_sci->_features->useAltWinGMSound()) {
+ // See the explanation in the kq5SignatureWinGMSignals comment
+ patcherEnablePatch(signatureTable, "Win: GM Music signal checks");
+ }
+ break;
+ case GID_LAURABOW2:
+ if (g_sci->speechAndSubtitlesEnabled()) {
+ // Enables Audio + subtitles patches for Laura Bow 2, when "Text and Speech: Both" is selected
+ patcherEnablePatch(signatureTable, "CD: audio + text support");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ while (signatureTable->signatureData) {
+ if ( (scriptNr == signatureTable->scriptNr) && (signatureTable->active) ) {
int32 foundOffset = 0;
int16 applyCount = signatureTable->applyCount;
do {
- foundOffset = findSignature(signatureTable, scriptData, scriptSize);
+ foundOffset = patcherFindSignature(signatureTable, scriptData, scriptSize, isMacSci11);
if (foundOffset != -1) {
// found, so apply the patch
- debugC(kDebugLevelScripts, "matched and patched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
- applyPatch(signatureTable->patch, scriptData, scriptSize, foundOffset);
+ debugC(kDebugLevelScriptPatcher, "Script-Patcher: '%s' on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
+ patcherApplyPatch(signatureTable, scriptData, scriptSize, foundOffset, isMacSci11);
}
applyCount--;
} while ((foundOffset != -1) && (applyCount));
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 97e33f256b..a059bee74e 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -262,8 +262,14 @@ const char *SegManager::getObjectName(reg_t pos) {
const char *name = 0;
if (nameReg.getSegment())
name = derefString(nameReg);
- if (!name)
- return "<invalid name>";
+ if (!name) {
+ // Crazy Nick Laura Bow is missing some object names needed for the static
+ // selector vocabulary
+ if (g_sci->getGameId() == GID_CNICK_LAURABOW && pos == make_reg(1, 0x2267))
+ return "Character";
+ else
+ return "<invalid name>";
+ }
return name;
}
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 074d3f6b0a..0667b75651 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -224,7 +224,7 @@ public:
* Allocate a fresh chunk of the hunk
* @param[in] size Number of bytes to allocate for the hunk entry
* @param[in] hunk_type A descriptive string for the hunk entry, for
- * debugging purposes
+ * debugging purposes
* @return The offset of the freshly allocated hunk entry
*/
reg_t allocateHunkEntry(const char *hunk_type, int size);
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index ef8f165084..d7c2fdc0eb 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -200,11 +200,18 @@ static void write_var(EngineState *s, int type, int index, reg_t value) {
s->variables[type][index] = value;
- // If the game is trying to change its speech/subtitle settings, apply the ScummVM audio
- // options first, if they haven't been applied yet
- if (type == VAR_GLOBAL && index == 90 && !g_sci->getEngineState()->_syncedAudioOptions) {
- g_sci->syncIngameAudioOptions();
- g_sci->getEngineState()->_syncedAudioOptions = true;
+ if (type == VAR_GLOBAL && index == 90) {
+ // The game is trying to change its speech/subtitle settings
+ if (!g_sci->getEngineState()->_syncedAudioOptions || s->variables[VAR_GLOBAL][4] == TRUE_REG) {
+ // ScummVM audio options haven't been applied yet, so apply them.
+ // We also force the ScummVM audio options when loading a game from
+ // the launcher.
+ g_sci->syncIngameAudioOptions();
+ g_sci->getEngineState()->_syncedAudioOptions = true;
+ } else {
+ // Update ScummVM's audio options
+ g_sci->updateScummVMAudioOptions();
+ }
}
}
}
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index 27015d9be4..5327dd1a2e 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -28,12 +28,12 @@
namespace Sci {
-reg_t reg_t::lookForWorkaround(const reg_t right) const {
+reg_t reg_t::lookForWorkaround(const reg_t right, const char *operation) const {
SciTrackOriginReply originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, arithmeticWorkarounds, &originReply);
if (solution.type == WORKAROUND_NONE)
- error("Invalid arithmetic operation (params: %04x:%04x and %04x:%04x) from method %s::%s (room %d, script %d, localCall %x)",
- PRINT_REG(*this), PRINT_REG(right), originReply.objectName.c_str(),
+ error("Invalid arithmetic operation (%s - params: %04x:%04x and %04x:%04x) from method %s::%s (room %d, script %d, localCall %x)",
+ operation, PRINT_REG(*this), PRINT_REG(right), originReply.objectName.c_str(),
originReply.methodName.c_str(), g_sci->getEngineState()->currentRoomNumber(), originReply.scriptNr,
originReply.localCallOffset);
assert(solution.type == WORKAROUND_FAKE);
@@ -55,7 +55,7 @@ reg_t reg_t::operator+(const reg_t right) const {
case SEG_TYPE_DYNMEM:
return make_reg(getSegment(), getOffset() + right.toSint16());
default:
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "addition");
}
} else if (isNumber() && right.isPointer()) {
// Adding a pointer to a number, flip the order
@@ -64,7 +64,7 @@ reg_t reg_t::operator+(const reg_t right) const {
// Normal arithmetics
return make_reg(0, toSint16() + right.toSint16());
} else {
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "addition");
}
}
@@ -82,14 +82,14 @@ reg_t reg_t::operator*(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toSint16() * right.toSint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "multiplication");
}
reg_t reg_t::operator/(const reg_t right) const {
if (isNumber() && right.isNumber() && !right.isNull())
return make_reg(0, toSint16() / right.toSint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "division");
}
reg_t reg_t::operator%(const reg_t right) const {
@@ -109,21 +109,21 @@ reg_t reg_t::operator%(const reg_t right) const {
result += modulo;
return make_reg(0, result);
} else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "modulo");
}
reg_t reg_t::operator>>(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toUint16() >> right.toUint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "shift right");
}
reg_t reg_t::operator<<(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toUint16() << right.toUint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "shift left");
}
reg_t reg_t::operator+(int16 right) const {
@@ -140,7 +140,7 @@ uint16 reg_t::requireUint16() const {
else
// The right parameter is NULL_REG because
// we're not comparing *this with anything here.
- return lookForWorkaround(NULL_REG).toUint16();
+ return lookForWorkaround(NULL_REG, "require unsigned number").toUint16();
}
int16 reg_t::requireSint16() const {
@@ -149,28 +149,28 @@ int16 reg_t::requireSint16() const {
else
// The right parameter is NULL_REG because
// we're not comparing *this with anything here.
- return lookForWorkaround(NULL_REG).toSint16();
+ return lookForWorkaround(NULL_REG, "require signed number").toSint16();
}
reg_t reg_t::operator&(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toUint16() & right.toUint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "bitwise AND");
}
reg_t reg_t::operator|(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toUint16() | right.toUint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "bitwise OR");
}
reg_t reg_t::operator^(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toUint16() ^ right.toUint16());
else
- return lookForWorkaround(right);
+ return lookForWorkaround(right, "bitwise XOR");
}
int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
@@ -184,7 +184,7 @@ int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
} else if (right.pointerComparisonWithInteger(*this)) {
return -1;
} else
- return lookForWorkaround(right).toSint16();
+ return lookForWorkaround(right, "comparison").toSint16();
}
bool reg_t::pointerComparisonWithInteger(const reg_t right) const {
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index 9a7589e9a7..22bd8beaa1 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -156,7 +156,7 @@ private:
* - a negative number if *this < right
*/
int cmp(const reg_t right, bool treatAsUnsigned) const;
- reg_t lookForWorkaround(const reg_t right) const;
+ reg_t lookForWorkaround(const reg_t right, const char *operation) const;
bool pointerComparisonWithInteger(const reg_t right) const;
};
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 6af6326042..6fdff1ce91 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -37,6 +37,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = {
{ GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #3313962
{ GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913
{ GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7
+ { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3")
{ GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl
{ GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version)
{ GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228
@@ -50,9 +51,16 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
+ { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #3614968
{ GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", -1, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #3039656). Moves the cursor to the view with the ID returned (in this case, the robot hand)
{ GID_CNICK_KQ, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // checkers/backgammon, like in hoyle 3 - temps 504 and 505 - bug #3606025
{ GID_CNICK_KQ, -1, 700, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering the control menu, like in hoyle 3
+ { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "<noname520>", -1, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - bug #3615121 (same as the theDoubleCube::make workaround for Hoyle 3)
+ { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "<noname519>", -1, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled (same as the theDoubleCube::accept workaround for Hoyle 3)
+ { GID_CNICK_LAURABOW, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // Yatch, like in hoyle 3 - temps 504 and 505 - bug #3615119
+ { GID_CNICK_LAURABOW, -1, 700, 0, NULL, "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - bug #3615118 (same as the gcWindow workaround for Hoyle 3)
+ { GID_CNICK_LAURABOW,100, 100, 0, NULL, "<noname144>", -1, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #3615129 (same as the dominoHand2 workaround for Hoyle 3)
+ { GID_CNICK_LAURABOW,100, 110, 0, NULL, "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #3615130
{ GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game
{ GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms
{ GID_FANMADE, 516, 979, 0, "", "export 0", -1, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos
@@ -71,12 +79,17 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_HOYLE3, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505
{ GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu
{ GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", -1, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #3036918
+ { GID_HOYLE3, 100, 110, 0, "OKButton", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #3615130
+ { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "make", -1, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled
+ { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "accept", -1, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled
{ GID_HOYLE4, -1, 0, 0, NULL, "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #3039294
{ GID_HOYLE4, 910, 18, 0, NULL, "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #3042756
{ GID_HOYLE4, 910, 910, 0, NULL, "setup", -1, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #3039294
- { GID_HOYLE4, 700, 718, 0, "compete_tree", "doit", -1, 75, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge - bug #3292332
- { GID_HOYLE4, 700, 716, 0, "other1_tree", "doit", -1, 46, { WORKAROUND_FAKE, 0 } }, // sometimes when placing a bid in bridge
- { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, 3, { WORKAROUND_FAKE, 0 } }, // sometimes when placing a bid in bridge
+ { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, 3, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always)
+ { GID_HOYLE4, 700, 710, 1, "BridgeStrategyPlay", "checkSplitTops", -1, 10, { WORKAROUND_FAKE, 0 } }, // while playing bridge, objects LeadReturn_Trump, SecondSeat_Trump, ThirdSeat_Trump and others - bug #3361925
+ { GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others
+ { GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge
+ { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #3292332 and #3361925
{ GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts
{ GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #3292334
{ GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #3292327
@@ -97,6 +110,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle
{ GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc)
{ GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #3059544
+ { GID_KQ6, -1, 928, 0, NULL, "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher)
{ GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
{ GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs (bug #3037694)
{ GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985)
@@ -104,6 +118,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #3035068, #3036274
{ GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
{ GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #3036291
+ { GID_LAURABOW2, -1, 928, 0, NULL, "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher)
{ GID_LONGBOW, -1, 0, 0, "Longbow", "restart", -1, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #3046200
{ GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room
{ GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #3036601
@@ -167,6 +182,9 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens)
{ GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin
{ GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously
+ { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447
+ { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447
+ { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447
{ GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #3038563
{ GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100)
{ GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places
@@ -208,6 +226,7 @@ const SciWorkaroundEntry kDeviceInfo_workarounds[] = {
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest)
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest)
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xe57, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back)
+ { GID_FANMADE, -1, 994, 0, "Black", "save", 0xa, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Black Cauldron Remake)
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xe5c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them)
{ GID_FANMADE, -1, 994, 1, "Game", "restore", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest)
{ GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest)
@@ -249,6 +268,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = {
{ GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object
{ GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #3034567
{ GID_QFG4, -1, 64989, 0, "longSong", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong)
+ { GID_SQ5, 800, 989, 0, "sq5Music1", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when cutting the wrong part of Goliath with the laser - bug #3614145
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -359,6 +379,13 @@ const SciWorkaroundEntry kNewWindow_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kReadNumber_workarounds[] = {
+ { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #3615120
+ { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #3615120
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = {
{ GID_QFG4, 100, 100, 0, "doMovie", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #3034506
SCI_WORKAROUNDENTRY_TERMINATOR
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 59054ae552..d5e91b70ec 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -88,6 +88,7 @@ extern const SciWorkaroundEntry kIsObject_workarounds[];
extern const SciWorkaroundEntry kMemory_workarounds[];
extern const SciWorkaroundEntry kMoveCursor_workarounds[];
extern const SciWorkaroundEntry kNewWindow_workarounds[];
+extern const SciWorkaroundEntry kReadNumber_workarounds[];
extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[];
extern const SciWorkaroundEntry kSetCursor_workarounds[];
extern const SciWorkaroundEntry kSetPort_workarounds[];
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index bf1ce6da64..76510fa53b 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -532,7 +532,7 @@ void GfxFrameout::showVideo() {
if (videoDecoder->needsUpdate()) {
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
if (frame) {
- g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
if (videoDecoder->hasDirtyPalette())
g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
@@ -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/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index dfb50b0edb..4df80b289f 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -129,7 +129,7 @@ void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) {
void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
if (surface)
- g_system->copyRectToScreen(surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height());
+ g_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect.left, rect.top, rect.width(), rect.height());
}
void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
@@ -153,7 +153,7 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::
*((byte *)newSurf.getBasePtr(j, i)) = 0;
}
- g_system->copyRectToScreen(newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height());
+ g_system->copyRectToScreen(newSurf.getPixels(), newSurf.pitch, rect.left, rect.top, rect.width(), rect.height());
newSurf.free();
}
@@ -224,7 +224,7 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected)
}
void GfxMacIconBar::remapColors(Graphics::Surface *surf, const byte *palette) {
- byte *pixels = (byte *)surf->pixels;
+ byte *pixels = (byte *)surf->getPixels();
// Remap to the screen palette
for (uint16 i = 0; i < surf->w * surf->h; i++) {
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index af372640da..8ad4f535f9 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -236,7 +236,9 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
byte *ptr = NULL;
byte *headerPtr = inbuffer + headerPos;
byte *rlePtr = inbuffer + rlePos;
- int16 displaceX, displaceY;
+ // displaceX, displaceY fields are ignored, and may contain garbage
+ // (e.g. pic 261 in Dr. Brain 1 Spanish - bug #3614914)
+ //int16 displaceX, displaceY;
byte priority = _addToFlag ? _priority : 0;
byte clearColor;
bool compression = true;
@@ -251,8 +253,8 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
// Width/height here are always LE, even in Mac versions
width = READ_LE_UINT16(headerPtr + 0);
height = READ_LE_UINT16(headerPtr + 2);
- displaceX = (signed char)headerPtr[4];
- displaceY = (unsigned char)headerPtr[5];
+ //displaceX = (signed char)headerPtr[4];
+ //displaceY = (unsigned char)headerPtr[5];
if (_resourceType == SCI_PICTURE_TYPE_SCI11)
// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
clearColor = _screen->getColorWhite();
@@ -262,16 +264,16 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
} else {
width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
height = READ_SCI11ENDIAN_UINT16(headerPtr + 2);
- displaceX = READ_SCI11ENDIAN_UINT16(headerPtr + 4); // probably signed?!?
- displaceY = READ_SCI11ENDIAN_UINT16(headerPtr + 6); // probably signed?!?
+ //displaceX = READ_SCI11ENDIAN_UINT16(headerPtr + 4); // probably signed?!?
+ //displaceY = READ_SCI11ENDIAN_UINT16(headerPtr + 6); // probably signed?!?
clearColor = headerPtr[8];
if (headerPtr[9] == 0)
compression = false;
}
#endif
- if (displaceX || displaceY)
- error("unsupported embedded cel-data in picture");
+ //if (displaceX || displaceY)
+ // error("unsupported embedded cel-data in picture");
// We will unpack cel-data into a temporary buffer and then plot it to screen
// That needs to be done cause a mirrored picture may be requested
@@ -656,6 +658,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
case 35:
case 381:
case 376:
+ //case 390: // in the blacklisted NRS patch 1.2 (bug #3615060)
return;
default:
break;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 527e2ae973..6d9dc03195 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -116,7 +116,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
setPort(_wmgrPort);
// SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow
// We leave _wmgrPort top at 0, so the adjustment wont get done
- if (!g_sci->_features->usesOldGfxFunctions()) {
+ if (!_usesOldGfxFunctions) {
setOrigin(0, offTop);
_wmgrPort->rect.bottom = _screen->getHeight() - offTop;
} else {
@@ -131,7 +131,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
_picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
// For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead
// Because of the menu/status bar
- if (g_sci->_features->usesOldGfxFunctions())
+ if (_usesOldGfxFunctions)
_picWind->top = offTop;
kernelInitPriorityBands();
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 74503c0c77..0df163dd7b 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -170,14 +170,14 @@ void GfxScreen::copyToScreen() {
void GfxScreen::copyFromScreen(byte *buffer) {
// TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
- memcpy(buffer, screen->pixels, _displayPixels);
+ memcpy(buffer, screen->getPixels(), _displayPixels);
g_system->unlockScreen();
}
void GfxScreen::kernelSyncWithFramebuffer() {
// TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
- memcpy(_displayScreen, screen->pixels, _displayPixels);
+ memcpy(_displayScreen, screen->getPixels(), _displayPixels);
g_system->unlockScreen();
}
@@ -286,11 +286,15 @@ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) {
* with flood fill, due to small difference in the Bresenham logic.
*/
void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) {
- int16 left = startPoint.x;
- int16 top = startPoint.y;
- int16 right = endPoint.x;
- int16 bottom = endPoint.y;
-
+ int16 maxWidth = _width - 1;
+ int16 maxHeight = _height - 1;
+ // we need to clip values here, lsl3 room 620 background picture draws a line from 0, 199 t 320, 199
+ // otherwise we would get heap corruption.
+ int16 left = CLIP<int16>(startPoint.x, 0, maxWidth);
+ int16 top = CLIP<int16>(startPoint.y, 0, maxHeight);
+ int16 right = CLIP<int16>(endPoint.x, 0, maxWidth);
+ int16 bottom = CLIP<int16>(endPoint.y, 0, maxHeight);
+
//set_drawing_flag
byte drawMask = getDrawingMask(color, priority, control);
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 4baf39c67f..6fa51754a4 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -498,7 +498,7 @@ protected:
void readWaveAudioPatches();
void processWavePatch(ResourceId resourceId, Common::String name);
- /**
+ /**
* Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2).
* Old SCI versions used two word header for script blocks (first word equal
* to 0x82, meaning of the second one unknown). New SCI versions used one
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index c1aadc3622..065565d8de 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -112,6 +112,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam
DebugMan.addDebugChannel(kDebugLevelDclInflate, "DCL", "DCL inflate debugging");
DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging");
DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded");
+ DebugMan.addDebugChannel(kDebugLevelScriptPatcher, "ScriptPatcher", "Notifies when scripts are patched");
DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging");
DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging");
DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game");
@@ -224,6 +225,7 @@ Common::Error SciEngine::run() {
_gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering"));
_kernel = new Kernel(_resMan, segMan);
+ _kernel->init();
_features = new GameFeatures(segMan, _kernel);
// Only SCI0, SCI01 and SCI1 EGA games used a parser
@@ -881,8 +883,18 @@ void SciEngine::syncSoundSettings() {
}
}
+// used by Script Patcher. Used to find out, if Laura Bow 2 needs patching for Speech+Subtitles - or not
+bool SciEngine::speechAndSubtitlesEnabled() {
+ bool subtitlesOn = ConfMan.getBool("subtitles");
+ bool speechOn = !ConfMan.getBool("speech_mute");
+
+ if (subtitlesOn && speechOn)
+ return true;
+ return false;
+}
+
void SciEngine::syncIngameAudioOptions() {
- // Now, sync the in-game speech/subtitles settings for SCI1.1 CD games
+ // Sync the in-game speech/subtitles settings for SCI1.1 CD games
if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
bool subtitlesOn = ConfMan.getBool("subtitles");
bool speechOn = !ConfMan.getBool("speech_mute");
@@ -893,16 +905,19 @@ void SciEngine::syncIngameAudioOptions() {
_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2); // speech
} else if (subtitlesOn && speechOn) {
// Is it a game that supports simultaneous speech and subtitles?
- if (getGameId() == GID_SQ4
- || getGameId() == GID_FREDDYPHARKAS
- || getGameId() == GID_ECOQUEST
- || getGameId() == GID_LSL6
+ switch (_gameId) {
+ case GID_SQ4:
+ case GID_FREDDYPHARKAS:
+ case GID_ECOQUEST:
+ case GID_LSL6:
// TODO: The following need script patches for simultaneous speech and subtitles
- //|| getGameId() == GID_KQ6
- //|| getGameId() == GID_LAURABOW2
- ) {
+ // GID_KQ6
_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3); // speech + subtitles
- } else {
+ break;
+ case GID_LAURABOW2:
+ // Laura Bow 2 gets patched when speech and subtitles are enabled
+ // It then does both, when the user has "speech" selected. That's why we select speech here
+ default:
// Game does not support speech and subtitles, set it to speech
_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2); // speech
}
@@ -910,6 +925,46 @@ void SciEngine::syncIngameAudioOptions() {
}
}
+void SciEngine::updateScummVMAudioOptions() {
+ // Update ScummVM's speech/subtitles settings for SCI1.1 CD games,
+ // depending on the in-game settings
+ if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
+ uint16 ingameSetting = _gamestate->variables[VAR_GLOBAL][90].getOffset();
+ bool subtitlesOn = ConfMan.getBool("subtitles");
+ bool speechOn = !ConfMan.getBool("speech_mute");
+
+ switch (ingameSetting) {
+ case 1:
+ // subtitles
+ ConfMan.setBool("subtitles", true);
+ ConfMan.setBool("speech_mute", true);
+ break;
+ case 2:
+ // speech
+ switch (_gameId) {
+ case GID_LAURABOW2:
+ // We don't sync "speech" for Laura Bow 2 in case the user choose "both" in the setting
+ // Because "speech" (2) within SCI means "speech + subtitles" for Laura Bow 2
+ if (subtitlesOn && speechOn)
+ return;
+ break;
+ default:
+ break;
+ }
+ ConfMan.setBool("subtitles", false);
+ ConfMan.setBool("speech_mute", false);
+ break;
+ case 3:
+ // speech + subtitles
+ ConfMan.setBool("subtitles", true);
+ ConfMan.setBool("speech_mute", false);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
void SciEngine::loadMacExecutable() {
if (getPlatform() != Common::kPlatformMacintosh || getSciVersion() < SCI_VERSION_1_EARLY || getSciVersion() > SCI_VERSION_1_1)
return;
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 3b9844b326..c91606fbc9 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -82,28 +82,29 @@ class GfxFrameout;
// our engine debug levels
enum kDebugLevels {
- kDebugLevelError = 1 << 0,
- kDebugLevelNodes = 1 << 1,
- kDebugLevelGraphics = 1 << 2,
- kDebugLevelStrings = 1 << 3,
- kDebugLevelMemory = 1 << 4,
- kDebugLevelFuncCheck = 1 << 5,
- kDebugLevelBresen = 1 << 6,
- kDebugLevelSound = 1 << 7,
- kDebugLevelBaseSetter = 1 << 8,
- kDebugLevelParser = 1 << 9,
- kDebugLevelSaid = 1 << 10,
- kDebugLevelFile = 1 << 11,
- kDebugLevelTime = 1 << 12,
- kDebugLevelRoom = 1 << 13,
- kDebugLevelAvoidPath = 1 << 14,
- kDebugLevelDclInflate = 1 << 15,
- kDebugLevelVM = 1 << 16,
- kDebugLevelScripts = 1 << 17,
- kDebugLevelGC = 1 << 18,
- kDebugLevelResMan = 1 << 19,
- kDebugLevelOnStartup = 1 << 20,
- kDebugLevelDebugMode = 1 << 21
+ kDebugLevelError = 1 << 0,
+ kDebugLevelNodes = 1 << 1,
+ kDebugLevelGraphics = 1 << 2,
+ kDebugLevelStrings = 1 << 3,
+ kDebugLevelMemory = 1 << 4,
+ kDebugLevelFuncCheck = 1 << 5,
+ kDebugLevelBresen = 1 << 6,
+ kDebugLevelSound = 1 << 7,
+ kDebugLevelBaseSetter = 1 << 8,
+ kDebugLevelParser = 1 << 9,
+ kDebugLevelSaid = 1 << 10,
+ kDebugLevelFile = 1 << 11,
+ kDebugLevelTime = 1 << 12,
+ kDebugLevelRoom = 1 << 13,
+ kDebugLevelAvoidPath = 1 << 14,
+ kDebugLevelDclInflate = 1 << 15,
+ kDebugLevelVM = 1 << 16,
+ kDebugLevelScripts = 1 << 17,
+ kDebugLevelGC = 1 << 18,
+ kDebugLevelResMan = 1 << 19,
+ kDebugLevelOnStartup = 1 << 20,
+ kDebugLevelDebugMode = 1 << 21,
+ kDebugLevelScriptPatcher = 1 << 22
};
enum SciGameId {
@@ -138,6 +139,7 @@ enum SciGameId {
GID_KQ5,
GID_KQ6,
GID_KQ7,
+ GID_KQUESTIONS,
GID_LAURABOW,
GID_LAURABOW2,
GID_LIGHTHOUSE,
@@ -243,13 +245,15 @@ public:
* and we add this functionality in ScummVM:
* - Space Quest 4 CD
* - Freddy Pharkas CD
+ * - Laura Bow 2 CD
* SCI1.1 games which don't support simultaneous speech and subtitles,
* and we haven't added any extra functionality in ScummVM because extra
* script patches are needed:
- * - Laura Bow 2 CD
* - King's Quest 6 CD
*/
+ bool speechAndSubtitlesEnabled();
void syncIngameAudioOptions();
+ void updateScummVMAudioOptions();
const SciGameId &getGameId() const { return _gameId; }
const char *getGameIdStr() const;
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 9546b1503f..186fc18a5c 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -20,6 +20,9 @@
*
*/
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+
#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/sound/midiparser_sci.h"
@@ -53,10 +56,6 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
_masterVolume = 15;
_volume = 127;
- _signalSet = false;
- _signalToSet = 0;
- _dataincAdd = false;
- _dataincToAdd = 0;
_resetOnPause = false;
_pSnd = 0;
}
@@ -439,20 +438,6 @@ void MidiParser_SCI::sendToDriver(uint32 midi) {
}
void MidiParser_SCI::parseNextEvent(EventInfo &info) {
- // Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs
- if (_dataincAdd) {
- _dataincAdd = false;
- _pSnd->dataInc += _dataincToAdd;
- _pSnd->signal = 0x7f + _pSnd->dataInc;
- debugC(4, kDebugLevelSound, "datainc %04x", _dataincToAdd);
- }
- if (_signalSet) {
- _signalSet = false;
- _pSnd->setSignal(_signalToSet);
-
- debugC(4, kDebugLevelSound, "signal %04x", _signalToSet);
- }
-
info.start = _position._playPos;
info.delta = 0;
while (*_position._playPos == 0xF8) {
@@ -474,6 +459,79 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
case 0xC:
info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
+ break;
+ case 0xD:
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = 0;
+ break;
+
+ case 0xB:
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
+ info.length = 0;
+ break;
+
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xE:
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
+ if (info.command() == 0x9 && info.basic.param2 == 0)
+ info.event = info.channel() | 0x80;
+ info.length = 0;
+ break;
+
+ case 0xF: // System Common, Meta or SysEx event
+ switch (info.event & 0x0F) {
+ case 0x2: // Song Position Pointer
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
+ break;
+
+ case 0x3: // Song Select
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = 0;
+ break;
+
+ case 0x6:
+ case 0x8:
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xE:
+ info.basic.param1 = info.basic.param2 = 0;
+ break;
+
+ case 0x0: // SysEx
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
+ break;
+
+ case 0xF: // META event
+ info.ext.type = *(_position._playPos++);
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
+ break;
+ default:
+ warning(
+ "MidiParser_SCI::parseNextEvent: Unsupported event code %x",
+ info.event);
+ } // // System Common, Meta or SysEx event
+ }// switch (info.command())
+}
+
+void MidiParser_SCI::processEvent(const EventInfo &info, bool fireEvents) {
+ if (!fireEvents) {
+ // We don't do any processing that should be done while skipping events
+ MidiParser::processEvent(info, fireEvents);
+ return;
+ }
+
+ switch (info.command()) {
+ case 0xC:
if (info.channel() == 0xF) {// SCI special case
if (info.basic.param1 != kSetSignalLoop) {
// At least in kq5/french&mac the first scene in the intro has
@@ -486,25 +544,47 @@ 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.
- if (_soundVersion <= SCI_VERSION_0_LATE ||
- _position._playTick || info.delta) {
- _signalSet = true;
- _signalToSet = info.basic.param1;
+ // 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.
+ bool skipSignal = false;
+ if (_soundVersion >= SCI_VERSION_1_EARLY) {
+ if (!_position._playTick) {
+ skipSignal = true;
+ switch (g_sci->getGameId()) {
+ case GID_ECOQUEST2:
+ // In Eco Quest 2 room 530 - gonzales is supposed to dance
+ // WORKAROUND: we need to signal in this case on tick 0
+ // this whole issue is complicated and can only be properly fixed by
+ // changing the whole parser to a per-channel parser. SSCI seems to
+ // start each channel at offset 13 (may be 10 for us) and only
+ // starting at offset 0 when the music loops to the initial position.
+ if (g_sci->getEngineState()->currentRoomNumber() == 530)
+ skipSignal = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (!skipSignal) {
+ if (!_jumpingToTick) {
+ _pSnd->setSignal(info.basic.param1);
+ debugC(4, kDebugLevelSound, "signal %04x", info.basic.param1);
+ }
}
} else {
- _loopTick = _position._playTick + info.delta;
+ _loopTick = _position._playTick;
}
+
+ // Done with this event.
+ return;
}
- break;
- case 0xD:
- info.basic.param1 = *(_position._playPos++);
- info.basic.param2 = 0;
- break;
+ // Break to let parent handle the rest.
+ break;
case 0xB:
- info.basic.param1 = *(_position._playPos++);
- info.basic.param2 = *(_position._playPos++);
-
// Reference for some events:
// http://wiki.scummvm.org/index.php/SCI/Specifications/Sound/SCI0_Resource_Format#Status_Reference
// Handle common special events
@@ -526,43 +606,48 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
switch (info.basic.param1) {
case kSetReverb:
// Already handled above
- break;
+ return;
case kMidiHold:
// 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.
if (info.basic.param2 == _pSnd->hold) {
- uint32 extraDelta = info.delta;
jumpToTick(_loopTick, false, false);
- _nextEvent.delta += extraDelta;
+ // Done with this event.
+ return;
}
- break;
+ return;
case kUpdateCue:
- _dataincAdd = true;
- switch (_soundVersion) {
- case SCI_VERSION_0_EARLY:
- case SCI_VERSION_0_LATE:
- _dataincToAdd = info.basic.param2;
- break;
- case SCI_VERSION_1_EARLY:
- case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1:
- _dataincToAdd = 1;
- break;
- default:
- error("unsupported _soundVersion");
+ if (!_jumpingToTick) {
+ int inc;
+ switch (_soundVersion) {
+ case SCI_VERSION_0_EARLY:
+ case SCI_VERSION_0_LATE:
+ inc = info.basic.param2;
+ break;
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ case SCI_VERSION_2_1:
+ inc = 1;
+ break;
+ default:
+ error("unsupported _soundVersion");
+ }
+ _pSnd->dataInc += inc;
+ debugC(4, kDebugLevelSound, "datainc %04x", inc);
+
}
- break;
+ return;
case kResetOnPause:
_resetOnPause = info.basic.param2;
- break;
+ return;
// Unhandled SCI commands
case 0x46: // LSL3 - binoculars
case 0x61: // Iceman (AdLib?)
case 0x73: // Hoyle
case 0xD1: // KQ4, when riding the unicorn
// Obscure SCI commands - ignored
- break;
+ return;
// Standard MIDI commands
case 0x01: // mod wheel
case 0x04: // foot controller
@@ -577,84 +662,49 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
case 0x4B: // voice mapping
// TODO: is any support for this needed at the MIDI parser level?
warning("Unhanded SCI MIDI command 0x%x - voice mapping (parameter %d)", info.basic.param1, info.basic.param2);
- break;
+ return;
default:
warning("Unhandled SCI MIDI command 0x%x (parameter %d)", info.basic.param1, info.basic.param2);
- break;
+ return;
}
+
}
- info.length = 0;
- break;
- case 0x8:
- case 0x9:
- case 0xA:
- case 0xE:
- info.basic.param1 = *(_position._playPos++);
- info.basic.param2 = *(_position._playPos++);
- if (info.command() == 0x9 && info.basic.param2 == 0)
- info.event = info.channel() | 0x80;
- info.length = 0;
+ // Break to let parent handle the rest.
break;
+ case 0xF: // META event
+ if (info.ext.type == 0x2F) {// end of track reached
+ if (_pSnd->loop)
+ _pSnd->loop--;
+ // QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold,
+ // but sometimes there's no hold marker in the associated songs
+ // (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) {
+ jumpToTick(_loopTick);
+
+ // Done with this event.
+ return;
- case 0xF: // System Common, Meta or SysEx event
- switch (info.event & 0x0F) {
- case 0x2: // Song Position Pointer
- info.basic.param1 = *(_position._playPos++);
- info.basic.param2 = *(_position._playPos++);
- break;
+ } else {
+ _pSnd->status = kSoundStopped;
+ _pSnd->setSignal(SIGNAL_OFFSET);
- case 0x3: // Song Select
- info.basic.param1 = *(_position._playPos++);
- info.basic.param2 = 0;
- break;
+ debugC(4, kDebugLevelSound, "signal EOT");
+ }
+ }
- case 0x6:
- case 0x8:
- case 0xA:
- case 0xB:
- case 0xC:
- case 0xE:
- info.basic.param1 = info.basic.param2 = 0;
- break;
+ // Break to let parent handle the rest.
+ break;
- case 0x0: // SysEx
- info.length = readVLQ(_position._playPos);
- info.ext.data = _position._playPos;
- _position._playPos += info.length;
- break;
+ default:
+ // Break to let parent handle the rest.
+ break;
+ }
- case 0xF: // META event
- info.ext.type = *(_position._playPos++);
- info.length = readVLQ(_position._playPos);
- info.ext.data = _position._playPos;
- _position._playPos += info.length;
- if (info.ext.type == 0x2F) {// end of track reached
- if (_pSnd->loop)
- _pSnd->loop--;
- // QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold,
- // but sometimes there's no hold marker in the associated songs
- // (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...
- uint32 extraDelta = info.delta;
- jumpToTick(_loopTick);
- _nextEvent.delta += extraDelta;
- } else {
- _pSnd->status = kSoundStopped;
- _pSnd->setSignal(SIGNAL_OFFSET);
-
- debugC(4, kDebugLevelSound, "signal EOT");
- }
- }
- break;
- default:
- warning(
- "MidiParser_SCI::parseNextEvent: Unsupported event code %x",
- info.event);
- } // // System Common, Meta or SysEx event
- }// switch (info.command())
+
+ // Let parent handle the rest
+ MidiParser::processEvent(info, fireEvents);
}
byte MidiParser_SCI::getSongReverb() {
diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h
index d3fd337644..5784dca1ab 100644
--- a/engines/sci/sound/midiparser_sci.h
+++ b/engines/sci/sound/midiparser_sci.h
@@ -89,6 +89,7 @@ public:
protected:
void parseNextEvent(EventInfo &info);
+ void processEvent(const EventInfo &info, bool fireEvents = true);
byte *midiMixChannels();
byte *midiFilterChannels(int channelMask);
byte midiGetNextChannel(long ticker);
@@ -106,10 +107,6 @@ protected:
byte _masterVolume; // the overall master volume (same for all tracks)
byte _volume; // the global volume of the current track
- bool _signalSet;
- int16 _signalToSet;
- bool _dataincAdd;
- int16 _dataincToAdd;
bool _resetOnPause;
bool _channelUsed[16];
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 913ba32cba..8c6d0d6431 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -519,9 +519,10 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
if (pSnd->status == kSoundStopped)
pSnd->pMidiParser->jumpToTick(0);
- else
+ else {
// Fast forward to the last position and perform associated events when loading
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true, true, true);
+ }
// Restore looping and hold
pSnd->loop = prevLoop;
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index 1f798c90d7..40236c8445 100644
--- a/engines/sci/sound/music.h
+++ b/engines/sci/sound/music.h
@@ -69,7 +69,7 @@ public:
uint16 dataInc;
uint16 ticker;
uint16 signal;
- byte priority;
+ int16 priority; // must be int16, at least in Laura Bow 1, main music (object conMusic) uses priority -1
uint16 loop;
int16 volume;
int16 hold;
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index daba976f50..aa2a309f4d 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -116,7 +116,10 @@ void SoundCommandParser::processInitSound(reg_t obj) {
newSound->resourceId = resourceId;
newSound->soundObj = obj;
newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
- newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)) & 0xFF;
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
+ else
+ newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)) & 0xFF;
if (_soundVersion >= SCI_VERSION_1_EARLY)
newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX);
newSound->reverb = -1; // initialize to SCI invalid, it'll be set correctly in soundInitSnd() below
@@ -428,7 +431,7 @@ reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) {
int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255);
if (objVol != musicSlot->volume)
_music->soundSetVolume(musicSlot, objVol);
- uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority));
+ int16 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority));
if (objPrio != musicSlot->priority)
_music->soundSetPriority(musicSlot, objPrio);
return acc;
@@ -505,9 +508,19 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
// fireworks).
// It is also needed in other games, e.g. LSL6 when talking to the
// receptionist (bug #3192166).
- // CHECKME: At least kq5cd/win and kq6 set signal to 0xFE here, but
- // kq5cd/dos does not set signal at all. Needs more investigation.
- writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ // TODO: More thorougly check the different SCI version:
+ // * SCI1late sets signal to 0xFE here. (With signal 0xFF
+ // duplicate music plays in LauraBow2CD - bug #6462)
+ // SCI1middle LSL1 1.000.510 does not have the 0xFE;
+ // SCI1late CastleDrBrain demo 1.000.005 does have the 0xFE.
+ // * Other SCI1 games seem to rely on processStopSound to set the signal
+ // * Need to check SCI0 behaviour.
+ uint16 sig;
+ if (getSciVersion() >= SCI_VERSION_1_LATE)
+ sig = 0xFFFE;
+ else
+ sig = SIGNAL_OFFSET;
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), sig);
if (_soundVersion <= SCI_VERSION_0_LATE) {
processStopSound(obj, false);
} else {
@@ -530,17 +543,21 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
}
reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) {
+ // The 4 parameter variant of this call is used in at least LSL1VGA, room
+ // 110 (Lefty's bar), to distort the music when Larry is drunk and stands
+ // up - bug #3614447.
reg_t obj = argv[0];
byte channel = argv[1].toUint16() & 0xf;
- byte midiCmd = argv[2].toUint16() & 0xff;
+ byte midiCmd = (argc == 5) ? argv[2].toUint16() & 0xff : 0xB0; // 0xB0: controller
+ uint16 controller = (argc == 5) ? argv[3].toUint16() : argv[2].toUint16();
+ uint16 param = (argc == 5) ? argv[4].toUint16() : argv[3].toUint16();
- // TODO: first there is a 4-parameter variant of this call which needs to get reversed
- // second the current code isn't 100% accurate, sierra sci does checks on the 4th parameter
- if (argc == 4)
- return acc;
-
- uint16 controller = argv[3].toUint16();
- uint16 param = argv[4].toUint16();
+ if (argc == 4 && controller == 0xFF) {
+ midiCmd = 0xE0; // 0xE0: pitch wheel
+ uint16 pitch = CLIP<uint16>(argv[3].toSint16() + 0x2000, 0x0000, 0x3FFF);
+ controller = pitch & 0x7F;
+ param = pitch >> 7;
+ }
debugC(kDebugLevelSound, "kDoSound(sendMidi): %04x:%04x, %d, %d, %d, %d", PRINT_REG(obj), channel, midiCmd, controller, param);
if (channel)
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index 0337a8d306..a567ece2ea 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -210,7 +210,7 @@ void RobotDecoder::readNextPacket() {
// Copy over the decompressed frame
byte *inFrame = decompressedFrame;
- byte *outFrame = (byte *)surface->pixels;
+ byte *outFrame = (byte *)surface->getPixels();
// Black out the surface
memset(outFrame, 0, surface->w * surface->h);
diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp
index a7b6346eca..54603ec1f1 100644
--- a/engines/sci/video/seq_decoder.cpp
+++ b/engines/sci/video/seq_decoder.cpp
@@ -119,7 +119,7 @@ const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() {
_fileStream->seek(offset);
if (frameType == kSeqFrameFull) {
- byte *dst = (byte *)_surface->pixels + frameTop * SEQ_SCREEN_WIDTH + frameLeft;
+ byte *dst = (byte *)_surface->getBasePtr(frameLeft, frameTop);
byte *linebuf = new byte[frameWidth];
@@ -133,7 +133,7 @@ const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() {
} else {
byte *buf = new byte[frameSize];
_fileStream->read(buf, frameSize);
- decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->pixels + SEQ_SCREEN_WIDTH * frameTop, frameLeft, frameWidth, frameHeight, colorKey);
+ decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->getBasePtr(0, frameTop), frameLeft, frameWidth, frameHeight, colorKey);
delete[] buf;
}
diff --git a/engines/scumm/POTFILES b/engines/scumm/POTFILES
new file mode 100644
index 0000000000..6034320259
--- /dev/null
+++ b/engines/scumm/POTFILES
@@ -0,0 +1,3 @@
+engines/scumm/dialogs.cpp
+engines/scumm/help.cpp
+engines/scumm/scumm.cpp
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 5c148a7b57..4e14473921 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -1485,7 +1485,7 @@ void ScummEngine::playActorSounds() {
int sound;
for (i = 1; i < _numActors; i++) {
- if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom() && _actors[i]->_sound) {
+ if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom()) {
_currentScript = 0xFF;
if (_game.version == 0) {
sound = v0ActorSounds[i - 1] & 0x3F;
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index b6acf01050..481c4af432 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -994,7 +994,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
if (_draw_bottom < rect.bottom)
_draw_bottom = rect.bottom;
- v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bytesPerPixel;
+ v1.destptr = (byte *)_out.getBasePtr(v1.x, v1.y);
codec1_genericDecode(v1);
@@ -1288,7 +1288,7 @@ byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) {
int32 numskip_before = skip_x + (skip_y * _width);
int32 numskip_after = _width - cur_x;
- byte *dst = (byte *)_out.pixels + height_unk * _out.pitch + width_unk * _vm->_bytesPerPixel;
+ byte *dst = (byte *)_out.getBasePtr(width_unk, height_unk);
akos16Decompress(dst, _out.pitch, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, transparency, clip.left, clip.top, _zbuf);
return 0;
@@ -1358,7 +1358,7 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) {
palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768;
}
- byte *dstPtr = (byte *)_out.pixels + dst.top * _out.pitch + dst.left * _vm->_bytesPerPixel;
+ byte *dstPtr = (byte *)_out.getBasePtr(dst.left, dst.top);
if (_shadow_mode == 3) {
Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, xmap, _vm->_bytesPerPixel);
} else {
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 46c68c81b0..e1a8688bb9 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -32,13 +32,15 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const
_out = vs;
if (drawToBackBuf)
- _out.pixels = vs.getBackPixels(0, 0);
+ _out.setPixels(vs.getBackPixels(0, 0));
else
- _out.pixels = vs.getPixels(0, 0);
+ _out.setPixels(vs.getPixels(0, 0));
_actorX += _vm->_virtscr[kMainVirtScreen].xstart & 7;
_out.w = _out.pitch / _vm->_bytesPerPixel;
- _out.pixels = (byte *)_out.pixels - (_vm->_virtscr[kMainVirtScreen].xstart & 7);
+ // We do not use getBasePtr here because the offset to pixels never used
+ // _vm->_bytesPerPixel, but it seems unclear why.
+ _out.setPixels((byte *)_out.getPixels() - (_vm->_virtscr[kMainVirtScreen].xstart & 7));
_numStrips = numStrips;
diff --git a/engines/scumm/bomp.cpp b/engines/scumm/bomp.cpp
index 845cf70722..5b87f3042c 100644
--- a/engines/scumm/bomp.cpp
+++ b/engines/scumm/bomp.cpp
@@ -231,7 +231,10 @@ void drawBomp(const BompDrawData &bd) {
}
src = bd.src;
- dst = (byte *)bd.dst.pixels + bd.y * bd.dst.pitch + (bd.x + clip.left);
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ dst = (byte *)const_cast<void *>(bd.dst.getBasePtr((bd.x + clip.left), bd.y));
const byte maskbit = revBitMask((bd.x + clip.left) & 7);
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 9ae75b6683..dd79aff2da 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -799,7 +799,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
if (ignoreCharsetMask || !vs->hasTwoBuffers) {
dstPtr = vs->getPixels(0, 0);
} else {
- dstPtr = (byte *)_vm->_textSurface.pixels;
+ dstPtr = (byte *)_vm->_textSurface.getPixels();
}
if (_blitAlso && vs->hasTwoBuffers) {
@@ -829,7 +829,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
dstPtr = vs->getPixels(_left, drawTop);
} else {
dstSurface = _vm->_textSurface;
- dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;
+ dstPtr = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier);
}
if (_blitAlso && vs->hasTwoBuffers) {
@@ -907,7 +907,7 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) {
void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) {
if (!prepareDraw(chr))
return;
- byte *dst = (byte *)s.pixels + y * s.pitch + x;
+ byte *dst = (byte *)s.getBasePtr(x, y);
drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
}
@@ -1242,7 +1242,7 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
if (ignoreCharsetMask) {
VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
s = *vs;
- s.pixels = vs->getPixels(0, 0);
+ s.setPixels(vs->getPixels(0, 0));
} else {
s = _vm->_textSurface;
drawTop -= _vm->_screenTop;
@@ -1401,7 +1401,7 @@ void CharsetRendererTownsClassic::drawBitsN(const Graphics::Surface&, byte *dst,
}
bool scale2x = (_vm->_textSurfaceMultiplier == 2);
- dst = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;
+ dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier);
int y, x;
int color;
diff --git a/engines/scumm/configure.engine b/engines/scumm/configure.engine
new file mode 100644
index 0000000000..e1de788061
--- /dev/null
+++ b/engines/scumm/configure.engine
@@ -0,0 +1,5 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine scumm "SCUMM" yes "scumm_7_8 he" "v0-v6 games"
+add_engine scumm_7_8 "v7 & v8 games" yes
+add_engine he "HE71+ games" yes
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 4ebdd00fdc..85c60f9a40 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -293,7 +293,7 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
return 2;
}
- v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bytesPerPixel;
+ v1.destptr = (byte *)_out.getBasePtr(v1.x, v1.y);
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf);
@@ -826,7 +826,7 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) {
int my = _actorY + y + ty;
int mx = _actorX + x + tx;
if (!(_zbuf && (maskBuf[my * _numStrips + mx / 8] & revBitMask(mx & 7))))
- *((byte *)_out.pixels + my * _out.pitch + mx) = palette[c];
+ *((byte *)_out.getBasePtr(mx, my)) = palette[c];
}
}
}
@@ -1238,7 +1238,7 @@ byte V0CostumeRenderer::drawLimb(const Actor *a, int limb) {
int destY = ypos + y;
if (destY >= 0 && destY < _out.h && destX >= 0 && destX < _out.w) {
- byte *dst = (byte *)_out.pixels + destY * _out.pitch + destX;
+ byte *dst = (byte *)_out.getBasePtr(destX, destY);
byte *mask = _vm->getMaskBuffer(0, destY, _zbuf);
if (a0->_limb_flipped[limb]) {
LINE(0, 0); LINE(2, 2); LINE(4, 4); LINE(6, 6);
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 269ae9e10a..721644b554 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -139,7 +139,7 @@ void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
return;
}
- setCursorFromBuffer((byte *)vs->pixels + (y - vs->topline) * vs->pitch + x, w, h, vs->pitch);
+ setCursorFromBuffer((byte *)vs->getBasePtr(x, y - vs->topline), w, h, vs->pitch);
}
void ScummEngine_v6::setDefaultCursor() {
@@ -417,13 +417,11 @@ void ScummEngine_v5::redefineBuiltinCursorFromChar(int index, int chr) {
Graphics::Surface s;
byte buf[16*17];
memset(buf, 123, 16*17);
- s.pixels = buf;
- s.w = _charset->getCharWidth(chr);
- s.h = _charset->getFontHeight();
- s.pitch = s.w;
+ s.init(_charset->getCharWidth(chr), _charset->getFontHeight(),
+ _charset->getCharWidth(chr), buf,
+ Graphics::PixelFormat::createFormatCLUT8());
// s.h = 17 for FM-TOWNS Loom Japanese. Fixes bug #1166917
assert(s.w <= 16 && s.h <= 17);
- s.format = Graphics::PixelFormat::createFormatCLUT8();
_charset->drawChar(chr, s, 0, 0);
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index 9b6dd1e687..872293f821 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -641,7 +641,7 @@ static void hlineColor(ScummEngine *scumm, int x1, int x2, int y, byte color) {
x2 = right - 1;
- ptr = (byte *)vs->pixels + x1 + y * vs->pitch;
+ ptr = (byte *)vs->getBasePtr(x1, y);
while (x1++ <= x2) {
*ptr++ = color;
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 170ca0993c..aa7e60930a 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -1223,8 +1223,8 @@ const char *ScummMetaEngine::getOriginalCopyright() const {
}
namespace Scumm {
- extern bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion);
-}
+bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion);
+} // End of namespace Scumm
int ScummMetaEngine::getMaximumSaveSlot() const { return 99; }
@@ -1262,25 +1262,21 @@ void ScummMetaEngine::removeSaveState(const char *target, int slot) const {
}
SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
- Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
-
- if (!in)
- return SaveStateDescriptor();
-
Common::String saveDesc;
- Scumm::getSavegameName(in, saveDesc, 0); // FIXME: heversion?!?
- delete in;
+ Graphics::Surface *thumbnail = nullptr;
+ SaveStateMetaInfos infos;
+ memset(&infos, 0, sizeof(infos));
+ SaveStateMetaInfos *infoPtr = &infos;
- // TODO: Cleanup
- Graphics::Surface *thumbnail = ScummEngine::loadThumbnailFromSlot(target, slot);
+ // FIXME: heversion?!?
+ if (!ScummEngine::querySaveMetaInfos(target, slot, 0, saveDesc, thumbnail, infoPtr)) {
+ return SaveStateDescriptor();
+ }
SaveStateDescriptor desc(slot, saveDesc);
desc.setThumbnail(thumbnail);
- SaveStateMetaInfos infos;
- memset(&infos, 0, sizeof(infos));
- if (ScummEngine::loadInfosFromSlot(target, slot, &infos)) {
+ if (infoPtr) {
int day = (infos.date >> 24) & 0xFF;
int month = (infos.date >> 16) & 0xFF;
int year = infos.date & 0xFFFF;
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index cb807997e9..6717ea9b06 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -299,7 +299,11 @@ static const GameSettings gameVariantsTable[] = {
// Changed o_getResourceSize to cover all resource types
{"farm", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
- {"puttzoo", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"puttzoo", "", 0, GID_PUTTZOO, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"puttzoo", "HE 72", 0, GID_PUTTZOO, 6, 72, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"puttzoo", "HE 98.5", 0, GID_PUTTZOO, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"puttzoo", "HE 99", 0, GID_PUTTZOO, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"puttzoo", "HE 100", 0, GID_PUTTZOO, 6, 100, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
// Added VAR_PLATFORM variable
{"jungle", "", 0, GID_HEGAME, 6, 74, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
@@ -385,7 +389,8 @@ static const GameSettings gameVariantsTable[] = {
{"Soccer2004", 0, 0, GID_SOCCER2004, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
// U32 code required, for testing only
- {"moonbase", 0, 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"moonbase", "1.0", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"moonbase", "1.1", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
{"moonbase", "Demo", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR | GF_DEMO, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
// HE100 games, which use older o72_debugInput code
@@ -758,6 +763,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 },
@@ -858,6 +864,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "puttzoo", "Zoo Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "puttzoo", "Putt-Putt Saves the Zoo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "puttzoo", "game", kGenHEPC, Common::EN_ANY, Common::kPlatformIOS, 0 },
+ { "puttzoo", "pp3_unlocked", kGenHEPC, Common::EN_ANY, Common::kPlatformWindows, 0 },
{ "SamsFunShop", "SamsFunShop", kGenHEPC, UNK_LANG, UNK, 0 },
{ "SamsFunShop", "Sam's FunShop", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 50ff0b3988..1bb4a28f65 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -421,8 +421,8 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int
}
_res->createResource(rtBuffer, slot + 1, size);
- vs->pixels = getResourceAddress(rtBuffer, slot + 1);
- memset(vs->pixels, 0, size); // reset background
+ vs->setPixels(getResourceAddress(rtBuffer, slot + 1));
+ memset(vs->getBasePtr(0, 0), 0, size); // reset background
if (twobufs) {
vs->backBuf = _res->createResource(rtBuffer, slot + 5, size);
@@ -612,7 +612,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
// Some paranoia checks
assert(top >= 0 && bottom <= vs->h);
assert(x >= 0 && width <= vs->pitch);
- assert(_textSurface.pixels);
+ assert(_textSurface.getPixels());
// Perform some clipping
if (width > vs->w - x)
@@ -1135,7 +1135,7 @@ void ScummEngine::clearTextSurface() {
_townsScreen->fillLayerRect(1, 0, 0, _textSurface.w, _textSurface.h, 0);
#endif
- fill((byte *)_textSurface.pixels, _textSurface.pitch,
+ fill((byte *)_textSurface.getPixels(), _textSurface.pitch,
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_game.platform == Common::kPlatformFMTowns ? 0 :
#endif
@@ -1590,7 +1590,7 @@ void GdiV2::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
if (vs->hasTwoBuffers)
dst = vs->backBuf + y * vs->pitch + x * 8;
else
- dst = (byte *)vs->pixels + y * vs->pitch + x * 8;
+ dst = (byte *)vs->getBasePtr(x * 8, y);
mask_ptr = getMaskBuffer(x, y, 1);
@@ -1769,11 +1769,8 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
// Check whether lights are turned on or not
const bool lightsOn = _vm->isLightOn();
- if (_vm->_game.features & GF_SMALL_HEADER) {
+ if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8) {
smap_ptr = ptr;
- } else if (_vm->_game.version == 8) {
- // Skip to the BSTR->WRAP->OFFS chunk
- smap_ptr = ptr + 24;
} else {
smap_ptr = _vm->findResource(MKTAG('S','M','A','P'), ptr);
assert(smap_ptr);
@@ -1827,7 +1824,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
if (vs->hasTwoBuffers)
dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
else
- dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
+ dstPtr = (byte *)vs->getBasePtr(x * 8, y);
transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr);
@@ -1836,7 +1833,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
transpStrip = true;
if (vs->hasTwoBuffers) {
- byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
+ byte *frontBuf = (byte *)vs->getBasePtr(x * 8, y);
if (lightsOn)
copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->format.bytesPerPixel);
else
@@ -1887,8 +1884,14 @@ bool Gdi::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width,
smapLen = READ_LE_UINT32(smap_ptr);
if (stripnr * 4 + 4 < smapLen)
offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 4);
+ } else if (_vm->_game.version == 8) {
+ smapLen = READ_BE_UINT32(smap_ptr + 4);
+ // Skip to the BSTR->WRAP->OFFS chunk
+ smap_ptr += 24;
+ if (stripnr * 4 + 8 < smapLen)
+ offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 8);
} else {
- smapLen = READ_BE_UINT32(smap_ptr);
+ smapLen = READ_BE_UINT32(smap_ptr + 4);
if (stripnr * 4 + 8 < smapLen)
offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 8);
}
@@ -2262,7 +2265,7 @@ void Gdi::resetBackground(int top, int bottom, int strip) {
vs->bdirty[strip] = bottom;
bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel;
- backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel;
+ backbuff_ptr = (byte *)vs->getBasePtr((strip + vs->xstart/8) * 8, top);
numLinesToProcess = bottom - top;
if (numLinesToProcess) {
diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp
index f86a4e56d5..0aed181afd 100644
--- a/engines/scumm/gfx_towns.cpp
+++ b/engines/scumm/gfx_towns.cpp
@@ -34,7 +34,7 @@ void ScummEngine::towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, in
if (width <= 0 || height <= 0)
return;
- assert(_textSurface.pixels);
+ assert(_textSurface.getPixels());
int m = _textSurfaceMultiplier;
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index be17a3b305..d01b456c8b 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -90,7 +90,7 @@ void MoviePlayer::copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint
if (!surface)
return;
- byte *src = (byte *)surface->pixels;
+ const byte *src = (const byte *)surface->getPixels();
if (_video->hasDirtyPalette())
_vm->setPaletteFromPtr(_video->getPalette(), 256);
@@ -119,7 +119,7 @@ void MoviePlayer::copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint
dst += y * pitch + x * 2;
do {
for (uint i = 0; i < w; i++) {
- uint16 color = *((uint16 *)src + i);
+ uint16 color = *((const uint16 *)src + i);
switch (dstType) {
case kDstScreen:
WRITE_UINT16(dst + i * 2, color);
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index fc5e4bcdf0..a674288775 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -628,7 +628,6 @@ public:
void parseEvents();
- bool _quit;
OSystem *_syst;
GameSettings _game;
diff --git a/engines/scumm/he/logic/moonbase.cpp b/engines/scumm/he/logic/moonbase.cpp
index fac2ea27ff..5b4618a4ad 100644
--- a/engines/scumm/he/logic/moonbase.cpp
+++ b/engines/scumm/he/logic/moonbase.cpp
@@ -39,6 +39,8 @@ public:
int LogicHEmoonbase::versionID() {
if (_vm->_game.features & GF_DEMO)
return -100;
+ else if (strcmp(_vm->_game.variant, "1.1") == 0)
+ return 110;
else
return 100;
}
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index b024154c7f..987f74957c 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -2148,7 +2148,7 @@ void ScummEngine_v100he::o100_systemOps() {
break;
case 132:
// Confirm shutdown
- quitGame();
+ confirmExitDialog();
break;
case 133:
quitGame();
diff --git a/engines/scumm/he/script_v70he.cpp b/engines/scumm/he/script_v70he.cpp
index adb2fcac2e..9259e0db2f 100644
--- a/engines/scumm/he/script_v70he.cpp
+++ b/engines/scumm/he/script_v70he.cpp
@@ -309,7 +309,7 @@ void ScummEngine_v70he::o70_systemOps() {
break;
case 160:
// Confirm shutdown
- quitGame();
+ confirmExitDialog();
break;
case 244:
quitGame();
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index b9f454de0f..42bf9a4bb6 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -158,7 +158,7 @@ int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
- if (ah == NULL || ah->data == NULL)
+ if (!ah)
error("readArray: invalid array %d (%d)", array, readVar(array));
if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) ||
@@ -1199,7 +1199,7 @@ void ScummEngine_v72he::o72_systemOps() {
break;
case 160:
// Confirm shutdown
- quitGame();
+ confirmExitDialog();
break;
case 244:
quitGame();
@@ -1779,8 +1779,11 @@ void ScummEngine_v72he::copyArray(int array1, int a1_dim2start, int a1_dim2end,
copyArrayHelper(ah, a1_dim2start, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize);
copyArrayHelper(ah, a2_dim2start, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize);
} else {
+ // start at the end, so we copy backwards (in case the indices overlap)
copyArrayHelper(ah, a1_dim2end, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize);
copyArrayHelper(ah, a2_dim2end, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize);
+ dstPitch = -dstPitch;
+ srcPitch = -srcPitch;
}
for (; a1_dim2start <= a1_dim2end; ++a1_dim2start) {
memcpy(dst, src, rowSize);
diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp
index eb62b650a4..ae43d714ad 100644
--- a/engines/scumm/he/script_v80he.cpp
+++ b/engines/scumm/he/script_v80he.cpp
@@ -23,7 +23,7 @@
#ifdef ENABLE_HE
#include "common/archive.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/config-manager.h"
#include "common/macresman.h"
#include "common/savefile.h"
@@ -180,7 +180,7 @@ void ScummEngine_v80he::o80_readConfigFile() {
}
} else {
// Normal Windows INI files
- Common::ConfigFile confFile;
+ Common::INIFile confFile;
if (!strcmp((char *)filename + r, "map.ini"))
confFile.loadFromFile((const char *)filename + r);
else
@@ -250,7 +250,7 @@ void ScummEngine_v80he::o80_writeConfigFile() {
memcpy(section, "BluesTreasureHunt-Disc2\0", 24);
}
- Common::ConfigFile ConfFile;
+ Common::INIFile ConfFile;
ConfFile.loadFromSaveFile((const char *)filename + r);
ConfFile.setKey((char *)option, (char *)section, (char *)string);
ConfFile.saveToSaveFile((const char *)filename + r);
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index a875702383..0e96952a48 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -46,7 +46,6 @@ namespace Scumm {
IMuseInternal::IMuseInternal() :
_native_mt32(false),
_enable_gs(false),
- _sc55(false),
_midi_adlib(NULL),
_midi_native(NULL),
_sysex(NULL),
@@ -495,12 +494,9 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
case IMuse::PROP_GS:
_enable_gs = (value > 0);
- // If True Roland MT-32 is not selected, run in GM or GS mode.
- // If it is selected, change the Roland GS synth to MT-32 mode.
- if (_midi_native && !_native_mt32)
- initGM(_midi_native);
- else if (_midi_native && _native_mt32 && _enable_gs) {
- _sc55 = true;
+ // GS Mode emulates MT-32 on a GS device, so _native_mt32 should always be true
+ if (_midi_native && _enable_gs) {
+ _native_mt32 = true;
initGM(_midi_native);
}
break;
@@ -1487,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
@@ -1499,7 +1495,7 @@ void IMuseInternal::initGM(MidiDriver *midi) {
if (_enable_gs) {
// All GS devices recognize the GS Reset command,
- // even with Roland's ID. It is impractical to
+ // even using Roland's ID. It is impractical to
// support other manufacturers' devices for
// further GS settings, as there are limitless
// numbers of them out there that would each
@@ -1514,29 +1510,27 @@ void IMuseInternal::initGM(MidiDriver *midi) {
debug(2, "GS SysEx: GS Reset");
_system->delayMillis(200);
- if (_sc55) {
- // This mode is for GS devices that support an MT-32-compatible
- // Map, such as the Roland Sound Canvas line of modules. It
- // will allow them to work with True MT-32 mode, but will
- // obviously still ignore MT-32 SysEx (and thus custom
- // instruments).
-
- // Set Channels 1-16 to SC-55 Map, then CM-64/32L Variation
- for (i = 0; i < 16; ++i) {
- midi->send((127 << 16) | (0 << 8) | (0xB0 | i));
- midi->send((1 << 16) | (32 << 8) | (0xB0 | i));
- midi->send((0 << 16) | (0 << 8) | (0xC0 | i));
- }
- debug(2, "GS Program Change: CM-64/32L Map Selected");
+ // 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);
+ debug(2, "GS SysEx: Master Tune set to 442.0kHz");
- // Set Percussion Channel to SC-55 Map (CC#32, 01H), then
- // Switch Drum Map to CM-64/32L (MT-32 Compatible Drums)
- midi->getPercussionChannel()->controlChange(0, 0);
- midi->getPercussionChannel()->controlChange(32, 1);
- midi->send(127 << 8 | 0xC0 | 9);
- debug(2, "GS Program Change: Drum Map is CM-64/32L");
+ // Note: All Roland GS devices support CM-64/32L maps
+ // Set Channels 1-16 to SC-55 Map, then CM-64/32L Variation
+ for (i = 0; i < 16; ++i) {
+ midi->send((127 << 16) | (0 << 8) | (0xB0 | i));
+ midi->send((1 << 16) | (32 << 8) | (0xB0 | i));
+ midi->send((0 << 16) | (0 << 8) | (0xC0 | i));
}
+ debug(2, "GS Program Change: CM-64/32L Map Selected");
+
+ // Set Percussion Channel to SC-55 Map (CC#32, 01H), then
+ // Switch Drum Map to CM-64/32L (MT-32 Compatible Drums)
+ midi->getPercussionChannel()->controlChange(0, 0);
+ midi->getPercussionChannel()->controlChange(32, 1);
+ midi->send(127 << 8 | 0xC0 | 9);
+ debug(2, "GS Program Change: Drum Map is CM-64/32L");
// Set Master Chorus to 0. The MT-32 has no chorus capability.
memcpy(&buffer[4], "\x40\x01\x3A\x00\x05", 5);
@@ -1546,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/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 6be564a517..d17d4ed28b 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -390,7 +390,6 @@ class IMuseInternal : public IMuse {
protected:
bool _native_mt32;
bool _enable_gs;
- bool _sc55;
MidiDriver *_midi_adlib;
MidiDriver *_midi_native;
TimerCallbackInfo _timer_info_adlib;
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index eb3717494f..a737539c44 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -275,9 +275,12 @@ void IMuseDigital::callback() {
feedSize &= ~1;
if (channels == 2)
feedSize &= ~3;
- } else {
+ } else if (bits == 8) {
if (channels == 2)
feedSize &= ~1;
+ } else {
+ warning("IMuseDigita::callback: Unexpected sample width, %d bits", bits);
+ continue;
}
if (feedSize == 0)
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index abd0d68e56..26e248fbca 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -443,11 +443,13 @@ ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::openSound(int32 soundId, const char
} else if (soundName[0] == 0) {
if (sound->bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0, header_outside) == 0 || ptr == NULL) {
closeSound(sound);
+ free(ptr);
return NULL;
}
} else {
if (sound->bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr, header_outside) == 0 || ptr == NULL) {
closeSound(sound);
+ free(ptr);
return NULL;
}
}
@@ -667,15 +669,18 @@ int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte
if (scumm_stricmp(fileName, soundDesc->lastFileName) != 0) {
int32 offs = 0, len = 0;
Common::SeekableReadStream *cmpFile;
+#if defined(USE_FLAC) || defined(USE_VORBIS) || defined(USE_MAD)
uint8 soundMode = 0;
+#endif
sprintf(fileName, "%s_reg%03d.fla", soundDesc->name, region);
cmpFile = soundDesc->bundle->getFile(fileName, offs, len);
if (len) {
#ifndef USE_FLAC
error("FLAC library compiled support needed");
-#endif
+#else
soundMode = 3;
+#endif
}
if (!len) {
sprintf(fileName, "%s_reg%03d.ogg", soundDesc->name, region);
@@ -683,8 +688,9 @@ int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte
if (len) {
#ifndef USE_VORBIS
error("Vorbis library compiled support needed");
-#endif
+#else
soundMode = 2;
+#endif
}
}
if (!len) {
@@ -693,8 +699,9 @@ int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte
if (len) {
#ifndef USE_MAD
error("Mad library compiled support needed");
-#endif
+#else
soundMode = 1;
+#endif
}
}
assert(len);
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..d711b63342 100644
--- a/engines/scumm/insane/insane_enemy.cpp
+++ b/engines/scumm/insane/insane_enemy.cpp
@@ -1519,8 +1519,7 @@ void Insane::chooseEnemyWeaponAnim(int32 buttons) {
case INV_BOOT:
case INV_HAND:
case INV_DUST:
- _actor[1].act[2].state = 0;
- switchEnemyWeapon();
+ // fallthrough
default:
switchEnemyWeapon();
}
@@ -2437,6 +2436,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/module.mk b/engines/scumm/module.mk
index 28884d7f78..d43db1e5f1 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -35,22 +35,23 @@ MODULE_OBJS := \
midiparser_ro.o \
object.o \
palette.o \
- player_apple2.o \
- player_mac.o \
- player_mod.o \
- player_nes.o \
- player_pce.o \
- player_sid.o \
- player_towns.o \
- player_v1.o \
- player_v2.o \
- player_v2a.o \
- player_v2base.o \
- player_v2cms.o \
- player_v3a.o \
- player_v3m.o \
- player_v4a.o \
- player_v5m.o \
+ players/player_ad.o \
+ players/player_apple2.o \
+ players/player_mac.o \
+ players/player_mod.o \
+ players/player_nes.o \
+ players/player_pce.o \
+ players/player_sid.o \
+ players/player_towns.o \
+ players/player_v1.o \
+ players/player_v2.o \
+ players/player_v2a.o \
+ players/player_v2base.o \
+ players/player_v2cms.o \
+ players/player_v3a.o \
+ players/player_v3m.o \
+ players/player_v4a.o \
+ players/player_v5m.o \
resource_v2.o \
resource_v3.o \
resource_v4.o \
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index 048b29d68b..d9f0b412e1 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -357,7 +357,10 @@ void NutRenderer::drawFrame(byte *dst, int c, int x, int y) {
}
void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color) {
- byte *dst = (byte *)s.pixels + y * s.pitch + x;
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y));
const int width = MIN((int)_chars[c].width, s.w - x);
const int height = MIN((int)_chars[c].height, s.h - y);
const byte *src = unpackChar(c);
@@ -391,7 +394,10 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt
}
void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) {
- byte *dst = (byte *)s.pixels + y * s.pitch + x;
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y));
const int width = _vm->_2byteWidth;
const int height = MIN(_vm->_2byteHeight, s.h - y);
const byte *src = _vm->get2byteCharPtr(c);
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index ed77a863cd..d266183f85 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -1715,7 +1715,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
error("object %d is not a blast object", eo->number);
bdd.dst = *vs;
- bdd.dst.pixels = vs->getPixels(0, 0);
+ bdd.dst.setPixels(vs->getPixels(0, 0));
bdd.x = eo->rect.left;
bdd.y = eo->rect.top;
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
new file mode 100644
index 0000000000..20630e1cb9
--- /dev/null
+++ b/engines/scumm/players/player_ad.cpp
@@ -0,0 +1,959 @@
+/* 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 "scumm/players/player_ad.h"
+#include "scumm/imuse/imuse.h"
+#include "scumm/scumm.h"
+#include "scumm/resource.h"
+
+#include "audio/fmopl.h"
+
+#include "common/textconsole.h"
+#include "common/config-manager.h"
+
+namespace Scumm {
+
+#define AD_CALLBACK_FREQUENCY 472
+
+Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
+ : _vm(scumm), _mixer(mixer), _rate(mixer->getOutputRate()) {
+ _opl2 = OPL::Config::create();
+ if (!_opl2->init(_rate)) {
+ error("Could not initialize OPL2 emulator");
+ }
+
+ _samplesPerCallback = _rate / AD_CALLBACK_FREQUENCY;
+ _samplesPerCallbackRemainder = _rate % AD_CALLBACK_FREQUENCY;
+ _samplesTillCallback = 0;
+ _samplesTillCallbackRemainder = 0;
+
+ memset(_registerBackUpTable, 0, sizeof(_registerBackUpTable));
+ writeReg(0x01, 0x00);
+ writeReg(0xBD, 0x00);
+ writeReg(0x08, 0x00);
+ writeReg(0x01, 0x20);
+
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ _engineMusicTimer = 0;
+ _soundPlaying = -1;
+
+ _curOffset = 0;
+
+ _sfxTimer = 4;
+ _rndSeed = 1;
+
+ memset(_channels, 0, sizeof(_channels));
+ memset(_sfxResource, 0, sizeof(_sfxResource));
+ memset(_sfxPriority, 0, sizeof(_sfxPriority));
+}
+
+Player_AD::~Player_AD() {
+ _mixer->stopHandle(_soundHandle);
+
+ stopAllSounds();
+ Common::StackLock lock(_mutex);
+ delete _opl2;
+ _opl2 = 0;
+}
+
+void Player_AD::setMusicVolume(int vol) {
+ // HACK: We ignore the parameter and set up the volume specified in the
+ // config manager. This allows us to differentiate between music and sfx
+ // volume changes.
+ setupVolume();
+}
+
+void Player_AD::startSound(int sound) {
+ Common::StackLock lock(_mutex);
+
+ // Query the sound resource
+ const byte *res = _vm->getResourceAddress(rtSound, sound);
+
+ if (res[2] == 0x80) {
+ // Stop the current sounds
+ stopAllSounds();
+
+ // Lock the new music resource
+ _soundPlaying = sound;
+ _vm->_res->lock(rtSound, _soundPlaying);
+
+ // Start the new music resource
+ _resource = res;
+ startMusic();
+ } else {
+ // Only try to start a sfx when no music is playing.
+ if (_soundPlaying == -1) {
+ const byte priority = res[0];
+ const byte channel = res[1];
+
+ // Check for out of bounds access
+ if (channel >= 3) {
+ warning("AdLib sfx resource %d uses channel %d", sound, channel);
+ return;
+ }
+
+ // Check whether the channel is free or the priority of the new
+ // sfx resource is above the old one.
+ if (_channels[channel * 3 + 0].state
+ || _channels[channel * 3 + 1].state
+ || _channels[channel * 3 + 2].state) {
+ if (_sfxPriority[channel] > priority) {
+ return;
+ }
+ }
+
+ // Lock the new resource
+ _sfxResource[channel] = sound;
+ _sfxPriority[channel] = priority;
+ _vm->_res->lock(rtSound, sound);
+
+ // Start the actual sfx resource
+ _resource = res;
+ startSfx();
+ }
+ }
+
+ // Setup the sound volume
+ setupVolume();
+}
+
+void Player_AD::stopSound(int sound) {
+ Common::StackLock lock(_mutex);
+
+ if (sound == _soundPlaying) {
+ stopAllSounds();
+ } else {
+ for (int i = 0; i < 3; ++i) {
+ if (_sfxResource[i] == sound) {
+ if (_channels[i * 3 + 0].state
+ || _channels[i * 3 + 1].state
+ || _channels[i * 3 + 2].state) {
+ // Unlock the sound resource
+ _vm->_res->unlock(rtSound, sound);
+
+ // Stop the actual sfx playback
+ _channels[i * 3 + 0].state = 0;
+ _channels[i * 3 + 1].state = 0;
+ _channels[i * 3 + 2].state = 0;
+ clearChannel(i * 3 + 0);
+ clearChannel(i * 3 + 1);
+ clearChannel(i * 3 + 2);
+ }
+ }
+ }
+ }
+}
+
+void Player_AD::stopAllSounds() {
+ Common::StackLock lock(_mutex);
+
+ // Unlock the music resource if present
+ if (_soundPlaying != -1) {
+ _vm->_res->unlock(rtSound, _soundPlaying);
+ _soundPlaying = -1;
+ }
+
+ // Stop the music playback
+ _curOffset = 0;
+
+ // Unloack all used sfx resources
+ for (int i = 0; i < 3; ++i) {
+ if (_channels[i * 3 + 0].state || _channels[i * 3 + 1].state || _channels[i * 3 + 2].state) {
+ _vm->_res->unlock(rtSound, _sfxResource[i]);
+ }
+ }
+
+ // Reset all the sfx channels
+ for (int i = 0; i < 9; ++i) {
+ _channels[i].state = 0;
+ clearChannel(i);
+ }
+
+ writeReg(0xBD, 0x00);
+}
+
+int Player_AD::getMusicTimer() {
+ return _engineMusicTimer;
+}
+
+int Player_AD::getSoundStatus(int sound) const {
+ return (sound == _soundPlaying);
+}
+
+void Player_AD::saveLoadWithSerializer(Serializer *ser) {
+ Common::StackLock lock(_mutex);
+
+ if (ser->getVersion() < VER(95)) {
+ IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL);
+ dummyImuse->save_or_load(ser, _vm, false);
+ delete dummyImuse;
+ return;
+ }
+
+ // TODO: Be nicer than the original and save the data to continue the
+ // currently played sound resources on load?
+}
+
+int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock lock(_mutex);
+
+ int len = numSamples;
+
+ while (len > 0) {
+ if (!_samplesTillCallback) {
+ // Run the update callback for music or sfx depending on which is
+ // active.
+ if (_curOffset) {
+ updateMusic();
+ } else {
+ updateSfx();
+ }
+
+ _samplesTillCallback = _samplesPerCallback;
+ _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
+ if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) {
+ ++_samplesTillCallback;
+ _samplesTillCallbackRemainder -= AD_CALLBACK_FREQUENCY;
+ }
+ }
+
+ const int samplesToRead = MIN(len, _samplesTillCallback);
+ _opl2->readBuffer(buffer, samplesToRead);
+
+ buffer += samplesToRead;
+ len -= samplesToRead;
+ _samplesTillCallback -= samplesToRead;
+ }
+
+ return numSamples;
+}
+
+void Player_AD::setupVolume() {
+ // Setup the correct volume
+ int soundVolumeMusic = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ int soundVolumeSfx = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ if (ConfMan.hasKey("mute")) {
+ if (ConfMan.getBool("mute")) {
+ soundVolumeMusic = 0;
+ soundVolumeSfx = 0;
+ }
+ }
+
+ // In case a music is being played set the music volume. Set the sfx
+ // volume otherwise. This is safe because in the latter case either
+ // sfx are playing or there is no sound being played at all.
+ if (_soundPlaying != -1) {
+ _mixer->setChannelVolume(_soundHandle, soundVolumeMusic);
+ } else {
+ _mixer->setChannelVolume(_soundHandle, soundVolumeSfx);
+ }
+}
+
+void Player_AD::writeReg(int r, int v) {
+ if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
+ _registerBackUpTable[r] = v;
+ }
+ _opl2->writeReg(r, v);
+}
+
+uint8 Player_AD::readReg(int r) const {
+ if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
+ return _registerBackUpTable[r];
+ } else {
+ return 0;
+ }
+}
+
+void Player_AD::setupChannel(const uint channel, const byte *instrOffset) {
+ instrOffset += 2;
+ writeReg(0xC0 + channel, *instrOffset++);
+ setupOperator(_operatorOffsetTable[channel * 2 + 0], instrOffset);
+ setupOperator(_operatorOffsetTable[channel * 2 + 1], instrOffset);
+}
+
+void Player_AD::setupOperator(const uint opr, const byte *&instrOffset) {
+ writeReg(0x20 + opr, *instrOffset++);
+ writeReg(0x40 + opr, *instrOffset++);
+ writeReg(0x60 + opr, *instrOffset++);
+ writeReg(0x80 + opr, *instrOffset++);
+ writeReg(0xE0 + opr, *instrOffset++);
+}
+
+const int Player_AD::_operatorOffsetTable[18] = {
+ 0, 3, 1, 4,
+ 2, 5, 8, 11,
+ 9, 12, 10, 13,
+ 16, 19, 17, 20,
+ 18, 21
+};
+
+// Music
+
+void Player_AD::startMusic() {
+ memset(_instrumentOffset, 0, sizeof(_instrumentOffset));
+ memset(_channelLastEvent, 0, sizeof(_channelLastEvent));
+ memset(_channelFrequency, 0, sizeof(_channelFrequency));
+ memset(_channelB0Reg, 0, sizeof(_channelB0Reg));
+
+ _voiceChannels = 0;
+ uint instruments = _resource[10];
+ for (uint i = 0; i < instruments; ++i) {
+ const int instrIndex = _resource[11 + i] - 1;
+ if (0 <= instrIndex && instrIndex < 16) {
+ _instrumentOffset[instrIndex] = i * 16 + 16 + 3;
+ _voiceChannels |= _resource[_instrumentOffset[instrIndex] + 13];
+ }
+ }
+
+ if (_voiceChannels) {
+ _mdvdrState = 0x20;
+ _voiceChannels = 6;
+ } else {
+ _mdvdrState = 0;
+ _voiceChannels = 9;
+ }
+
+ _curOffset = 0x93;
+ // TODO: is this the same for Loom?
+ _nextEventTimer = 40;
+ _engineMusicTimer = 0;
+ _internalMusicTimer = 0;
+ _musicTimer = 0;
+
+ writeReg(0xBD, _mdvdrState);
+
+ const bool isLoom = (_vm->_game.id == GID_LOOM);
+ _timerLimit = isLoom ? 473 : 256;
+ _musicTicks = _resource[3] * (isLoom ? 2 : 1);
+ _loopFlag = (_resource[4] == 0);
+ _musicLoopStart = READ_LE_UINT16(_resource + 5);
+}
+
+void Player_AD::updateMusic() {
+ _musicTimer += _musicTicks;
+ if (_musicTimer < _timerLimit) {
+ return;
+ }
+ _musicTimer -= _timerLimit;
+
+ ++_internalMusicTimer;
+ if (_internalMusicTimer > 120) {
+ _internalMusicTimer = 0;
+ ++_engineMusicTimer;
+ }
+
+ --_nextEventTimer;
+ if (_nextEventTimer) {
+ return;
+ }
+
+ while (true) {
+ uint command = _resource[_curOffset++];
+ if (command == 0xFF) {
+ // META EVENT
+ // Get the command number.
+ command = _resource[_curOffset++];
+ if (command == 47) {
+ // End of track
+ if (_loopFlag) {
+ // In case the track is looping jump to the start.
+ _curOffset = _musicLoopStart;
+ _nextEventTimer = 0;
+ } else {
+ // Otherwise completely stop playback.
+ stopAllSounds();
+ }
+ return;
+ } else if (command == 88) {
+ // This is proposedly a debug information insertion. The CMS
+ // player code handles this differently, but is still using
+ // the same resources...
+ _curOffset += 5;
+ } else if (command == 81) {
+ // Change tempo. This is used exclusively in Loom.
+ const uint timing = _resource[_curOffset + 2] | (_resource[_curOffset + 1] << 8);
+ _musicTicks = 0x73000 / timing;
+ command = _resource[_curOffset++];
+ _curOffset += command;
+ } else {
+ // In case an unknown meta event occurs just skip over the
+ // data by using the length supplied.
+ command = _resource[_curOffset++];
+ _curOffset += command;
+ }
+ } else {
+ if (command >= 0x90) {
+ // NOTE ON
+ // Extract the channel number and save it in command.
+ command -= 0x90;
+
+ const uint instrOffset = _instrumentOffset[command];
+ if (instrOffset) {
+ if (_resource[instrOffset + 13] != 0) {
+ setupRhythm(_resource[instrOffset + 13], instrOffset);
+ } else {
+ int channel = findFreeChannel();
+ if (channel != -1) {
+ noteOff(channel);
+ setupChannel(channel, instrOffset);
+ _channelLastEvent[channel] = command + 0x90;
+ _channelFrequency[channel] = _resource[_curOffset];
+ setupFrequency(channel, _resource[_curOffset]);
+ }
+ }
+ }
+ } else {
+ // NOTE OFF
+ const uint note = _resource[_curOffset];
+ command += 0x10;
+
+ // Find the output channel which plays the note.
+ uint channel = 0xFF;
+ for (uint i = 0; i < _voiceChannels; ++i) {
+ if (_channelFrequency[i] == note && _channelLastEvent[i] == command) {
+ channel = i;
+ break;
+ }
+ }
+
+ if (channel != 0xFF) {
+ // In case a output channel playing the note was found,
+ // stop it.
+ noteOff(channel);
+ } else {
+ // In case there is no such note this will disable the
+ // rhythm instrument played on the channel.
+ command -= 0x90;
+ const uint instrOffset = _instrumentOffset[command];
+ if (instrOffset && _resource[instrOffset + 13] != 0) {
+ const uint rhythmInstr = _resource[instrOffset + 13];
+ if (rhythmInstr < 6) {
+ _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF;
+ writeReg(0xBD, _mdvdrState);
+ }
+ }
+ }
+ }
+
+ _curOffset += 2;
+ }
+
+ // In case there is a delay till the next event stop handling.
+ if (_resource[_curOffset] != 0) {
+ break;
+ }
+ ++_curOffset;
+ }
+
+ _nextEventTimer = _resource[_curOffset++];
+ if (_nextEventTimer & 0x80) {
+ _nextEventTimer -= 0x80;
+ _nextEventTimer <<= 7;
+ _nextEventTimer |= _resource[_curOffset++];
+ }
+
+ _nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1;
+ if (!_nextEventTimer) {
+ _nextEventTimer = 1;
+ }
+}
+
+void Player_AD::noteOff(uint channel) {
+ _channelLastEvent[channel] = 0;
+ writeReg(0xB0 + channel, _channelB0Reg[channel] & 0xDF);
+}
+
+int Player_AD::findFreeChannel() {
+ for (uint i = 0; i < _voiceChannels; ++i) {
+ if (!_channelLastEvent[i]) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void Player_AD::setupFrequency(uint channel, int8 frequency) {
+ frequency -= 31;
+ if (frequency < 0) {
+ frequency = 0;
+ }
+
+ uint octave = 0;
+ while (frequency >= 12) {
+ frequency -= 12;
+ ++octave;
+ }
+
+ const uint noteFrequency = _noteFrequencies[frequency];
+ octave <<= 2;
+ octave |= noteFrequency >> 8;
+ octave |= 0x20;
+ writeReg(0xA0 + channel, noteFrequency & 0xFF);
+ _channelB0Reg[channel] = octave;
+ writeReg(0xB0 + channel, octave);
+}
+
+void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
+ if (rhythmInstr == 1) {
+ setupChannel(6, instrOffset);
+ writeReg(0xA6, _resource[instrOffset++]);
+ writeReg(0xB6, _resource[instrOffset] & 0xDF);
+ _mdvdrState |= 0x10;
+ writeReg(0xBD, _mdvdrState);
+ } else if (rhythmInstr < 6) {
+ const byte *secondOperatorOffset = _resource + instrOffset + 8;
+ setupOperator(_rhythmOperatorTable[rhythmInstr], secondOperatorOffset);
+ writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++]);
+ writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++] & 0xDF);
+ writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset]);
+ _mdvdrState |= _mdvdrTable[rhythmInstr];
+ writeReg(0xBD, _mdvdrState);
+ }
+}
+
+const uint Player_AD::_noteFrequencies[12] = {
+ 0x200, 0x21E, 0x23F, 0x261,
+ 0x285, 0x2AB, 0x2D4, 0x300,
+ 0x32E, 0x35E, 0x390, 0x3C7
+};
+
+const uint Player_AD::_mdvdrTable[6] = {
+ 0x00, 0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+const uint Player_AD::_rhythmOperatorTable[6] = {
+ 0x00, 0x00, 0x14, 0x12, 0x15, 0x11
+};
+
+const uint Player_AD::_rhythmChannelTable[6] = {
+ 0x00, 0x00, 0x07, 0x08, 0x08, 0x07
+};
+
+// SFX
+
+void Player_AD::startSfx() {
+ writeReg(0xBD, 0x00);
+
+ // The second byte of the resource defines the logical channel where
+ // the sound effect should be played.
+ const int startChannel = _resource[1] * 3;
+
+ // Clear the channel.
+ _channels[startChannel + 0].state = 0;
+ _channels[startChannel + 1].state = 0;
+ _channels[startChannel + 2].state = 0;
+
+ clearChannel(startChannel + 0);
+ clearChannel(startChannel + 1);
+ clearChannel(startChannel + 2);
+
+ // Set up the first channel to pick up playback.
+ _channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2;
+ _channels[startChannel].state = 1;
+
+ // Scan for the start of the other channels and set them up if required.
+ int curChannel = startChannel + 1;
+ const byte *bufferPosition = _resource + 2;
+ uint8 command = 0;
+ while ((command = *bufferPosition) != 0xFF) {
+ switch (command) {
+ case 1:
+ // INSTRUMENT DEFINITION
+ bufferPosition += 15;
+ break;
+
+ case 2:
+ // NOTE DEFINITION
+ bufferPosition += 11;
+ break;
+
+ case 0x80:
+ // LOOP
+ bufferPosition += 1;
+ break;
+
+ default:
+ // START OF CHANNEL
+ bufferPosition += 1;
+ _channels[curChannel].currentOffset = bufferPosition;
+ _channels[curChannel].startOffset = bufferPosition;
+ _channels[curChannel].state = 1;
+ ++curChannel;
+ break;
+ }
+ }
+}
+
+void Player_AD::updateSfx() {
+ if (--_sfxTimer) {
+ return;
+ }
+ _sfxTimer = 4;
+
+ for (int i = 0; i <= 9; ++i) {
+ if (!_channels[i].state) {
+ continue;
+ }
+
+ updateChannel(i);
+ }
+}
+
+void Player_AD::clearChannel(int channel) {
+ writeReg(0xA0 + channel, 0x00);
+ writeReg(0xB0 + channel, 0x00);
+}
+
+void Player_AD::updateChannel(int channel) {
+ if (_channels[channel].state == 1) {
+ parseSlot(channel);
+ } else {
+ updateSlot(channel);
+ }
+}
+
+void Player_AD::parseSlot(int channel) {
+ while (true) {
+ const byte *curOffset = _channels[channel].currentOffset;
+
+ switch (*curOffset) {
+ case 1:
+ // INSTRUMENT DEFINITION
+ ++curOffset;
+ _channels[channel].instrumentData[0] = *(curOffset + 0);
+ _channels[channel].instrumentData[1] = *(curOffset + 2);
+ _channels[channel].instrumentData[2] = *(curOffset + 9);
+ _channels[channel].instrumentData[3] = *(curOffset + 8);
+ _channels[channel].instrumentData[4] = *(curOffset + 4);
+ _channels[channel].instrumentData[5] = *(curOffset + 3);
+ _channels[channel].instrumentData[6] = 0;
+
+ setupChannel(channel, curOffset);
+
+ writeReg(0xA0 + channel, *(curOffset + 0));
+ writeReg(0xB0 + channel, *(curOffset + 1) & 0xDF);
+
+ _channels[channel].currentOffset += 15;
+ break;
+
+ case 2:
+ // NOTE DEFINITION
+ ++curOffset;
+ _channels[channel].state = 2;
+ noteOffOn(channel);
+ parseNote(channel, 0, curOffset);
+ parseNote(channel, 1, curOffset);
+ return;
+
+ case 0x80:
+ // LOOP
+ _channels[channel].currentOffset = _channels[channel].startOffset;
+ break;
+
+ default:
+ // START OF CHANNEL
+ // When we encounter a start of another channel while playback
+ // it means that the current channel is finished. Thus, we will
+ // stop it.
+ clearChannel(channel);
+ _channels[channel].state = 0;
+
+ // If no channel of the sound effect is playing anymore, unlock
+ // the resource.
+ channel /= 3;
+ if (!_channels[channel + 0].state
+ && !_channels[channel + 1].state
+ && !_channels[channel + 2].state) {
+ _vm->_res->unlock(rtSound, _sfxResource[channel]);
+ }
+ return;
+ }
+ }
+}
+
+void Player_AD::updateSlot(int channel) {
+ const byte *curOffset = _channels[channel].currentOffset + 1;
+
+ for (int num = 0; num <= 1; ++num, curOffset += 5) {
+ if (!(*curOffset & 0x80)) {
+ continue;
+ }
+
+ const int note = channel * 2 + num;
+ bool updateNote = false;
+
+ if (_notes[note].state == 2) {
+ if (!--_notes[note].sustainTimer) {
+ updateNote = true;
+ }
+ } else {
+ updateNote = processNoteEnvelope(note, _notes[note].instrumentValue);
+
+ if (_notes[note].bias) {
+ writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
+ } else {
+ writeRegisterSpecial(note, _notes[note].instrumentValue, *curOffset & 0x07);
+ }
+ }
+
+ if (updateNote) {
+ if (processNote(note, curOffset)) {
+ if (!(*curOffset & 0x08)) {
+ _channels[channel].currentOffset += 11;
+ _channels[channel].state = 1;
+ continue;
+ } else if (*curOffset & 0x10) {
+ noteOffOn(channel);
+ }
+
+ _notes[note].state = -1;
+ processNote(note, curOffset);
+ }
+ }
+
+ if ((*curOffset & 0x20) && !--_notes[note].playTime) {
+ _channels[channel].currentOffset += 11;
+ _channels[channel].state = 1;
+ }
+ }
+}
+
+void Player_AD::parseNote(int channel, int num, const byte *offset) {
+ if (num) {
+ offset += 5;
+ }
+
+ if (*offset & 0x80) {
+ const int note = channel * 2 + num;
+ _notes[note].state = -1;
+ processNote(note, offset);
+ _notes[note].playTime = 0;
+
+ if (*offset & 0x20) {
+ _notes[note].playTime = (*(offset + 4) >> 4) * 118;
+ _notes[note].playTime += (*(offset + 4) & 0x0F) * 8;
+ }
+ }
+}
+
+bool Player_AD::processNote(int note, const byte *offset) {
+ if (++_notes[note].state == 4) {
+ return true;
+ }
+
+ const int instrumentDataOffset = *offset & 0x07;
+ _notes[note].bias = _noteBiasTable[instrumentDataOffset];
+
+ uint8 instrumentDataValue = 0;
+ if (_notes[note].state == 0) {
+ instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
+ }
+
+ uint8 noteInstrumentValue = readRegisterSpecial(note, instrumentDataValue, instrumentDataOffset);
+ if (_notes[note].bias) {
+ noteInstrumentValue = _notes[note].bias - noteInstrumentValue;
+ }
+ _notes[note].instrumentValue = noteInstrumentValue;
+
+ if (_notes[note].state == 2) {
+ _notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4];
+
+ if (*offset & 0x40) {
+ _notes[note].sustainTimer = (((getRnd() << 8) * _notes[note].sustainTimer) >> 16) + 1;
+ }
+ } else {
+ int timer1, timer2;
+ if (_notes[note].state == 3) {
+ timer1 = *(offset + 3) & 0x0F;
+ timer2 = 0;
+ } else {
+ timer1 = *(offset + _notes[note].state + 1) >> 4;
+ timer2 = *(offset + _notes[note].state + 1) & 0x0F;
+ }
+
+ int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue;
+ setupNoteEnvelopeState(note, _numStepsTable[timer1], adjustValue);
+ }
+
+ return false;
+}
+
+void Player_AD::noteOffOn(int channel) {
+ const uint8 regValue = readReg(0xB0 | channel);
+ writeReg(0xB0 | channel, regValue & 0xDF);
+ writeReg(0xB0 | channel, regValue | 0x20);
+}
+
+void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
+ if (offset == 6) {
+ return;
+ }
+
+ // Division by 2 extracts the channel number out of the note.
+ note /= 2;
+
+ uint8 regNum;
+ if (_useOperatorTable[offset]) {
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ } else {
+ regNum = _channelOffsetTable[note];
+ }
+
+ regNum += _baseRegisterTable[offset];
+
+ uint8 regValue = readReg(regNum) & (~_registerMaskTable[offset]);
+ regValue |= value << _registerShiftTable[offset];
+
+ writeReg(regNum, regValue);
+}
+
+uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
+ if (offset == 6) {
+ return 0;
+ }
+
+ // Division by 2 extracts the channel number out of the note.
+ note /= 2;
+
+ uint8 regNum;
+ if (_useOperatorTable[offset]) {
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ } else {
+ regNum = _channelOffsetTable[note];
+ }
+
+ regNum += _baseRegisterTable[offset];
+
+ uint8 regValue;
+ if (defaultValue) {
+ regValue = defaultValue;
+ } else {
+ regValue = readReg(regNum);
+ }
+
+ regValue &= _registerMaskTable[offset];
+ regValue >>= _registerShiftTable[offset];
+
+ return regValue;
+}
+
+void Player_AD::setupNoteEnvelopeState(int note, int steps, int adjust) {
+ _notes[note].preIncrease = 0;
+ if (ABS(adjust) > steps) {
+ _notes[note].preIncrease = 1;
+ _notes[note].adjust = adjust / steps;
+ _notes[note].envelope.stepIncrease = ABS(adjust % steps);
+ } else {
+ _notes[note].adjust = adjust;
+ _notes[note].envelope.stepIncrease = ABS(adjust);
+ }
+
+ _notes[note].envelope.step = steps;
+ _notes[note].envelope.stepCounter = 0;
+ _notes[note].envelope.timer = steps;
+}
+
+bool Player_AD::processNoteEnvelope(int note, int &instrumentValue) {
+ if (_notes[note].preIncrease) {
+ instrumentValue += _notes[note].adjust;
+ }
+
+ _notes[note].envelope.stepCounter += _notes[note].envelope.stepIncrease;
+ if (_notes[note].envelope.stepCounter >= _notes[note].envelope.step) {
+ _notes[note].envelope.stepCounter -= _notes[note].envelope.step;
+
+ if (_notes[note].adjust < 0) {
+ --instrumentValue;
+ } else {
+ ++instrumentValue;
+ }
+ }
+
+ if (--_notes[note].envelope.timer) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+uint8 Player_AD::getRnd() {
+ if (_rndSeed & 1) {
+ _rndSeed >>= 1;
+ _rndSeed ^= 0xB8;
+ } else {
+ _rndSeed >>= 1;
+ }
+
+ return _rndSeed;
+}
+
+const uint Player_AD::_noteBiasTable[7] = {
+ 0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x00
+};
+
+const uint Player_AD::_numStepsTable[16] = {
+ 1, 4, 6, 8,
+ 10, 14, 18, 24,
+ 36, 64, 100, 160,
+ 240, 340, 600, 1200
+};
+
+const uint Player_AD::_noteAdjustScaleTable[7] = {
+ 255, 7, 63, 15, 63, 15, 63
+};
+
+const uint Player_AD::_noteAdjustTable[16] = {
+ 0, 4369, 8738, 13107,
+ 17476, 21845, 26214, 30583,
+ 34952, 39321, 43690, 48059,
+ 52428, 46797, 61166, 65535
+};
+
+const bool Player_AD::_useOperatorTable[7] = {
+ false, false, true, true, true, true, false
+};
+
+const uint Player_AD::_channelOffsetTable[11] = {
+ 0, 1, 2, 3,
+ 4, 5, 6, 7,
+ 8, 8, 7
+};
+
+const uint Player_AD::_channelOperatorOffsetTable[7] = {
+ 0, 0, 1, 1, 0, 0, 0
+};
+
+const uint Player_AD::_baseRegisterTable[7] = {
+ 0xA0, 0xC0, 0x40, 0x20, 0x40, 0x20, 0x00
+};
+
+const uint Player_AD::_registerMaskTable[7] = {
+ 0xFF, 0x0E, 0x3F, 0x0F, 0x3F, 0x0F, 0x00
+};
+
+const uint Player_AD::_registerShiftTable[7] = {
+ 0, 1, 0, 0, 0, 0, 0
+};
+
+} // End of namespace Scumm
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
new file mode 100644
index 0000000000..fbb65fbe24
--- /dev/null
+++ b/engines/scumm/players/player_ad.h
@@ -0,0 +1,190 @@
+/* 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 SCUMM_PLAYERS_PLAYER_AD_H
+#define SCUMM_PLAYERS_PLAYER_AD_H
+
+#include "scumm/music.h"
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+
+#include "common/mutex.h"
+
+namespace OPL {
+class OPL;
+}
+
+namespace Scumm {
+
+class ScummEngine;
+
+/**
+ * Sound output for v3/v4 AdLib data.
+ */
+class Player_AD : public MusicEngine, public Audio::AudioStream {
+public:
+ Player_AD(ScummEngine *scumm, Audio::Mixer *mixer);
+ virtual ~Player_AD();
+
+ // MusicEngine API
+ virtual void setMusicVolume(int vol);
+ virtual void startSound(int sound);
+ virtual void stopSound(int sound);
+ virtual void stopAllSounds();
+ virtual int getMusicTimer();
+ virtual int getSoundStatus(int sound) const;
+
+ virtual void saveLoadWithSerializer(Serializer *ser);
+
+ // AudioStream API
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const { return false; }
+ virtual bool endOfData() const { return false; }
+ virtual int getRate() const { return _rate; }
+
+private:
+ ScummEngine *const _vm;
+ Common::Mutex _mutex;
+ Audio::Mixer *const _mixer;
+ const int _rate;
+ Audio::SoundHandle _soundHandle;
+ void setupVolume();
+
+ OPL::OPL *_opl2;
+
+ int _samplesPerCallback;
+ int _samplesPerCallbackRemainder;
+ int _samplesTillCallback;
+ int _samplesTillCallbackRemainder;
+
+ int _soundPlaying;
+ int _engineMusicTimer;
+
+ // AdLib register utilities
+ uint8 _registerBackUpTable[256];
+ void writeReg(int r, int v);
+ uint8 readReg(int r) const;
+
+ // Instrument setup
+ void setupChannel(const uint channel, uint instrOffset) {
+ setupChannel(channel, _resource + instrOffset);
+ }
+ void setupChannel(const uint channel, const byte *instrOffset);
+ void setupOperator(const uint opr, const byte *&instrOffset);
+ static const int _operatorOffsetTable[18];
+
+ // Sound data
+ const byte *_resource;
+
+ // Music handling
+ void startMusic();
+ void updateMusic();
+ void noteOff(uint channel);
+ int findFreeChannel();
+ void setupFrequency(uint channel, int8 frequency);
+ void setupRhythm(uint rhythmInstr, uint instrOffset);
+
+ uint _timerLimit;
+ uint _musicTicks;
+ uint _musicTimer;
+ uint _internalMusicTimer;
+ bool _loopFlag;
+ uint _musicLoopStart;
+ uint _instrumentOffset[16];
+ uint _channelLastEvent[9];
+ uint _channelFrequency[9];
+ uint _channelB0Reg[9];
+
+ uint _mdvdrState;
+ uint _voiceChannels;
+
+ uint _curOffset;
+ uint _nextEventTimer;
+
+ static const uint _noteFrequencies[12];
+ static const uint _mdvdrTable[6];
+ static const uint _rhythmOperatorTable[6];
+ static const uint _rhythmChannelTable[6];
+
+ // SFX handling
+ void startSfx();
+ void updateSfx();
+ void clearChannel(int channel);
+ void updateChannel(int channel);
+ void parseSlot(int channel);
+ void updateSlot(int channel);
+ void parseNote(int channel, int num, const byte *offset);
+ bool processNote(int note, const byte *offset);
+ void noteOffOn(int channel);
+ void writeRegisterSpecial(int note, uint8 value, int offset);
+ uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset);
+ void setupNoteEnvelopeState(int note, int steps, int adjust);
+ bool processNoteEnvelope(int note, int &instrumentValue);
+
+ int _sfxTimer;
+
+ int _sfxResource[3];
+ int _sfxPriority[3];
+
+ struct Channel {
+ int state;
+ const byte *currentOffset;
+ const byte *startOffset;
+ uint8 instrumentData[7];
+ } _channels[11];
+
+ uint8 _rndSeed;
+ uint8 getRnd();
+
+ struct Note {
+ int state;
+ int playTime;
+ int sustainTimer;
+ int instrumentValue;
+ int bias;
+ int preIncrease;
+ int adjust;
+
+ struct Envelope {
+ int stepIncrease;
+ int step;
+ int stepCounter;
+ int timer;
+ } envelope;
+ } _notes[22];
+
+ static const uint _noteBiasTable[7];
+ static const uint _numStepsTable[16];
+ static const uint _noteAdjustScaleTable[7];
+ static const uint _noteAdjustTable[16];
+ static const bool _useOperatorTable[7];
+ static const uint _channelOffsetTable[11];
+ static const uint _channelOperatorOffsetTable[7];
+ static const uint _baseRegisterTable[7];
+ static const uint _registerMaskTable[7];
+ static const uint _registerShiftTable[7];
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/player_apple2.cpp b/engines/scumm/players/player_apple2.cpp
index 58e4f78a94..87b8100f22 100644
--- a/engines/scumm/player_apple2.cpp
+++ b/engines/scumm/players/player_apple2.cpp
@@ -21,7 +21,7 @@
*/
#include "engines/engine.h"
-#include "scumm/player_apple2.h"
+#include "scumm/players/player_apple2.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_apple2.h b/engines/scumm/players/player_apple2.h
index e1ec9d8946..9930a4f95d 100644
--- a/engines/scumm/player_apple2.h
+++ b/engines/scumm/players/player_apple2.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_APPLEII_H
-#define SCUMM_PLAYER_APPLEII_H
+#ifndef SCUMM_PLAYERS_PLAYER_APPLEII_H
+#define SCUMM_PLAYERS_PLAYER_APPLEII_H
#include "common/mutex.h"
#include "common/scummsys.h"
diff --git a/engines/scumm/player_mac.cpp b/engines/scumm/players/player_mac.cpp
index c16c85bff3..281eec5336 100644
--- a/engines/scumm/player_mac.cpp
+++ b/engines/scumm/players/player_mac.cpp
@@ -24,7 +24,7 @@
#include "common/translation.h"
#include "engines/engine.h"
#include "gui/message.h"
-#include "scumm/player_mac.h"
+#include "scumm/players/player_mac.h"
#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/imuse/imuse.h"
@@ -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_mac.h b/engines/scumm/players/player_mac.h
index 09307b4e57..7f9f42c34e 100644
--- a/engines/scumm/player_mac.h
+++ b/engines/scumm/players/player_mac.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_MAC_H
-#define SCUMM_PLAYER_MAC_H
+#ifndef SCUMM_PLAYERS_PLAYER_MAC_H
+#define SCUMM_PLAYERS_PLAYER_MAC_H
#include "common/scummsys.h"
#include "common/util.h"
diff --git a/engines/scumm/player_mod.cpp b/engines/scumm/players/player_mod.cpp
index 6411f0a17a..abaa8c1fc5 100644
--- a/engines/scumm/player_mod.cpp
+++ b/engines/scumm/players/player_mod.cpp
@@ -21,7 +21,7 @@
*/
-#include "scumm/player_mod.h"
+#include "scumm/players/player_mod.h"
#include "audio/mixer.h"
#include "audio/rate.h"
#include "audio/decoders/raw.h"
diff --git a/engines/scumm/player_mod.h b/engines/scumm/players/player_mod.h
index 619d83541d..d4a5b16fca 100644
--- a/engines/scumm/player_mod.h
+++ b/engines/scumm/players/player_mod.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_MOD_H
-#define SCUMM_PLAYER_MOD_H
+#ifndef SCUMM_PLAYERS_PLAYER_MOD_H
+#define SCUMM_PLAYERS_PLAYER_MOD_H
#include "scumm/scumm.h"
#include "audio/audiostream.h"
diff --git a/engines/scumm/player_nes.cpp b/engines/scumm/players/player_nes.cpp
index a6ffc9ed86..f55f1f9edd 100644
--- a/engines/scumm/player_nes.cpp
+++ b/engines/scumm/players/player_nes.cpp
@@ -23,7 +23,7 @@
#ifndef DISABLE_NES_APU
#include "engines/engine.h"
-#include "scumm/player_nes.h"
+#include "scumm/players/player_nes.h"
#include "scumm/scumm.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/player_nes.h b/engines/scumm/players/player_nes.h
index be1617e0f6..f0b3e79aad 100644
--- a/engines/scumm/player_nes.h
+++ b/engines/scumm/players/player_nes.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_NES_H
-#define SCUMM_PLAYER_NES_H
+#ifndef SCUMM_PLAYERS_PLAYER_NES_H
+#define SCUMM_PLAYERS_PLAYER_NES_H
#include "common/scummsys.h"
#include "scumm/music.h"
diff --git a/engines/scumm/player_pce.cpp b/engines/scumm/players/player_pce.cpp
index 8d886ee008..6d6e2fcde5 100644
--- a/engines/scumm/player_pce.cpp
+++ b/engines/scumm/players/player_pce.cpp
@@ -29,7 +29,7 @@
*/
#include <math.h>
-#include "player_pce.h"
+#include "scumm/players/player_pce.h"
#include "common/endian.h"
// PCE sound engine is only used by Loom, which requires 16bit color support
diff --git a/engines/scumm/player_pce.h b/engines/scumm/players/player_pce.h
index 427fb1ace6..ca2eddf58c 100644
--- a/engines/scumm/player_pce.h
+++ b/engines/scumm/players/player_pce.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_PCE_H
-#define SCUMM_PLAYER_PCE_H
+#ifndef SCUMM_PLAYERS_PLAYER_PCE_H
+#define SCUMM_PLAYERS_PLAYER_PCE_H
#include "common/scummsys.h"
#include "common/mutex.h"
diff --git a/engines/scumm/player_sid.cpp b/engines/scumm/players/player_sid.cpp
index 7a609364e5..1b97ad16d4 100644
--- a/engines/scumm/player_sid.cpp
+++ b/engines/scumm/players/player_sid.cpp
@@ -23,7 +23,7 @@
#ifndef DISABLE_SID
#include "engines/engine.h"
-#include "scumm/player_sid.h"
+#include "scumm/players/player_sid.h"
#include "scumm/scumm.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/player_sid.h b/engines/scumm/players/player_sid.h
index 12e3573575..a48ec793cd 100644
--- a/engines/scumm/player_sid.h
+++ b/engines/scumm/players/player_sid.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_SID_H
-#define SCUMM_PLAYER_SID_H
+#ifndef SCUMM_PLAYERS_PLAYER_SID_H
+#define SCUMM_PLAYERS_PLAYER_SID_H
#include "common/mutex.h"
#include "common/scummsys.h"
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/players/player_towns.cpp
index 33e3e40e39..acbdbc7fb6 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/players/player_towns.cpp
@@ -22,7 +22,7 @@
#include "scumm/sound.h"
-#include "scumm/player_towns.h"
+#include "scumm/players/player_towns.h"
namespace Scumm {
diff --git a/engines/scumm/player_towns.h b/engines/scumm/players/player_towns.h
index 5c76d7c6c7..2369b7da5f 100644
--- a/engines/scumm/player_towns.h
+++ b/engines/scumm/players/player_towns.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_TOWNS_H
-#define SCUMM_PLAYER_TOWNS_H
+#ifndef SCUMM_PLAYERS_PLAYER_TOWNS_H
+#define SCUMM_PLAYERS_PLAYER_TOWNS_H
#include "scumm/scumm.h"
#include "scumm/imuse/imuse.h"
diff --git a/engines/scumm/player_v1.cpp b/engines/scumm/players/player_v1.cpp
index 8e784e9866..0fa1ee9361 100644
--- a/engines/scumm/player_v1.cpp
+++ b/engines/scumm/players/player_v1.cpp
@@ -22,7 +22,7 @@
#include "engines/engine.h"
-#include "scumm/player_v1.h"
+#include "scumm/players/player_v1.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_v1.h b/engines/scumm/players/player_v1.h
index 9e6063adc9..ccd24c39df 100644
--- a/engines/scumm/player_v1.h
+++ b/engines/scumm/players/player_v1.h
@@ -20,10 +20,10 @@
*
*/
-#ifndef SCUMM_PLAYER_V1_H
-#define SCUMM_PLAYER_V1_H
+#ifndef SCUMM_PLAYERS_PLAYER_V1_H
+#define SCUMM_PLAYERS_PLAYER_V1_H
-#include "scumm/player_v2.h"
+#include "scumm/players/player_v2.h"
namespace Scumm {
diff --git a/engines/scumm/player_v2.cpp b/engines/scumm/players/player_v2.cpp
index 6910f5e0db..2429af2d8c 100644
--- a/engines/scumm/player_v2.cpp
+++ b/engines/scumm/players/player_v2.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "scumm/player_v2.h"
+#include "scumm/players/player_v2.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_v2.h b/engines/scumm/players/player_v2.h
index d932585b8e..33878ff08b 100644
--- a/engines/scumm/player_v2.h
+++ b/engines/scumm/players/player_v2.h
@@ -20,10 +20,10 @@
*
*/
-#ifndef SCUMM_PLAYER_V2_H
-#define SCUMM_PLAYER_V2_H
+#ifndef SCUMM_PLAYERS_PLAYER_V2_H
+#define SCUMM_PLAYERS_PLAYER_V2_H
-#include "scumm/player_v2base.h"
+#include "scumm/players/player_v2base.h"
namespace Scumm {
diff --git a/engines/scumm/player_v2a.cpp b/engines/scumm/players/player_v2a.cpp
index 07fc77b301..aeccb8b7cb 100644
--- a/engines/scumm/player_v2a.cpp
+++ b/engines/scumm/players/player_v2a.cpp
@@ -21,7 +21,7 @@
*/
#include "engines/engine.h"
-#include "scumm/player_v2a.h"
+#include "scumm/players/player_v2a.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_v2a.h b/engines/scumm/players/player_v2a.h
index fe20b43846..12193635f2 100644
--- a/engines/scumm/player_v2a.h
+++ b/engines/scumm/players/player_v2a.h
@@ -20,12 +20,12 @@
*
*/
-#ifndef SCUMM_PLAYER_V2A_H
-#define SCUMM_PLAYER_V2A_H
+#ifndef SCUMM_PLAYERS_PLAYER_V2A_H
+#define SCUMM_PLAYERS_PLAYER_V2A_H
#include "common/scummsys.h"
#include "scumm/music.h"
-#include "scumm/player_mod.h"
+#include "scumm/players/player_mod.h"
class Mixer;
diff --git a/engines/scumm/player_v2base.cpp b/engines/scumm/players/player_v2base.cpp
index 0d3ad4b1b3..75f1518989 100644
--- a/engines/scumm/player_v2base.cpp
+++ b/engines/scumm/players/player_v2base.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "scumm/player_v2base.h"
+#include "scumm/players/player_v2base.h"
#include "scumm/scumm.h"
#define FREQ_HZ 236 // Don't change!
diff --git a/engines/scumm/player_v2base.h b/engines/scumm/players/player_v2base.h
index eb9ed941ca..32bde95ddc 100644
--- a/engines/scumm/player_v2base.h
+++ b/engines/scumm/players/player_v2base.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_V2BASE_H
-#define SCUMM_PLAYER_V2BASE_H
+#ifndef SCUMM_PLAYERS_PLAYER_V2BASE_H
+#define SCUMM_PLAYERS_PLAYER_V2BASE_H
#include "common/scummsys.h"
#include "common/mutex.h"
diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/players/player_v2cms.cpp
index c1242e0645..8e903bf9d2 100644
--- a/engines/scumm/player_v2cms.cpp
+++ b/engines/scumm/players/player_v2cms.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "scumm/player_v2cms.h"
+#include "scumm/players/player_v2cms.h"
#include "scumm/scumm.h"
#include "audio/mididrv.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/player_v2cms.h b/engines/scumm/players/player_v2cms.h
index 905c7c141e..fe42720215 100644
--- a/engines/scumm/player_v2cms.h
+++ b/engines/scumm/players/player_v2cms.h
@@ -20,10 +20,10 @@
*
*/
-#ifndef SCUMM_PLAYER_V2CMS_H
-#define SCUMM_PLAYER_V2CMS_H
+#ifndef SCUMM_PLAYERS_PLAYER_V2CMS_H
+#define SCUMM_PLAYERS_PLAYER_V2CMS_H
-#include "scumm/player_v2base.h" // for channel_data
+#include "scumm/players/player_v2base.h" // for channel_data
class CMSEmulator;
diff --git a/engines/scumm/player_v3a.cpp b/engines/scumm/players/player_v3a.cpp
index 472cd1252b..ca0eedc90a 100644
--- a/engines/scumm/player_v3a.cpp
+++ b/engines/scumm/players/player_v3a.cpp
@@ -22,7 +22,7 @@
#include "engines/engine.h"
-#include "scumm/player_v3a.h"
+#include "scumm/players/player_v3a.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_v3a.h b/engines/scumm/players/player_v3a.h
index 9449664e9b..3f84a74e51 100644
--- a/engines/scumm/player_v3a.h
+++ b/engines/scumm/players/player_v3a.h
@@ -20,12 +20,12 @@
*
*/
-#ifndef SCUMM_PLAYER_V3A_H
-#define SCUMM_PLAYER_V3A_H
+#ifndef SCUMM_PLAYERS_PLAYER_V3A_H
+#define SCUMM_PLAYERS_PLAYER_V3A_H
#include "common/scummsys.h"
#include "scumm/music.h"
-#include "scumm/player_mod.h"
+#include "scumm/players/player_mod.h"
class Mixer;
diff --git a/engines/scumm/player_v3m.cpp b/engines/scumm/players/player_v3m.cpp
index 0f222d84fe..e30e31aff9 100644
--- a/engines/scumm/player_v3m.cpp
+++ b/engines/scumm/players/player_v3m.cpp
@@ -91,7 +91,7 @@
#include "common/translation.h"
#include "engines/engine.h"
#include "gui/message.h"
-#include "scumm/player_v3m.h"
+#include "scumm/players/player_v3m.h"
#include "scumm/scumm.h"
namespace Scumm {
@@ -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/player_v3m.h b/engines/scumm/players/player_v3m.h
index 359bab32a9..615d736035 100644
--- a/engines/scumm/player_v3m.h
+++ b/engines/scumm/players/player_v3m.h
@@ -20,14 +20,14 @@
*
*/
-#ifndef SCUMM_PLAYER_V3M_H
-#define SCUMM_PLAYER_V3M_H
+#ifndef SCUMM_PLAYERS_PLAYER_V3M_H
+#define SCUMM_PLAYERS_PLAYER_V3M_H
#include "common/scummsys.h"
#include "common/util.h"
#include "common/mutex.h"
#include "scumm/music.h"
-#include "scumm/player_mac.h"
+#include "scumm/players/player_mac.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/player_v4a.cpp b/engines/scumm/players/player_v4a.cpp
index e791736f0e..59f49625c3 100644
--- a/engines/scumm/player_v4a.cpp
+++ b/engines/scumm/players/player_v4a.cpp
@@ -21,7 +21,7 @@
*/
#include "engines/engine.h"
-#include "scumm/player_v4a.h"
+#include "scumm/players/player_v4a.h"
#include "scumm/scumm.h"
#include "common/file.h"
diff --git a/engines/scumm/player_v4a.h b/engines/scumm/players/player_v4a.h
index d01c70f295..c8c7b63ed2 100644
--- a/engines/scumm/player_v4a.h
+++ b/engines/scumm/players/player_v4a.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_PLAYER_V4A_H
-#define SCUMM_PLAYER_V4A_H
+#ifndef SCUMM_PLAYERS_PLAYER_V4A_H
+#define SCUMM_PLAYERS_PLAYER_V4A_H
#include "common/scummsys.h"
#include "common/util.h"
diff --git a/engines/scumm/player_v5m.cpp b/engines/scumm/players/player_v5m.cpp
index 500f3bbc40..77b6d52a3c 100644
--- a/engines/scumm/player_v5m.cpp
+++ b/engines/scumm/players/player_v5m.cpp
@@ -76,7 +76,7 @@
#include "common/translation.h"
#include "engines/engine.h"
#include "gui/message.h"
-#include "scumm/player_v5m.h"
+#include "scumm/players/player_v5m.h"
#include "scumm/scumm.h"
namespace Scumm {
diff --git a/engines/scumm/player_v5m.h b/engines/scumm/players/player_v5m.h
index b2079ee331..e3a457f8af 100644
--- a/engines/scumm/player_v5m.h
+++ b/engines/scumm/players/player_v5m.h
@@ -20,14 +20,14 @@
*
*/
-#ifndef SCUMM_PLAYER_V5M_H
-#define SCUMM_PLAYER_V5M_H
+#ifndef SCUMM_PLAYERS_PLAYER_V5M_H
+#define SCUMM_PLAYERS_PLAYER_V5M_H
#include "common/scummsys.h"
#include "common/util.h"
#include "common/mutex.h"
#include "scumm/music.h"
-#include "scumm/player_mac.h"
+#include "scumm/players/player_mac.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 3453e53a18..5197e07819 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -30,7 +30,7 @@
#include "scumm/charset.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse/imuse.h"
-#include "scumm/player_towns.h"
+#include "scumm/players/player_towns.h"
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
@@ -634,100 +634,83 @@ bool ScummEngine::getSavegameName(int slot, Common::String &desc) {
return result;
}
-bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion) {
- SaveGameHeader hdr;
-
+namespace {
+bool loadAndCheckSaveGameHeader(Common::InSaveFile *in, int heversion, SaveGameHeader &hdr, Common::String *error = nullptr) {
if (!loadSaveGameHeader(in, hdr)) {
- desc = "Invalid savegame";
+ if (error) {
+ *error = "Invalid savegame";
+ }
return false;
}
- if (hdr.ver > CURRENT_VER)
+ if (hdr.ver > CURRENT_VER) {
hdr.ver = TO_LE_32(hdr.ver);
+ }
+
if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) {
- desc = "Invalid version";
+ if (error) {
+ *error = "Invalid version";
+ }
return false;
}
// We (deliberately) broke HE savegame compatibility at some point.
if (hdr.ver < VER(57) && heversion >= 60) {
- desc = "Unsupported version";
+ if (error) {
+ *error = "Unsupported version";
+ }
return false;
}
hdr.name[sizeof(hdr.name) - 1] = 0;
- desc = hdr.name;
return true;
}
+} // End of anonymous namespace
-Graphics::Surface *ScummEngine::loadThumbnailFromSlot(const char *target, int slot) {
- Common::SeekableReadStream *in;
+bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion) {
SaveGameHeader hdr;
- if (slot < 0)
- return 0;
-
- Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
- if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
- return 0;
- }
-
- if (!loadSaveGameHeader(in, hdr)) {
- delete in;
- return 0;
+ if (!loadAndCheckSaveGameHeader(in, heversion, hdr, &desc)) {
+ return false;
}
- if (hdr.ver > CURRENT_VER)
- hdr.ver = TO_LE_32(hdr.ver);
- if (hdr.ver < VER(52)) {
- delete in;
- return 0;
- }
+ desc = hdr.name;
+ return true;
+}
- Graphics::Surface *thumb = 0;
- if (Graphics::checkThumbnailHeader(*in)) {
- thumb = Graphics::loadThumbnail(*in);
+bool ScummEngine::querySaveMetaInfos(const char *target, int slot, int heversion, Common::String &desc, Graphics::Surface *&thumbnail, SaveStateMetaInfos *&timeInfos) {
+ if (slot < 0) {
+ return false;
}
- delete in;
- return thumb;
-}
-
-bool ScummEngine::loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff) {
- Common::SeekableReadStream *in;
SaveGameHeader hdr;
+ const Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
+ Common::ScopedPtr<Common::SeekableReadStream> in(g_system->getSavefileManager()->openForLoading(filename));
- if (slot < 0)
- return 0;
-
- Common::String filename = makeSavegameName(target, slot, false);
- if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
+ if (!in) {
return false;
}
- if (!loadSaveGameHeader(in, hdr)) {
- delete in;
+ if (!loadAndCheckSaveGameHeader(in.get(), heversion, hdr)) {
return false;
}
- if (hdr.ver > CURRENT_VER)
- hdr.ver = TO_LE_32(hdr.ver);
- if (hdr.ver < VER(56)) {
- delete in;
- return false;
- }
+ desc = hdr.name;
- if (!Graphics::skipThumbnail(*in)) {
- delete in;
- return false;
- }
+ if (hdr.ver > VER(52)) {
+ if (Graphics::checkThumbnailHeader(*in)) {
+ thumbnail = Graphics::loadThumbnail(*in);
+ }
- if (!loadInfos(in, stuff)) {
- delete in;
- return false;
+ if (hdr.ver > VER(57)) {
+ if (!loadInfos(in.get(), timeInfos)) {
+ return false;
+ }
+ } else {
+ timeInfos = nullptr;
+ }
}
- delete in;
return true;
}
@@ -781,7 +764,7 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos
return true;
}
-void ScummEngine::saveInfos(Common::WriteStream* file) {
+void ScummEngine::saveInfos(Common::WriteStream *file) {
SaveInfoSection section;
section.type = MKTAG('I','N','F','O');
section.version = INFOSECTION_VERSION;
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 7b2ff91ad3..c34be5816d 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -47,7 +47,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 94
+#define CURRENT_VER 95
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 2d4c326b68..3da7000ae9 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -27,7 +27,7 @@
#include "scumm/scumm_v3.h"
#include "scumm/scumm_v5.h"
#include "scumm/sound.h"
-#include "scumm/player_towns.h"
+#include "scumm/players/player_towns.h"
#include "scumm/util.h"
#include "scumm/verbs.h"
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index a75e864e7a..6983c51f30 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -394,7 +394,7 @@ ScummEngine_v6::ArrayHeader *ScummEngine_v6::getArray(int array) {
int ScummEngine_v6::readArray(int array, int idx, int base) {
ArrayHeader *ah = getArray(array);
- if (ah == NULL || ah->data == NULL)
+ if (!ah)
error("readArray: invalid array %d (%d)", array, readVar(array));
// WORKAROUND bug #645711. This is clearly a script bug, as this script
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 6aad52578d..ae80f306af 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 Thu May 2 21:27:50 2013
+ This file was generated by the md5table tool on Fri Sep 27 05:44:12 2013
DO NOT EDIT MANUALLY!
*/
@@ -121,9 +121,11 @@ static const MD5Table md5table[] = {
{ "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "Floppy", "Floppy", 7932, Common::EN_ANY, Common::kPlatformDOS },
{ "27b2ef1653089fe5b897d9cc89ce784f", "balloon", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformAmiga },
+ { "288fb75b24389733c29fa107fe8d44e8", "catalog", "HE CUP", "Preview", 10795148, Common::EN_USA, Common::kPlatformUnknown },
{ "28d24a33448fab6795850bc9f159a4a2", "atlantis", "FM-TOWNS", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns },
{ "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformDOS },
{ "28f07458f1b6c24e118a1ea056827701", "lost", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "291fb06071e65897f755846611f5ad40", "ft", "", "7-Wolf", 19697, Common::RU_RUS, Common::kPlatformUnknown },
{ "2a208ffbcd0e83e86f4356e6f64aa6e1", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "2a41b53cf1a90b6e6f26c10cc6041084", "tentacle", "", "Demo", 2439158, Common::EN_ANY, Common::kPlatformMacintosh },
{ "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows },
@@ -238,7 +240,7 @@ static const MD5Table md5table[] = {
{ "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown },
{ "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga },
{ "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown },
- { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
+ { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "Akella", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows },
{ "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii },
@@ -327,6 +329,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 },
@@ -342,6 +345,7 @@ static const MD5Table md5table[] = {
{ "78c07ca088526d8d4446a4c2cb501203", "freddi3", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7974365d3dc0f43a2748c975f91ff042", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "79b05f628586837e7166e82b2279bb50", "loom", "PC-Engine", "", -1, Common::JA_JPN, Common::kPlatformPCEngine },
+ { "7b4ee071eecadc2d8cd0c3509110825c", "puttzoo", "HE 100", "Remastered", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "7bad72e332a59f9fcc1d437f4edad32a", "puttcircus", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "7c2e76087027eeee9c8f8985f93a1cc5", "freddi4", "", "Demo", 13584, Common::EN_ANY, Common::kPlatformUnknown },
{ "7c8100e360e8ef05f88069d4cfa0afd1", "puttrace", "HE 99", "Demo", 13108, Common::EN_GRB, Common::kPlatformWindows },
@@ -534,7 +538,7 @@ static const MD5Table md5table[] = {
{ "ce7733f185b838e248927c7ba1a04204", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformAmiga },
{ "ce7fd0c382389a6791fc3e199c117ef4", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "cea91e3dd47f2518ea418e41611aa77f", "spyfox2", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
- { "cf400d20769fb70eb21766582f4924f7", "moonbase", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "cf400d20769fb70eb21766582f4924f7", "moonbase", "1.0", "1.0", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows },
@@ -582,6 +586,7 @@ static const MD5Table md5table[] = {
{ "e03ed1474ec14de78359970e0457a820", "freddi4", "HE 99", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows },
{ "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", 51152, Common::EN_ANY, Common::kPlatformWindows },
{ "e17db1ddf91b39ca6bbc8ad3ed19e883", "monkey", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
+ { "e1c9998826ce7fa8bde5cc3a5023edec", "moonbase", "1.1", "1.1", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "e246e02db9630533a40d99c9f54a8e01", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "e361a7058ed8e8ebb462663c0a3ae8d6", "puttputt", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformDOS },
{ "e41de1c2a15abbcdbf9977e2d7e8a340", "freddi2", "HE 100", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2a14673855..cc8665e450 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -45,25 +45,26 @@
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/smush/smush_mixer.h"
#include "scumm/smush/smush_player.h"
-#include "scumm/player_towns.h"
+#include "scumm/players/player_towns.h"
#include "scumm/insane/insane.h"
#include "scumm/he/animation_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/sound_he.h"
#include "scumm/object.h"
-#include "scumm/player_nes.h"
-#include "scumm/player_sid.h"
-#include "scumm/player_pce.h"
-#include "scumm/player_apple2.h"
-#include "scumm/player_v1.h"
-#include "scumm/player_v2.h"
-#include "scumm/player_v2cms.h"
-#include "scumm/player_v2a.h"
-#include "scumm/player_v3a.h"
-#include "scumm/player_v3m.h"
-#include "scumm/player_v4a.h"
-#include "scumm/player_v5m.h"
+#include "scumm/players/player_ad.h"
+#include "scumm/players/player_nes.h"
+#include "scumm/players/player_sid.h"
+#include "scumm/players/player_pce.h"
+#include "scumm/players/player_apple2.h"
+#include "scumm/players/player_v1.h"
+#include "scumm/players/player_v2.h"
+#include "scumm/players/player_v2cms.h"
+#include "scumm/players/player_v2a.h"
+#include "scumm/players/player_v3a.h"
+#include "scumm/players/player_v3m.h"
+#include "scumm/players/player_v4a.h"
+#include "scumm/players/player_v5m.h"
#include "scumm/resource.h"
#include "scumm/he/resource_he.h"
#include "scumm/scumm_v0.h"
@@ -1841,6 +1842,15 @@ void ScummEngine::setupMusic(int midi) {
_musicEngine = _townsPlayer = new Player_Towns_v1(this, _mixer);
if (!_townsPlayer->init())
error("Failed to initialize FM-Towns audio driver");
+ } else if (_game.platform == Common::kPlatformDOS && (_sound->_musicType == MDT_ADLIB) && (_game.id == GID_LOOM || _game.id == GID_INDY3)) {
+ // For Indy3 DOS and Loom DOS we use an implementation of the original
+ // AD player when AdLib is selected. This fixes sound effects in those
+ // games (see for example bug #2027877 "INDY3: Non-Looping Sound
+ // Effects"). The player itself is also used in Monkey Island DOS
+ // EGA/VGA. However, we support multi MIDI for that game and we cannot
+ // support this with the Player_AD code at the moment. The reason here
+ // is that multi MIDI is supported internally by our iMuse output.
+ _musicEngine = new Player_AD(this, _mixer);
} else if (_game.version >= 3 && _game.heversion <= 62) {
MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index a77c1c0141..f192a1e256 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -240,6 +240,7 @@ enum ScummGameId {
GID_FBEAR,
GID_PUTTMOON,
GID_FUNPACK,
+ GID_PUTTZOO,
GID_FREDDI3,
GID_BIRTHDAYRED,
GID_BIRTHDAYYELLOW,
@@ -619,15 +620,10 @@ public:
// thumbnail + info stuff
public:
- Graphics::Surface *loadThumbnailFromSlot(int slot) {
- return loadThumbnailFromSlot(_targetName.c_str(), slot);
- }
- static Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot);
-
- static bool loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff);
+ static bool querySaveMetaInfos(const char *target, int slot, int heversion, Common::String &desc, Graphics::Surface *&thumbnail, SaveStateMetaInfos *&timeInfos);
protected:
- void saveInfos(Common::WriteStream* file);
+ void saveInfos(Common::WriteStream *file);
static bool loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos *stuff);
protected:
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 3f6290f8fc..071805752b 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -30,7 +30,7 @@
#include "scumm/file.h"
#include "scumm/imuse/imuse.h"
#include "scumm/imuse_digi/dimuse.h"
-#include "scumm/player_towns.h"
+#include "scumm/players/player_towns.h"
#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
@@ -470,8 +470,10 @@ static int compareMP3OffsetTable(const void *a, const void *b) {
void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle *handle) {
int num = 0, i;
- int size = 0;
int id = -1;
+#if defined(USE_FLAC) || defined(USE_VORBIS) || defined(USE_MAD)
+ int size = 0;
+#endif
Common::ScopedPtr<ScummFile> file;
if (_vm->_game.id == GID_CMI) {
@@ -562,10 +564,14 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
num = result->num_tags;
}
offset = result->new_offset;
+#if defined(USE_FLAC) || defined(USE_VORBIS) || defined(USE_MAD)
size = result->compressed_size;
+#endif
} else {
offset += 8;
+#if defined(USE_FLAC) || defined(USE_VORBIS) || defined(USE_MAD)
size = -1;
+#endif
}
file.reset(new ScummFile());
@@ -1930,7 +1936,6 @@ int ScummEngine::readSoundResourceSmallHeader(ResId idx) {
// 8 bytes MTrk header
// 7 bytes MIDI tempo sysex
// + some default instruments
- byte *ptr;
if (_game.features & GF_OLD_BUNDLE) {
ad_size -= 4;
_fileHandle->seek(ad_offs + 4, SEEK_SET);
@@ -1938,10 +1943,17 @@ int ScummEngine::readSoundResourceSmallHeader(ResId idx) {
ad_size -= 6;
_fileHandle->seek(ad_offs, SEEK_SET);
}
- ptr = (byte *) calloc(ad_size, 1);
- _fileHandle->read(ptr, ad_size);
- convertADResource(_res, _game, idx, ptr, ad_size);
- free(ptr);
+ // For games using AD except Indy3 and Loom we are using our iMuse
+ // implementation. See output initialization in
+ // ScummEngine::setupMusic for more information.
+ if (_game.id != GID_INDY3 && _game.id != GID_LOOM) {
+ byte *ptr = (byte *)calloc(ad_size, 1);
+ _fileHandle->read(ptr, ad_size);
+ convertADResource(_res, _game, idx, ptr, ad_size);
+ free(ptr);
+ } else {
+ _fileHandle->read(_res->createResource(rtSound, idx, ad_size), ad_size);
+ }
return 1;
} else if (ro_offs != 0) {
_fileHandle->seek(ro_offs - 2, SEEK_SET);
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 77c7daa0df..9c90d7575d 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -714,6 +714,12 @@ void ScummEngine_v99he::resetScummVars() {
VAR(140) = 0;
#endif
}
+
+ if (_game.id == GID_PUTTZOO && _game.heversion == 100 && _game.platform == Common::kPlatformWindows) {
+ // Specific to Nimbus Games version.
+ VAR(156) = 1;
+ VAR(157) = 0;
+ }
}
#endif
diff --git a/engines/sky/POTFILES b/engines/sky/POTFILES
new file mode 100644
index 0000000000..6c39f82e75
--- /dev/null
+++ b/engines/sky/POTFILES
@@ -0,0 +1,2 @@
+engines/sky/compact.cpp
+engines/sky/detection.cpp
diff --git a/engines/sky/configure.engine b/engines/sky/configure.engine
new file mode 100644
index 0000000000..32b84849cb
--- /dev/null
+++ b/engines/sky/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine sky "Beneath a Steel Sky" yes
diff --git a/engines/sky/music/musicbase.cpp b/engines/sky/music/musicbase.cpp
index b388afdb13..944edb1fdc 100644
--- a/engines/sky/music/musicbase.cpp
+++ b/engines/sky/music/musicbase.cpp
@@ -44,9 +44,9 @@ MusicBase::~MusicBase() {
}
void MusicBase::loadSection(uint8 pSection) {
- Common::StackLock lock(_mutex);
if (_currentMusic)
stopMusicInternal();
+ Common::StackLock lock(_mutex);
free(_musicData);
_currentSection = pSection;
_musicData = _skyDisk->loadFile(_driverFileBase + FILES_PER_SECTION * pSection);
@@ -70,13 +70,14 @@ bool MusicBase::musicIsPlaying() {
}
void MusicBase::stopMusic() {
- Common::StackLock lock(_mutex);
stopMusicInternal();
}
void MusicBase::stopMusicInternal() {
_mixer->stopHandle(_musicHandle);
+ Common::StackLock lock(_mutex);
+
for (uint8 cnt = 0; cnt < _numberOfChannels; cnt++)
delete _channels[cnt];
_numberOfChannels = 0;
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index fd90015aa3..4c47dfafc7 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -187,9 +187,14 @@ Common::Error SkyEngine::go() {
}
if (!shouldQuit()) {
- _skyLogic->initScreen0();
+ // restartGame() takes us to the first scene, without showing the
+ // initial animation where Foster is being chased. initScreen0()
+ // shows the first scene together with that animation. We can't
+ // call both, as they both load the same scene.
if (introSkipped)
_skyControl->restartGame();
+ else
+ _skyLogic->initScreen0();
}
}
diff --git a/engines/sword1/POTFILES b/engines/sword1/POTFILES
new file mode 100644
index 0000000000..849bef9060
--- /dev/null
+++ b/engines/sword1/POTFILES
@@ -0,0 +1,4 @@
+engines/sword1/animation.cpp
+engines/sword1/control.cpp
+engines/sword1/logic.cpp
+engines/sword1/sword1.cpp
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 206bd68b07..742aac1a53 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()) {
@@ -308,7 +314,7 @@ bool MoviePlayer::playVideo() {
if (_decoderType == kVideoDecoderPSX)
drawFramePSX(frame);
else
- _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
}
if (_decoder->hasDirtyPalette()) {
@@ -401,7 +407,7 @@ bool MoviePlayer::playVideo() {
}
Graphics::Surface *screen = _vm->_system->lockScreen();
- performPostProcessing((byte *)screen->pixels);
+ performPostProcessing((byte *)screen->getPixels());
_vm->_system->unlockScreen();
_vm->_system->updateScreen();
}
@@ -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:
@@ -493,7 +498,7 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
uint16 x = (g_system->getWidth() - scaledFrame.w) / 2;
uint16 y = (g_system->getHeight() - scaledFrame.h) / 2;
- _vm->_system->copyRectToScreen(scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
+ _vm->_system->copyRectToScreen(scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
scaledFrame.free();
}
@@ -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/sword1/configure.engine b/engines/sword1/configure.engine
new file mode 100644
index 0000000000..0578d176a9
--- /dev/null
+++ b/engines/sword1/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine sword1 "Broken Sword" yes
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index c34630aceb..f31faffd5e 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -110,7 +110,7 @@ bool MusicHandle::play(const Common::String &filename, bool loop) {
return true;
}
-bool MusicHandle::playPSX(uint16 id) {
+bool MusicHandle::playPSX(uint16 id, bool loop) {
stop();
if (!_file.isOpen())
@@ -131,7 +131,7 @@ bool MusicHandle::playPSX(uint16 id) {
// not over file size
if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= _file.size())) {
_file.seek(offset, SEEK_SET);
- _audioSource = Audio::makeXAStream(_file.readStream(size), 11025);
+ _audioSource = Audio::makeLoopingAudioStream(Audio::makeXAStream(_file.readStream(size), 11025), loop ? 0 : 1);
fadeUp();
} else {
_audioSource = NULL;
@@ -297,7 +297,7 @@ void Music::startMusic(int32 tuneId, int32 loopFlag) {
the mutex before, to have the soundthread playing normally.
As the corresponding _converter is NULL, the handle will be ignored by the playing thread */
if (SwordEngine::isPsx()) {
- if (_handles[newStream].playPSX(tuneId)) {
+ if (_handles[newStream].playPSX(tuneId, loopFlag != 0)) {
_mutex.lock();
_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
_mutex.unlock();
diff --git a/engines/sword1/music.h b/engines/sword1/music.h
index f1366202d7..4207019c13 100644
--- a/engines/sword1/music.h
+++ b/engines/sword1/music.h
@@ -44,7 +44,7 @@ public:
MusicHandle() : _fading(0), _audioSource(NULL) {}
virtual int readBuffer(int16 *buffer, const int numSamples);
bool play(const Common::String &filename, bool loop);
- bool playPSX(uint16 id);
+ bool playPSX(uint16 id, bool loop);
void stop();
void fadeUp();
void fadeDown();
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index ae128b8c05..76957e0a70 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -57,6 +57,30 @@ Screen::Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
_psxCache.extPlxCache = NULL;
_oldScrollX = 0;
_oldScrollY = 0;
+
+ _textMan = 0;
+
+ for (int i = 0; i < 4; i++)
+ _layerGrid[i] = 0;
+
+ for (int i = 0; i < 4; i++)
+ _layerBlocks[i] = 0;
+
+ _parallax[0] = 0;
+ _parallax[1] = 0;
+
+ _fullRefresh = 0;
+
+ for (int i = 0; i < MAX_SORT; i++) {
+ _sortList[i].id = 0;
+ _sortList[i].y = 0;
+ }
+ _scrnSizeX = 0;
+ _scrnSizeY = 0;
+ _gridSizeX = 0;
+ _gridSizeY = 0;
+ _fadingDirection = 0;
+ _isBlack = 0;
}
Screen::~Screen() {
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 268da74508..643657c71f 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -269,9 +269,8 @@ void Sound::playSample(QueueElement *elem) {
uint8 volume = (volR + volL) / 2;
if (SwordEngine::isPsx()) {
- // We ignore FX_LOOP as XA has its own looping mechanism
uint32 size = READ_LE_UINT32(sampleData);
- Audio::AudioStream *audStream = Audio::makeXAStream(new Common::MemoryReadStream(sampleData + 4, size - 4), 11025);
+ Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(Audio::makeXAStream(new Common::MemoryReadStream(sampleData + 4, size - 4), 11025), (_fxList[elem->id].type == FX_LOOP) ? 0 : 1);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &elem->handle, audStream, elem->id, volume, pan);
} else {
uint32 size = READ_LE_UINT32(sampleData + 0x28);
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 2d5452778d..5738431dce 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -67,6 +67,17 @@ SwordEngine::SwordEngine(OSystem *syst)
SearchMan.addSubDirectoryMatching(gameDataDir, "italian"); // PSX Demo
_console = new SwordConsole(this);
+
+ _mouseState = 0;
+ _resMan = 0;
+ _objectMan = 0;
+ _screen = 0;
+ _mouse = 0;
+ _logic = 0;
+ _sound = 0;
+ _menu = 0;
+ _music = 0;
+ _control = 0;
}
SwordEngine::~SwordEngine() {
diff --git a/engines/sword2/POTFILES b/engines/sword2/POTFILES
new file mode 100644
index 0000000000..94ad720989
--- /dev/null
+++ b/engines/sword2/POTFILES
@@ -0,0 +1,2 @@
+engines/sword2/animation.cpp
+engines/sword2/sword2.cpp
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 00260f789a..92fa9d0e44 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) {
@@ -328,7 +334,7 @@ bool MoviePlayer::playVideo() {
if (_decoderType == kVideoDecoderPSX)
drawFramePSX(frame);
else
- _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
}
if (_decoder->hasDirtyPalette()) {
@@ -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) {
@@ -397,7 +403,7 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
uint16 x = (g_system->getWidth() - scaledFrame.w) / 2;
uint16 y = (g_system->getHeight() - scaledFrame.h) / 2;
- _vm->_system->copyRectToScreen(scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
+ _vm->_system->copyRectToScreen(scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
scaledFrame.free();
}
@@ -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/sword2/configure.engine b/engines/sword2/configure.engine
new file mode 100644
index 0000000000..7153605433
--- /dev/null
+++ b/engines/sword2/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine sword2 "Broken Sword II" yes
diff --git a/engines/sword25/configure.engine b/engines/sword25/configure.engine
new file mode 100644
index 0000000000..1729bbeb33
--- /dev/null
+++ b/engines/sword25/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine sword25 "Broken Sword 2.5" no "" "" "png zlib 16bit"
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index a95532ec65..3cdce1b493 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -130,10 +130,10 @@ void MoviePlayer::update() {
assert(s->format.bytesPerPixel == 4);
#ifdef THEORA_INDIRECT_RENDERING
- const byte *frameData = (const byte *)s->getBasePtr(0, 0);
+ const byte *frameData = (const byte *)s->getPixels();
_outputBitmap->setContent(frameData, s->pitch * s->h, 0, s->pitch);
#else
- g_system->copyRectToScreen(s->getBasePtr(0, 0), s->pitch, _outX, _outY, MIN(s->w, _backSurface->w), MIN(s->h, _backSurface->h));
+ g_system->copyRectToScreen(s->getPixels(), s->pitch, _outX, _outY, MIN(s->w, _backSurface->w), MIN(s->h, _backSurface->h));
g_system->updateScreen();
#endif
}
diff --git a/engines/sword25/gfx/animation.cpp b/engines/sword25/gfx/animation.cpp
index 1660c393c0..37207c967b 100644
--- a/engines/sword25/gfx/animation.cpp
+++ b/engines/sword25/gfx/animation.cpp
@@ -553,15 +553,15 @@ bool Animation::persist(OutputPersistenceBlock &writer) {
writer.write(_currentFrameTime);
writer.write(_running);
writer.write(_finished);
- writer.write(static_cast<uint>(_direction));
+ writer.write(static_cast<uint32>(_direction));
// Je nach Animationstyp entweder das Template oder die Ressource speichern.
if (_animationResourcePtr) {
- uint marker = 0;
+ uint32 marker = 0;
writer.write(marker);
writer.writeString(_animationResourcePtr->getFileName());
} else if (_animationTemplateHandle) {
- uint marker = 1;
+ uint32 marker = 1;
writer.write(marker);
writer.write(_animationTemplateHandle);
} else {
@@ -574,13 +574,13 @@ bool Animation::persist(OutputPersistenceBlock &writer) {
// The following is only there to for compatibility with older saves
// resp. the original engine.
- writer.write((uint)1);
+ writer.write((uint32)1);
writer.writeString("LuaLoopPointCB");
writer.write(getHandle());
- writer.write((uint)1);
+ writer.write((uint32)1);
writer.writeString("LuaActionCB");
writer.write(getHandle());
- writer.write((uint)1);
+ writer.write((uint32)1);
writer.writeString("LuaDeleteCB");
writer.write(getHandle());
@@ -605,12 +605,12 @@ bool Animation::unpersist(InputPersistenceBlock &reader) {
reader.read(_currentFrameTime);
reader.read(_running);
reader.read(_finished);
- uint direction;
+ uint32 direction;
reader.read(direction);
_direction = static_cast<Direction>(direction);
// Animationstyp einlesen.
- uint marker;
+ uint32 marker;
reader.read(marker);
if (marker == 0) {
Common::String resourceFilename;
@@ -629,9 +629,9 @@ bool Animation::unpersist(InputPersistenceBlock &reader) {
// The following is only there to for compatibility with older saves
// resp. the original engine.
- uint callbackCount;
+ uint32 callbackCount;
Common::String callbackFunctionName;
- uint callbackData;
+ uint32 callbackData;
// loop point callback
reader.read(callbackCount);
diff --git a/engines/sword25/gfx/animation.h b/engines/sword25/gfx/animation.h
index 44255e3b64..ced1995ae9 100644
--- a/engines/sword25/gfx/animation.h
+++ b/engines/sword25/gfx/animation.h
@@ -159,18 +159,18 @@ private:
BACKWARD
};
- int _relX;
- int _relY;
+ int32 _relX;
+ int32 _relY;
float _scaleFactorX;
float _scaleFactorY;
- uint _modulationColor;
- uint _currentFrame;
- int _currentFrameTime;
+ uint32 _modulationColor;
+ uint32 _currentFrame;
+ int32 _currentFrameTime;
bool _running;
bool _finished;
Direction _direction;
AnimationResource *_animationResourcePtr;
- uint _animationTemplateHandle;
+ uint32 _animationTemplateHandle;
bool _framesLocked;
ANIMATION_CALLBACK _loopPointCallback;
diff --git a/engines/sword25/gfx/animationdescription.cpp b/engines/sword25/gfx/animationdescription.cpp
index da0a660df9..164206bbc2 100644
--- a/engines/sword25/gfx/animationdescription.cpp
+++ b/engines/sword25/gfx/animationdescription.cpp
@@ -36,7 +36,7 @@
namespace Sword25 {
bool AnimationDescription::persist(OutputPersistenceBlock &writer) {
- writer.write(static_cast<uint>(_animationType));
+ writer.write(static_cast<uint32>(_animationType));
writer.write(_FPS);
writer.write(_millisPerFrame);
writer.write(_scalingAllowed);
@@ -47,7 +47,7 @@ bool AnimationDescription::persist(OutputPersistenceBlock &writer) {
}
bool AnimationDescription::unpersist(InputPersistenceBlock &reader) {
- uint animationType;
+ uint32 animationType;
reader.read(animationType);
_animationType = static_cast<Animation::ANIMATION_TYPES>(animationType);
reader.read(_FPS);
diff --git a/engines/sword25/gfx/animationdescription.h b/engines/sword25/gfx/animationdescription.h
index 3b11686bb9..009d83dcc7 100644
--- a/engines/sword25/gfx/animationdescription.h
+++ b/engines/sword25/gfx/animationdescription.h
@@ -52,8 +52,8 @@ protected:
public:
struct Frame {
// Die Hotspot-Angabe bezieht sich auf das ungeflippte Bild!!
- int hotspotX;
- int hotspotY;
+ int32 hotspotX;
+ int32 hotspotY;
bool flipV;
bool flipH;
Common::String fileName;
@@ -88,8 +88,8 @@ public:
protected:
Animation::ANIMATION_TYPES _animationType;
- int _FPS;
- int _millisPerFrame;
+ int32 _FPS;
+ int32 _millisPerFrame;
bool _scalingAllowed;
bool _alphaAllowed;
bool _colorModulationAllowed;
diff --git a/engines/sword25/gfx/animationresource.cpp b/engines/sword25/gfx/animationresource.cpp
index 621e20ad8c..8c09a545a0 100644
--- a/engines/sword25/gfx/animationresource.cpp
+++ b/engines/sword25/gfx/animationresource.cpp
@@ -188,7 +188,7 @@ bool AnimationResource::parserCallback_frame(ParserNode *node) {
Common::String flipHString = node->values["fliph"];
if (!flipHString.empty()) {
- if (!parseBooleanKey(flipVString, frame.flipV)) {
+ if (!parseBooleanKey(flipHString, frame.flipH)) {
warning("Illegal fliph value (\"%s\") in <frame> tag in \"%s\". Assuming default (\"false\").",
flipHString.c_str(), getFileName().c_str());
frame.flipH = false;
diff --git a/engines/sword25/gfx/animationtemplate.cpp b/engines/sword25/gfx/animationtemplate.cpp
index 19924302b9..a1d2bf5d1a 100644
--- a/engines/sword25/gfx/animationtemplate.cpp
+++ b/engines/sword25/gfx/animationtemplate.cpp
@@ -181,7 +181,7 @@ bool AnimationTemplate::persist(OutputPersistenceBlock &writer) {
Result &= AnimationDescription::persist(writer);
// Frameanzahl schreiben.
- writer.write(_frames.size());
+ writer.write((uint32)_frames.size());
// Frames einzeln persistieren.
Common::Array<const Frame>::const_iterator Iter = _frames.begin();
@@ -209,7 +209,7 @@ bool AnimationTemplate::unpersist(InputPersistenceBlock &reader) {
result &= AnimationDescription::unpersist(reader);
// Frameanzahl lesen.
- uint frameCount;
+ uint32 frameCount;
reader.read(frameCount);
// Frames einzeln wieder herstellen.
diff --git a/engines/sword25/gfx/animationtemplateregistry.cpp b/engines/sword25/gfx/animationtemplateregistry.cpp
index 8184b49eba..4cefe24b18 100644
--- a/engines/sword25/gfx/animationtemplateregistry.cpp
+++ b/engines/sword25/gfx/animationtemplateregistry.cpp
@@ -47,7 +47,7 @@ bool AnimationTemplateRegistry::persist(OutputPersistenceBlock &writer) {
writer.write(_nextHandle);
// Anzahl an BS_AnimationTemplates schreiben.
- writer.write(_handle2PtrMap.size());
+ writer.write((uint32)_handle2PtrMap.size());
// Alle BS_AnimationTemplates persistieren.
HANDLE2PTR_MAP::const_iterator iter = _handle2PtrMap.begin();
@@ -77,13 +77,13 @@ bool AnimationTemplateRegistry::unpersist(InputPersistenceBlock &reader) {
delete _handle2PtrMap.begin()->_value;
// Anzahl an BS_AnimationTemplates einlesen.
- uint animationTemplateCount;
+ uint32 animationTemplateCount;
reader.read(animationTemplateCount);
// Alle gespeicherten BS_AnimationTemplates wieder herstellen.
for (uint i = 0; i < animationTemplateCount; ++i) {
// Handle lesen.
- uint handle;
+ uint32 handle;
reader.read(handle);
// BS_AnimationTemplate wieder herstellen.
diff --git a/engines/sword25/gfx/bitmap.h b/engines/sword25/gfx/bitmap.h
index caa1238558..f22c5d7fc9 100644
--- a/engines/sword25/gfx/bitmap.h
+++ b/engines/sword25/gfx/bitmap.h
@@ -176,9 +176,9 @@ protected:
bool _flipV;
float _scaleFactorX;
float _scaleFactorY;
- uint _modulationColor;
- int _originalWidth;
- int _originalHeight;
+ uint32 _modulationColor;
+ int32 _originalWidth;
+ int32 _originalHeight;
};
} // End of namespace Sword25
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/art.cpp b/engines/sword25/gfx/image/art.cpp
index 9c4b9fe8bd..e2eeaca33f 100644
--- a/engines/sword25/gfx/image/art.cpp
+++ b/engines/sword25/gfx/image/art.cpp
@@ -424,8 +424,7 @@ static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max,
x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
} else {
// don't subdivide
- art_vpath_add_point(p_vpath, pn, pn_max,
- ART_LINETO, x3, y3);
+ art_vpath_add_point(p_vpath, pn, pn_max, ART_LINETO, x3, y3);
}
}
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/imgloader.cpp b/engines/sword25/gfx/image/imgloader.cpp
index e103626416..9006a596b4 100644
--- a/engines/sword25/gfx/image/imgloader.cpp
+++ b/engines/sword25/gfx/image/imgloader.cpp
@@ -50,7 +50,7 @@ bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&un
width = pngSurface->w;
height = pngSurface->h;
uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h];
- memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h);
+ memcpy(uncompressedDataPtr, (byte *)pngSurface->getPixels(), pngSurface->pitch * pngSurface->h);
pngSurface->free();
delete pngSurface;
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index c8a6666046..b359fc6a3e 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 {
@@ -239,25 +240,13 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
int cg = (color >> 8) & 0xff;
int cb = (color >> 0) & 0xff;
- // Compensate for transparency. Since we're coming
- // down to 255 alpha, we just compensate for the colors here
- if (ca != 255) {
- cr = cr * ca >> 8;
- cg = cg * ca >> 8;
- cb = cb * ca >> 8;
- }
-
// Create an encapsulating surface for the data
Graphics::Surface srcImage;
// TODO: Is the data really in the screen format?
- srcImage.format = g_system->getScreenFormat();
- srcImage.pitch = _width * 4;
- srcImage.w = _width;
- srcImage.h = _height;
- srcImage.pixels = _data;
+ srcImage.init(_width, _height, _width * 4, _data, g_system->getScreenFormat());
if (pPartRect) {
- srcImage.pixels = &_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4];
+ srcImage.setPixels(&_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]);
srcImage.w = pPartRect->right - pPartRect->left;
srcImage.h = pPartRect->bottom - pPartRect->top;
@@ -286,14 +275,14 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
if ((width != srcImage.w) || (height != srcImage.h)) {
// Scale the image
img = imgScaled = scale(srcImage, width, height);
- savedPixels = (byte *)img->pixels;
+ savedPixels = (byte *)img->getPixels();
} else {
img = &srcImage;
}
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 +294,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 +303,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 +318,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 +339,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 +349,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 +359,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)
@@ -403,52 +392,52 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
} else {
#if defined(SCUMM_LITTLE_ENDIAN)
pix = *(uint32 *)out;
- int outb = (pix >> 0) & 0xff;
- int outg = (pix >> 8) & 0xff;
- int outr = (pix >> 16) & 0xff;
+ int outb = ((pix >> 0) & 0xff) * (255 - a);
+ int outg = ((pix >> 8) & 0xff) * (255 - a);
+ int outr = ((pix >> 16) & 0xff) * (255 - a);
if (cb == 0)
- outb = 0;
+ outb = outb >> 8;
else if (cb != 255)
- outb += ((b - outb) * a * cb) >> 16;
+ outb = ((outb << 8) + b * a * cb) >> 16;
else
- outb += ((b - outb) * a) >> 8;
+ outb = (outb + b * a) >> 8;
if (cg == 0)
- outg = 0;
+ outg = outg >> 8;
else if (cg != 255)
- outg += ((g - outg) * a * cg) >> 16;
+ outg = ((outg << 8) + g * a * cg) >> 16;
else
- outg += ((g - outg) * a) >> 8;
+ outg = (outg + g * a) >> 8;
if (cr == 0)
- outr = 0;
+ outr = outr >> 8;
else if (cr != 255)
- outr += ((r - outr) * a * cr) >> 16;
+ outr = ((outr << 8) + r * a * cr) >> 16;
else
- outr += ((r - outr) * a) >> 8;
+ outr = (outr + r * a) >> 8;
*(uint32 *)out = (255 << 24) | (outr << 16) | (outg << 8) | outb;
out += 4;
#else
*out = 255;
out++;
if (cr == 0)
- *out = 0;
+ *out = (*out * (255-a)) >> 8;
else if (cr != 255)
- *out += ((r - *out) * a * cr) >> 16;
+ *out = (((*out * (255-a)) << 8) + r * a * cr) >> 16;
else
- *out += ((r - *out) * a) >> 8;
+ *out = ((*out * (255-a)) + r * a) >> 8;
out++;
if (cg == 0)
- *out = 0;
+ *out = (*out * (255-a)) >> 8;
else if (cg != 255)
- *out += ((g - *out) * a * cg) >> 16;
+ *out = (((*out * (255-a)) << 8) + g * a * cg) >> 16;
else
- *out += ((g - *out) * a) >> 8;
+ *out = ((*out * (255-a)) + g * a) >> 8;
out++;
if (cb == 0)
- *out = 0;
+ *out = (*out * (255-a)) >> 8;
else if (cb != 255)
- *out += ((b - *out) * a * cb) >> 16;
+ *out = (((*out * (255-a)) << 8) + b * a * cb) >> 16;
else
- *out += ((b - *out) * a) >> 8;
+ *out = ((*out * (255-a)) + b * a) >> 8;
out++;
#endif
}
@@ -459,11 +448,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
}
}
-
+
}
if (imgScaled) {
- imgScaled->pixels = savedPixels;
+ imgScaled->setPixels(savedPixels);
imgScaled->free();
delete imgScaled;
}
@@ -509,60 +498,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/microtiles.cpp b/engines/sword25/gfx/microtiles.cpp
index 8dceed5348..18e4a9a1fb 100644
--- a/engines/sword25/gfx/microtiles.cpp
+++ b/engines/sword25/gfx/microtiles.cpp
@@ -119,7 +119,6 @@ RectangleList *MicroTileArray::getRectangles() {
for (y = 0; y < _tilesH; ++y) {
for (x = 0; x < _tilesW; ++x) {
- int start;
int finish = 0;
BoundingBox boundingBox = _tiles[i];
@@ -132,8 +131,6 @@ RectangleList *MicroTileArray::getRectangles() {
y0 = (y * TileSize) + TileY0(boundingBox);
y1 = (y * TileSize) + TileY1(boundingBox);
- start = i;
-
if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) { // check if the tile continues
while (!finish) {
++x;
diff --git a/engines/sword25/gfx/panel.cpp b/engines/sword25/gfx/panel.cpp
index 931b9cdbe7..9b7fe82914 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;
}
@@ -104,7 +104,7 @@ bool Panel::unpersist(InputPersistenceBlock &reader) {
result &= RenderObject::unpersist(reader);
- uint color;
+ uint32 color;
reader.read(color);
setColor(color);
diff --git a/engines/sword25/gfx/panel.h b/engines/sword25/gfx/panel.h
index 74a93247b6..d372b4e0fc 100644
--- a/engines/sword25/gfx/panel.h
+++ b/engines/sword25/gfx/panel.h
@@ -64,7 +64,7 @@ protected:
virtual bool doRender(RectangleList *updateRects);
private:
- uint _color;
+ uint32 _color;
};
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp
index 807c1eb64b..e9e11aae4e 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
@@ -219,27 +219,27 @@ Common::Rect RenderObject::calcBoundingBox() const {
return bbox;
}
-void RenderObject::calcAbsolutePos(int &x, int &y, int &z) const {
+void RenderObject::calcAbsolutePos(int32 &x, int32 &y, int32 &z) const {
x = calcAbsoluteX();
y = calcAbsoluteY();
z = calcAbsoluteZ();
}
-int RenderObject::calcAbsoluteX() const {
+int32 RenderObject::calcAbsoluteX() const {
if (_parentPtr.isValid())
return _parentPtr->getAbsoluteX() + _x;
else
return _x;
}
-int RenderObject::calcAbsoluteY() const {
+int32 RenderObject::calcAbsoluteY() const {
if (_parentPtr.isValid())
return _parentPtr->getAbsoluteY() + _y;
else
return _y;
}
-int RenderObject::calcAbsoluteZ() const {
+int32 RenderObject::calcAbsoluteZ() const {
if (_parentPtr.isValid())
return _parentPtr->getAbsoluteZ() + _z;
else
@@ -399,7 +399,7 @@ RenderObjectPtr<Text> RenderObject::addText(const Common::String &font, const Co
bool RenderObject::persist(OutputPersistenceBlock &writer) {
// Typ und Handle werden als erstes gespeichert, damit beim Laden ein Objekt vom richtigen Typ mit dem richtigen Handle erzeugt werden kann.
- writer.write(static_cast<uint>(_type));
+ writer.write(static_cast<uint32>(_type));
writer.write(_handle);
// Restliche Objekteigenschaften speichern.
@@ -413,14 +413,14 @@ bool RenderObject::persist(OutputPersistenceBlock &writer) {
writer.write(_visible);
writer.write(_childChanged);
writer.write(_initSuccess);
- writer.write(_bbox.left);
- writer.write(_bbox.top);
- writer.write(_bbox.right);
- writer.write(_bbox.bottom);
- writer.write(_oldBbox.left);
- writer.write(_oldBbox.top);
- writer.write(_oldBbox.right);
- writer.write(_oldBbox.bottom);
+ writer.write((int32)_bbox.left);
+ writer.write((int32)_bbox.top);
+ writer.write((int32)_bbox.right);
+ writer.write((int32)_bbox.bottom);
+ writer.write((int32)_oldBbox.left);
+ writer.write((int32)_oldBbox.top);
+ writer.write((int32)_oldBbox.right);
+ writer.write((int32)_oldBbox.bottom);
writer.write(_oldX);
writer.write(_oldY);
writer.write(_oldZ);
@@ -455,7 +455,7 @@ bool RenderObject::unpersist(InputPersistenceBlock &reader) {
reader.read(_oldY);
reader.read(_oldZ);
reader.read(_oldVisible);
- uint parentHandle;
+ uint32 parentHandle;
reader.read(parentHandle);
_parentPtr = RenderObjectPtr<RenderObject>(parentHandle);
reader.read(_refreshForced);
@@ -470,7 +470,7 @@ bool RenderObject::persistChildren(OutputPersistenceBlock &writer) {
bool result = true;
// Kinderanzahl speichern.
- writer.write(_children.size());
+ writer.write((uint32)_children.size());
// Rekursiv alle Kinder speichern.
RENDEROBJECT_LIST::iterator it = _children.begin();
@@ -486,13 +486,13 @@ bool RenderObject::unpersistChildren(InputPersistenceBlock &reader) {
bool result = true;
// Kinderanzahl einlesen.
- uint childrenCount;
+ uint32 childrenCount;
reader.read(childrenCount);
if (!reader.isGood())
return false;
// Alle Kinder rekursiv wieder herstellen.
- for (uint i = 0; i < childrenCount; ++i) {
+ for (uint32 i = 0; i < childrenCount; ++i) {
if (!recreatePersistedRenderObject(reader).isValid())
return false;
}
@@ -504,8 +504,8 @@ RenderObjectPtr<RenderObject> RenderObject::recreatePersistedRenderObject(InputP
RenderObjectPtr<RenderObject> result;
// Typ und Handle auslesen.
- uint type;
- uint handle;
+ uint32 type;
+ uint32 handle;
reader.read(type);
reader.read(handle);
if (!reader.isGood())
diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h
index 7e0334ee88..7fcd3a87a3 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.
*/
@@ -359,15 +359,15 @@ public:
/**
@brief Gibt das Handle des Objekte zurück.
*/
- uint getHandle() const {
+ uint32 getHandle() const {
return _handle;
}
- // Get the RenderObjects current version
+ // Get the RenderObjects current version
int getVersion() const {
return _version;
}
-
+
bool isSolid() const {
return _isSolid;
}
@@ -388,14 +388,14 @@ protected:
typedef Common::List<RenderObjectPtr<RenderObject> > RENDEROBJECT_LIST;
typedef Common::List<RenderObjectPtr<RenderObject> >::iterator RENDEROBJECT_ITER;
- int _x; ///< Die X-Position des Objektes relativ zum Eltern-Objekt
- int _y; ///< Die Y-Position des Objektes relativ zum Eltern-Objekt
- int _z; ///< Der Z-Wert des Objektes relativ zum Eltern-Objekt
- int _absoluteX; ///< Die absolute X-Position des Objektes
- int _absoluteY; ///< Die absolute Y-Position des Objektes
- int _absoluteZ;
- int _width; ///< Die Breite des Objektes
- int _height; ///< Die Höhe des Objektes
+ int32 _x; ///< Die X-Position des Objektes relativ zum Eltern-Objekt
+ int32 _y; ///< Die Y-Position des Objektes relativ zum Eltern-Objekt
+ int32 _z; ///< Der Z-Wert des Objektes relativ zum Eltern-Objekt
+ int32 _absoluteX; ///< Die absolute X-Position des Objektes
+ int32 _absoluteY; ///< Die absolute Y-Position des Objektes
+ int32 _absoluteZ;
+ int32 _width; ///< Die Breite des Objektes
+ int32 _height; ///< Die Höhe des Objektes
bool _visible; ///< Ist true, wenn das Objekt sichtbar ist
bool _childChanged; ///< Ist true, wenn sich ein Kinderobjekt verändert hat
TYPES _type; ///< Der Objekttyp
@@ -404,14 +404,14 @@ protected:
// Kopien der Variablen, die für die Errechnung des Dirty-Rects und zur Bestimmung der Objektveränderung notwendig sind
Common::Rect _oldBbox;
- int _oldX;
- int _oldY;
- int _oldZ;
+ int32 _oldX;
+ int32 _oldY;
+ int32 _oldZ;
bool _oldVisible;
static int _nextGlobalVersion;
-
- int _version;
+
+ int32 _version;
// This should be set to true if the RenderObject is NOT alpha-blended to optimize drawing
bool _isSolid;
@@ -475,7 +475,7 @@ private:
/// Ist true, wenn das Objekt in nächsten Frame neu gezeichnet werden soll
bool _refreshForced;
- uint _handle;
+ uint32 _handle;
/**
@brief Entfernt ein Objekt aus der Kinderliste.
@@ -500,18 +500,18 @@ private:
/**
@brief Berechnet die absolute Position des Objektes.
*/
- void calcAbsolutePos(int &x, int &y, int &z) const;
+ void calcAbsolutePos(int32 &x, int32 &y, int32 &z) const;
/**
@brief Berechnet die absolute Position des Objektes auf der X-Achse.
*/
- int calcAbsoluteX() const;
+ int32 calcAbsoluteX() const;
/**
@brief Berechnet die absolute Position des Objektes.
*/
- int calcAbsoluteY() const;
-
- int calcAbsoluteZ() const;
-
+ int32 calcAbsoluteY() const;
+
+ int32 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..bc7dd02636 100644
--- a/engines/sword25/gfx/renderobjectmanager.cpp
+++ b/engines/sword25/gfx/renderobjectmanager.cpp
@@ -103,17 +103,20 @@ bool RenderObjectManager::render() {
_uta->clear();
// Add rectangles of objects which don't exist in this frame any more
- for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it)
- if (!_currQueue->exists(*it))
- _uta->addRect((*it)._bbox);
- // Add rectangles of objects which are different from the previous frame
- for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it)
- if (!_prevQueue->exists(*it))
- _uta->addRect((*it)._bbox);
+ for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it) {
+ if (!_currQueue->exists(*it))
+ _uta->addRect((*it)._bbox);
+ }
+
+ // Add rectangles of objects which are different from the previous frame
+ for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it) {
+ if (!_prevQueue->exists(*it))
+ _uta->addRect((*it)._bbox);
+ }
RectangleList *updateRects = _uta->getRectangles();
Common::Array<int> updateRectsMinZ;
-
+
updateRectsMinZ.reserve(updateRects->size());
// Calculate the minimum drawing Z value of each update rectangle
@@ -144,9 +147,9 @@ bool RenderObjectManager::render() {
}
delete updateRects;
-
+
SWAP(_currQueue, _prevQueue);
-
+
return true;
}
@@ -171,7 +174,7 @@ bool RenderObjectManager::persist(OutputPersistenceBlock &writer) {
writer.write(_frameStarted);
// Referenzen auf die TimedRenderObjects persistieren.
- writer.write(_timedRenderObjects.size());
+ writer.write((uint32)_timedRenderObjects.size());
RenderObjectList::const_iterator iter = _timedRenderObjects.begin();
while (iter != _timedRenderObjects.end()) {
writer.write((*iter)->getHandle());
@@ -200,10 +203,10 @@ bool RenderObjectManager::unpersist(InputPersistenceBlock &reader) {
_timedRenderObjects.resize(0);
// Referenzen auf die TimedRenderObjects wieder herstellen.
- uint timedObjectCount;
+ uint32 timedObjectCount;
reader.read(timedObjectCount);
- for (uint i = 0; i < timedObjectCount; ++i) {
- uint handle;
+ for (uint32 i = 0; i < timedObjectCount; ++i) {
+ uint32 handle;
reader.read(handle);
_timedRenderObjects.push_back(handle);
}
diff --git a/engines/sword25/gfx/screenshot.cpp b/engines/sword25/gfx/screenshot.cpp
index 0ea4bff906..7b56a6e9f3 100644
--- a/engines/sword25/gfx/screenshot.cpp
+++ b/engines/sword25/gfx/screenshot.cpp
@@ -40,7 +40,7 @@ namespace Sword25 {
bool Screenshot::saveToFile(Graphics::Surface *data, Common::WriteStream *stream) {
// Convert the RGBA data to RGB
- const byte *pSrc = (const byte *)data->getBasePtr(0, 0);
+ const byte *pSrc = (const byte *)data->getPixels();
// Write our own custom header
stream->writeUint32BE(MKTAG('S','C','R','N')); // SCRN, short for "Screenshot"
@@ -85,7 +85,7 @@ Common::SeekableReadStream *Screenshot::createThumbnail(Graphics::Surface *data)
uint x, y;
x = y = 0;
- for (byte *pDest = (byte *)thumbnail.pixels; pDest < ((byte *)thumbnail.pixels + thumbnail.pitch * thumbnail.h); ) {
+ for (byte *pDest = (byte *)thumbnail.getPixels(); pDest < ((byte *)thumbnail.getBasePtr(0, thumbnail.h)); ) {
// Get an average over a 4x4 pixel block in the source image
int alpha, red, green, blue;
alpha = red = green = blue = 0;
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/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index d4aaa90682..8c33fa8d61 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -45,7 +45,7 @@
namespace Sword25 {
namespace {
-const uint AUTO_WRAP_THRESHOLD_DEFAULT = 300;
+const uint32 AUTO_WRAP_THRESHOLD_DEFAULT = 300;
}
Text::Text(RenderObjectPtr<RenderObject> parentPtr) :
@@ -98,8 +98,8 @@ void Text::setText(const Common::String &text) {
}
}
-void Text::setColor(uint modulationColor) {
- uint newModulationColor = (modulationColor & 0x00ffffff) | (_modulationColor & 0xff000000);
+void Text::setColor(uint32 modulationColor) {
+ uint32 newModulationColor = (modulationColor & 0x00ffffff) | (_modulationColor & 0xff000000);
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -108,7 +108,7 @@ void Text::setColor(uint modulationColor) {
void Text::setAlpha(int alpha) {
assert(alpha >= 0 && alpha < 256);
- uint newModulationColor = (_modulationColor & 0x00ffffff) | alpha << 24;
+ uint32 newModulationColor = (_modulationColor & 0x00ffffff) | alpha << 24;
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -123,7 +123,7 @@ void Text::setAutoWrap(bool autoWrap) {
}
}
-void Text::setAutoWrapThreshold(uint autoWrapThreshold) {
+void Text::setAutoWrapThreshold(uint32 autoWrapThreshold) {
if (autoWrapThreshold != _autoWrapThreshold) {
_autoWrapThreshold = autoWrapThreshold;
updateFormat();
@@ -351,7 +351,7 @@ bool Text::unpersist(InputPersistenceBlock &reader) {
reader.read(autoWrap);
setAutoWrap(autoWrap);
- uint autoWrapThreshold;
+ uint32 autoWrapThreshold;
reader.read(autoWrapThreshold);
setAutoWrapThreshold(autoWrapThreshold);
diff --git a/engines/sword25/gfx/text.h b/engines/sword25/gfx/text.h
index 94e7a30865..873eb33380 100644
--- a/engines/sword25/gfx/text.h
+++ b/engines/sword25/gfx/text.h
@@ -80,7 +80,7 @@ public:
@remark Dieses Attribut wird mit dem Wert 300 initialisiert.
@remark Eine automatische Formatierung wird nur vorgenommen, wenn diese durch einen Aufruf von SetAutoWrap() aktiviert wurde.
*/
- void setAutoWrapThreshold(uint autoWrapThreshold);
+ void setAutoWrapThreshold(uint32 autoWrapThreshold);
/**
@brief Gibt den dargestellten Text zurück.
@@ -100,7 +100,7 @@ public:
@brief Setzt die Farbe des Textes.
@param Color eine 24-Bit RGB Farbe, die die Farbe des Textes festlegt.
*/
- void setColor(uint modulationColor);
+ void setColor(uint32 modulationColor);
/**
@brief Gibt den Alphawert des Textes zurück.
@@ -128,7 +128,7 @@ public:
/**
@brief Gibt die Längengrenze des Textes in Pixeln zurück, ab der eine automatische Formatierung vorgenommen wird.
*/
- uint getAutoWrapThreshold() const {
+ uint32 getAutoWrapThreshold() const {
return _autoWrapThreshold;
}
@@ -142,11 +142,11 @@ private:
Text(RenderObjectPtr<RenderObject> parentPtr);
Text(InputPersistenceBlock &reader, RenderObjectPtr<RenderObject> parentPtr, uint handle);
- uint _modulationColor;
+ uint32 _modulationColor;
Common::String _font;
Common::String _text;
bool _autoWrap;
- uint _autoWrapThreshold;
+ uint32 _autoWrapThreshold;
struct Line {
Common::Rect bbox;
diff --git a/engines/sword25/input/inputengine.cpp b/engines/sword25/input/inputengine.cpp
index bb9c2c8b40..0d1c449805 100644
--- a/engines/sword25/input/inputengine.cpp
+++ b/engines/sword25/input/inputengine.cpp
@@ -235,13 +235,13 @@ bool InputEngine::persist(OutputPersistenceBlock &writer) {
// Write out the number of command callbacks and their names.
// Note: We do this only for compatibility with older engines resp.
// the original engine.
- writer.write((uint)1);
+ writer.write((uint32)1);
writer.writeString("LuaCommandCB");
// Write out the number of command callbacks and their names.
// Note: We do this only for compatibility with older engines resp.
// the original engine.
- writer.write((uint)1);
+ writer.write((uint32)1);
writer.writeString("LuaCharacterCB");
return true;
@@ -253,7 +253,7 @@ bool InputEngine::unpersist(InputPersistenceBlock &reader) {
// Read number of command callbacks and their names.
// Note: We do this only for compatibility with older engines resp.
// the original engine.
- uint commandCallbackCount;
+ uint32 commandCallbackCount;
reader.read(commandCallbackCount);
assert(commandCallbackCount == 1);
@@ -263,7 +263,7 @@ bool InputEngine::unpersist(InputPersistenceBlock &reader) {
// Read number of character callbacks and their names.
// Note: We do this only for compatibility with older engines resp.
// the original engine.
- uint characterCallbackCount;
+ uint32 characterCallbackCount;
reader.read(characterCallbackCount);
assert(characterCallbackCount == 1);
diff --git a/engines/sword25/kernel/inputpersistenceblock.cpp b/engines/sword25/kernel/inputpersistenceblock.cpp
index 0fe5d88b80..aa3a759756 100644
--- a/engines/sword25/kernel/inputpersistenceblock.cpp
+++ b/engines/sword25/kernel/inputpersistenceblock.cpp
@@ -48,12 +48,12 @@ InputPersistenceBlock::~InputPersistenceBlock() {
}
void InputPersistenceBlock::read(int16 &value) {
- signed int v;
+ int32 v;
read(v);
value = static_cast<int16>(v);
}
-void InputPersistenceBlock::read(signed int &value) {
+void InputPersistenceBlock::read(int32 &value) {
if (checkMarker(SINT_MARKER)) {
value = (int32)READ_LE_UINT32(_iter);
_iter += 4;
@@ -62,7 +62,7 @@ void InputPersistenceBlock::read(signed int &value) {
}
}
-void InputPersistenceBlock::read(uint &value) {
+void InputPersistenceBlock::read(uint32 &value) {
if (checkMarker(UINT_MARKER)) {
value = READ_LE_UINT32(_iter);
_iter += 4;
@@ -96,7 +96,7 @@ void InputPersistenceBlock::readString(Common::String &value) {
value = "";
if (checkMarker(STRING_MARKER)) {
- uint size;
+ uint32 size;
read(size);
if (checkBlockSize(size)) {
@@ -108,7 +108,7 @@ void InputPersistenceBlock::readString(Common::String &value) {
void InputPersistenceBlock::readByteArray(Common::Array<byte> &value) {
if (checkMarker(BLOCK_MARKER)) {
- uint size;
+ uint32 size;
read(size);
if (checkBlockSize(size)) {
diff --git a/engines/sword25/kernel/inputpersistenceblock.h b/engines/sword25/kernel/inputpersistenceblock.h
index 2518d7e32c..02a944ff1b 100644
--- a/engines/sword25/kernel/inputpersistenceblock.h
+++ b/engines/sword25/kernel/inputpersistenceblock.h
@@ -50,8 +50,8 @@ public:
virtual ~InputPersistenceBlock();
void read(int16 &value);
- void read(signed int &value);
- void read(uint &value);
+ void read(int32 &value);
+ void read(uint32 &value);
void read(float &value);
void read(bool &value);
void readString(Common::String &value);
diff --git a/engines/sword25/kernel/objectregistry.h b/engines/sword25/kernel/objectregistry.h
index d9a7c353f7..449b1b60a3 100644
--- a/engines/sword25/kernel/objectregistry.h
+++ b/engines/sword25/kernel/objectregistry.h
@@ -139,12 +139,12 @@ protected:
}
};
- typedef Common::HashMap<uint, T *> HANDLE2PTR_MAP;
- typedef Common::HashMap<T *, uint, ClassPointer_Hash, ClassPointer_EqualTo> PTR2HANDLE_MAP;
+ typedef Common::HashMap<uint32, T *> HANDLE2PTR_MAP;
+ typedef Common::HashMap<T *, uint32, ClassPointer_Hash, ClassPointer_EqualTo> PTR2HANDLE_MAP;
HANDLE2PTR_MAP _handle2PtrMap;
PTR2HANDLE_MAP _ptr2HandleMap;
- uint _nextHandle;
+ uint32 _nextHandle;
T *findPtrByHandle(uint handle) {
// Zum Handle gehörigen Pointer finden.
diff --git a/engines/sword25/kernel/outputpersistenceblock.cpp b/engines/sword25/kernel/outputpersistenceblock.cpp
index e29d956e5f..53fb624767 100644
--- a/engines/sword25/kernel/outputpersistenceblock.cpp
+++ b/engines/sword25/kernel/outputpersistenceblock.cpp
@@ -41,13 +41,13 @@ OutputPersistenceBlock::OutputPersistenceBlock() {
_data.reserve(INITIAL_BUFFER_SIZE);
}
-void OutputPersistenceBlock::write(signed int value) {
+void OutputPersistenceBlock::write(int32 value) {
writeMarker(SINT_MARKER);
value = TO_LE_32(value);
rawWrite(&value, sizeof(value));
}
-void OutputPersistenceBlock::write(uint value) {
+void OutputPersistenceBlock::write(uint32 value) {
writeMarker(UINT_MARKER);
value = TO_LE_32(value);
rawWrite(&value, sizeof(value));
@@ -74,14 +74,14 @@ void OutputPersistenceBlock::write(bool value) {
void OutputPersistenceBlock::writeString(const Common::String &string) {
writeMarker(STRING_MARKER);
- write(string.size());
+ write((uint32)string.size());
rawWrite(string.c_str(), string.size());
}
void OutputPersistenceBlock::writeByteArray(Common::Array<byte> &value) {
writeMarker(BLOCK_MARKER);
- write((uint)value.size());
+ write((uint32)value.size());
rawWrite(&value[0], value.size());
}
diff --git a/engines/sword25/kernel/outputpersistenceblock.h b/engines/sword25/kernel/outputpersistenceblock.h
index 12351d22e2..17f018a106 100644
--- a/engines/sword25/kernel/outputpersistenceblock.h
+++ b/engines/sword25/kernel/outputpersistenceblock.h
@@ -41,8 +41,8 @@ class OutputPersistenceBlock : public PersistenceBlock {
public:
OutputPersistenceBlock();
- void write(signed int value);
- void write(uint value);
+ void write(int32 value);
+ void write(uint32 value);
void write(float value);
void write(bool value);
void writeString(const Common::String &string);
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index 27d669caa1..df26da7800 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -59,7 +59,7 @@ static const int VERSIONNUM = 2;
char gameTarget[MAX_SAVEGAME_SIZE];
void setGameTarget(const char *target) {
- strncpy(gameTarget, target, MAX_SAVEGAME_SIZE);
+ strncpy(gameTarget, target, MAX_SAVEGAME_SIZE - 1);
}
static Common::String generateSavegameFilename(uint slotID) {
diff --git a/engines/sword25/math/polygon.cpp b/engines/sword25/math/polygon.cpp
index 2e7836ff77..99d947df87 100644
--- a/engines/sword25/math/polygon.cpp
+++ b/engines/sword25/math/polygon.cpp
@@ -364,20 +364,20 @@ bool Polygon::isPointInPolygon(const Vertex &point, bool edgesBelongToPolygon) c
bool Polygon::persist(OutputPersistenceBlock &writer) {
writer.write(vertexCount);
for (int i = 0; i < vertexCount; ++i) {
- writer.write(vertices[i].x);
- writer.write(vertices[i].y);
+ writer.write((int32)vertices[i].x);
+ writer.write((int32)vertices[i].y);
}
return true;
}
bool Polygon::unpersist(InputPersistenceBlock &reader) {
- int storedvertexCount;
+ int32 storedvertexCount;
reader.read(storedvertexCount);
Common::Array<Vertex> storedvertices;
for (int i = 0; i < storedvertexCount; ++i) {
- int x, y;
+ int32 x, y;
reader.read(x);
reader.read(y);
storedvertices.push_back(Vertex(x, y));
diff --git a/engines/sword25/math/polygon.h b/engines/sword25/math/polygon.h
index ffdbf14f6b..f81e165621 100644
--- a/engines/sword25/math/polygon.h
+++ b/engines/sword25/math/polygon.h
@@ -169,7 +169,7 @@ public:
//
/// Specifies the number of Vertecies in the Vertecies array.
- int vertexCount;
+ int32 vertexCount;
/// COntains the Vertecies of the polygon
Vertex *vertices;
diff --git a/engines/sword25/math/region.cpp b/engines/sword25/math/region.cpp
index 7681ef6d9f..db888e432a 100644
--- a/engines/sword25/math/region.cpp
+++ b/engines/sword25/math/region.cpp
@@ -67,7 +67,7 @@ uint Region::create(REGION_TYPE type) {
uint Region::create(InputPersistenceBlock &reader, uint handle) {
// Read type
- uint type;
+ uint32 type;
reader.read(type);
// Depending on the type, create a new BS_Region or BS_WalkRegion object
@@ -299,22 +299,22 @@ bool Region::isLineOfSight(const Vertex &a, const Vertex &b) const {
bool Region::persist(OutputPersistenceBlock &writer) {
bool Result = true;
- writer.write(static_cast<uint>(_type));
+ writer.write(static_cast<uint32>(_type));
writer.write(_valid);
- writer.write(_position.x);
- writer.write(_position.y);
+ writer.write((int32)_position.x);
+ writer.write((int32)_position.y);
- writer.write(_polygons.size());
+ writer.write((uint32)_polygons.size());
Common::Array<Polygon>::iterator It = _polygons.begin();
while (It != _polygons.end()) {
Result &= It->persist(writer);
++It;
}
- writer.write(_boundingBox.left);
- writer.write(_boundingBox.top);
- writer.write(_boundingBox.right);
- writer.write(_boundingBox.bottom);
+ writer.write((int32)_boundingBox.left);
+ writer.write((int32)_boundingBox.top);
+ writer.write((int32)_boundingBox.right);
+ writer.write((int32)_boundingBox.bottom);
return Result;
}
@@ -325,7 +325,7 @@ bool Region::unpersist(InputPersistenceBlock &reader) {
reader.read(_position.y);
_polygons.clear();
- uint PolygonCount;
+ uint32 PolygonCount;
reader.read(PolygonCount);
for (uint i = 0; i < PolygonCount; ++i) {
_polygons.push_back(Polygon(reader));
diff --git a/engines/sword25/math/regionregistry.cpp b/engines/sword25/math/regionregistry.cpp
index 68c360a5ee..e4925f7baf 100644
--- a/engines/sword25/math/regionregistry.cpp
+++ b/engines/sword25/math/regionregistry.cpp
@@ -47,7 +47,7 @@ bool RegionRegistry::persist(OutputPersistenceBlock &writer) {
writer.write(_nextHandle);
// Number of regions to write
- writer.write(_handle2PtrMap.size());
+ writer.write((uint32)_handle2PtrMap.size());
// Persist all the BS_Regions
HANDLE2PTR_MAP::const_iterator iter = _handle2PtrMap.begin();
@@ -76,13 +76,13 @@ bool RegionRegistry::unpersist(InputPersistenceBlock &reader) {
delete _handle2PtrMap.begin()->_value;
// read in the number of BS_Regions
- uint regionCount;
+ uint32 regionCount;
reader.read(regionCount);
// Restore all the BS_Regions objects
for (uint i = 0; i < regionCount; ++i) {
// Handle read
- uint handle;
+ uint32 handle;
reader.read(handle);
// BS_Region restore
diff --git a/engines/sword25/math/walkregion.cpp b/engines/sword25/math/walkregion.cpp
index bace4d54bc..0ba7e8ec3d 100644
--- a/engines/sword25/math/walkregion.cpp
+++ b/engines/sword25/math/walkregion.cpp
@@ -328,22 +328,22 @@ bool WalkRegion::persist(OutputPersistenceBlock &writer) {
result &= Region::persist(writer);
// Persist the nodes
- writer.write(_nodes.size());
+ writer.write((uint32)_nodes.size());
Common::Array<Vertex>::const_iterator it = _nodes.begin();
while (it != _nodes.end()) {
- writer.write(it->x);
- writer.write(it->y);
+ writer.write((int32)it->x);
+ writer.write((int32)it->y);
++it;
}
// Persist the visibility matrix
- writer.write(_visibilityMatrix.size());
+ writer.write((uint32)_visibilityMatrix.size());
Common::Array< Common::Array<int> >::const_iterator rowIter = _visibilityMatrix.begin();
while (rowIter != _visibilityMatrix.end()) {
- writer.write(rowIter->size());
+ writer.write((uint32)rowIter->size());
Common::Array<int>::const_iterator colIter = rowIter->begin();
while (colIter != rowIter->end()) {
- writer.write(*colIter);
+ writer.write((int32)*colIter);
++colIter;
}
@@ -360,7 +360,7 @@ bool WalkRegion::unpersist(InputPersistenceBlock &reader) {
// this point only the additional data from BS_WalkRegion needs to be loaded
// Node load
- uint nodeCount;
+ uint32 nodeCount;
reader.read(nodeCount);
_nodes.clear();
_nodes.resize(nodeCount);
@@ -372,18 +372,20 @@ bool WalkRegion::unpersist(InputPersistenceBlock &reader) {
}
// Visibility matrix load
- uint rowCount;
+ uint32 rowCount;
reader.read(rowCount);
_visibilityMatrix.clear();
_visibilityMatrix.resize(rowCount);
Common::Array< Common::Array<int> >::iterator rowIter = _visibilityMatrix.begin();
while (rowIter != _visibilityMatrix.end()) {
- uint colCount;
+ uint32 colCount;
reader.read(colCount);
rowIter->resize(colCount);
Common::Array<int>::iterator colIter = rowIter->begin();
while (colIter != rowIter->end()) {
- reader.read(*colIter);
+ int32 t;
+ reader.read(t);
+ *colIter = t;
++colIter;
}
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 61d53c89a7..8ff1b0cf2a 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -339,7 +339,10 @@ bool SoundEngine::persist(OutputPersistenceBlock &writer) {
_handles[i].type = kFreeHandle;
writer.writeString(_handles[i].fileName);
- writer.write((int)_handles[i].sndType);
+ if (_handles[i].type == kFreeHandle)
+ writer.write((int32)-1);
+ else
+ writer.write(_handles[i].sndType);
writer.write(_handles[i].volume);
writer.write(_handles[i].pan);
writer.write(_handles[i].loop);
@@ -363,13 +366,13 @@ bool SoundEngine::unpersist(InputPersistenceBlock &reader) {
reader.read(_handles[i].id);
Common::String fileName;
- int sndType;
+ int32 sndType;
float volume;
float pan;
bool loop;
- int loopStart;
- int loopEnd;
- uint layer;
+ int32 loopStart;
+ int32 loopEnd;
+ uint32 layer;
reader.readString(fileName);
reader.read(sndType);
@@ -381,7 +384,7 @@ bool SoundEngine::unpersist(InputPersistenceBlock &reader) {
reader.read(layer);
if (reader.isGood()) {
- if (sndType != kFreeHandle)
+ if (sndType != -1)
playSoundEx(fileName, (SOUND_TYPES)sndType, volume, pan, loop, loopStart, loopEnd, layer, i);
} else
return false;
diff --git a/engines/sword25/sfx/soundengine.h b/engines/sword25/sfx/soundengine.h
index 8132ec556e..8974ee69e5 100644
--- a/engines/sword25/sfx/soundengine.h
+++ b/engines/sword25/sfx/soundengine.h
@@ -67,13 +67,13 @@ struct SndHandle {
uint32 id;
Common::String fileName;
- int sndType;
+ int32 sndType;
float volume;
float pan;
bool loop;
- int loopStart;
- int loopEnd;
- uint layer;
+ int32 loopStart;
+ int32 loopEnd;
+ uint32 layer;
};
diff --git a/engines/sword25/util/lua/lcode.cpp b/engines/sword25/util/lua/lcode.cpp
index ead780d359..93188b37e2 100644
--- a/engines/sword25/util/lua/lcode.cpp
+++ b/engines/sword25/util/lua/lcode.cpp
@@ -5,8 +5,6 @@
*/
-#include <stdlib.h>
-
#define lcode_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/ldebug.cpp b/engines/sword25/util/lua/ldebug.cpp
index e89ae9cad5..396c5df18b 100644
--- a/engines/sword25/util/lua/ldebug.cpp
+++ b/engines/sword25/util/lua/ldebug.cpp
@@ -5,11 +5,6 @@
*/
-#include <stdarg.h>
-#include <stddef.h>
-#include <string.h>
-
-
#define ldebug_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lfunc.cpp b/engines/sword25/util/lua/lfunc.cpp
index f8fa19e25a..95e616cc7e 100644
--- a/engines/sword25/util/lua/lfunc.cpp
+++ b/engines/sword25/util/lua/lfunc.cpp
@@ -5,8 +5,6 @@
*/
-#include <stddef.h>
-
#define lfunc_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lgc.cpp b/engines/sword25/util/lua/lgc.cpp
index 54f7b548dd..53f512280a 100644
--- a/engines/sword25/util/lua/lgc.cpp
+++ b/engines/sword25/util/lua/lgc.cpp
@@ -4,8 +4,6 @@
** See Copyright Notice in lua.h
*/
-#include <string.h>
-
#define lgc_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/llimits.h b/engines/sword25/util/lua/llimits.h
index 0925231350..ce6dbc980c 100644
--- a/engines/sword25/util/lua/llimits.h
+++ b/engines/sword25/util/lua/llimits.h
@@ -8,9 +8,6 @@
#define llimits_h
-#include <limits.h>
-#include <stddef.h>
-
#include "lua.h"
diff --git a/engines/sword25/util/lua/lmem.cpp b/engines/sword25/util/lua/lmem.cpp
index 004a467dc8..8cd220308c 100644
--- a/engines/sword25/util/lua/lmem.cpp
+++ b/engines/sword25/util/lua/lmem.cpp
@@ -5,8 +5,6 @@
*/
-#include <stddef.h>
-
#define lmem_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lopcodes.cpp b/engines/sword25/util/lua/lopcodes.cpp
index 255b2029e9..8b0a3ab330 100644
--- a/engines/sword25/util/lua/lopcodes.cpp
+++ b/engines/sword25/util/lua/lopcodes.cpp
@@ -8,6 +8,7 @@
#define LUA_CORE
+#include "lua.h"
#include "lopcodes.h"
@@ -60,7 +61,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T A B C mode opcode */
- opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
diff --git a/engines/sword25/util/lua/lparser.cpp b/engines/sword25/util/lua/lparser.cpp
index 03ea333315..0c88992e79 100644
--- a/engines/sword25/util/lua/lparser.cpp
+++ b/engines/sword25/util/lua/lparser.cpp
@@ -5,8 +5,6 @@
*/
-#include <string.h>
-
#define lparser_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lstate.cpp b/engines/sword25/util/lua/lstate.cpp
index 26bed7bec2..c0ea29de01 100644
--- a/engines/sword25/util/lua/lstate.cpp
+++ b/engines/sword25/util/lua/lstate.cpp
@@ -5,8 +5,6 @@
*/
-#include <stddef.h>
-
#define lstate_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lstring.cpp b/engines/sword25/util/lua/lstring.cpp
index 046b87ee1c..5cfc72539a 100644
--- a/engines/sword25/util/lua/lstring.cpp
+++ b/engines/sword25/util/lua/lstring.cpp
@@ -5,8 +5,6 @@
*/
-#include <string.h>
-
#define lstring_c
#define LUA_CORE
diff --git a/engines/sword25/util/lua/lstrlib.cpp b/engines/sword25/util/lua/lstrlib.cpp
index ed68a2fa00..5da45e1fea 100644
--- a/engines/sword25/util/lua/lstrlib.cpp
+++ b/engines/sword25/util/lua/lstrlib.cpp
@@ -7,12 +7,6 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_ctype_h
-#include <ctype.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
#define lstrlib_c
#define LUA_LIB
diff --git a/engines/sword25/util/lua/ltablib.cpp b/engines/sword25/util/lua/ltablib.cpp
index 93be9e6077..064c33c005 100644
--- a/engines/sword25/util/lua/ltablib.cpp
+++ b/engines/sword25/util/lua/ltablib.cpp
@@ -5,8 +5,6 @@
*/
-#include <stddef.h>
-
#define ltablib_c
#define LUA_LIB
diff --git a/engines/sword25/util/lua/lua.h b/engines/sword25/util/lua/lua.h
index a3b7573ca5..4f557e462b 100644
--- a/engines/sword25/util/lua/lua.h
+++ b/engines/sword25/util/lua/lua.h
@@ -22,7 +22,7 @@
#define LUA_RELEASE "Lua 5.1.3"
#define LUA_VERSION_NUM 501
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
-#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
/* mark for precompiled code (`<esc>Lua') */
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index b7f5e30340..fb477c1687 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,16 @@
* 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 "sword25/util/lua/lua.h"
#include "pluto.h"
+#undef TOTEXT
+
#define USE_PDEP
#ifdef USE_PDEP
@@ -42,10 +47,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 +71,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 +108,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 +210,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 +237,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 +260,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 +300,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 +318,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 +374,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 +415,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 +455,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 +554,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 +575,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 +596,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 +637,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 +677,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 +787,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 +796,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 +805,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 +825,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 +857,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 +872,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 +950,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 +981,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 +1000,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 +1016,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 +1040,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 +1064,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 +1167,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 +1188,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 +1264,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 +1684,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 +1703,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 +1735,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 +1764,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 +1816,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 +1984,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 +2026,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/POTFILES b/engines/teenagent/POTFILES
new file mode 100644
index 0000000000..b8b832872e
--- /dev/null
+++ b/engines/teenagent/POTFILES
@@ -0,0 +1 @@
+engines/teenagent/resources.cpp
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/configure.engine b/engines/teenagent/configure.engine
new file mode 100644
index 0000000000..223a0e884c
--- /dev/null
+++ b/engines/teenagent/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine teenagent "Teen Agent" yes
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/font.cpp b/engines/teenagent/font.cpp
index 47f52ff90f..9d85328f20 100644
--- a/engines/teenagent/font.cpp
+++ b/engines/teenagent/font.cpp
@@ -65,7 +65,7 @@ uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color)
byte *glyph = _data + READ_LE_UINT16(_data + idx * 2);
int h = glyph[0], w = glyph[1];
- if (surface == NULL || surface->pixels == NULL || y + h <= 0 || y >= kScreenHeight || x + w <= 0 || x >= kScreenWidth)
+ if (surface == NULL || surface->getPixels() == NULL || y + h <= 0 || y >= kScreenHeight || x + w <= 0 || x >= kScreenWidth)
return w - _widthPack;
int i0 = 0, j0 = 0;
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
index 442d0abf16..cdbdcf9655 100644
--- a/engines/teenagent/resources.cpp
+++ b/engines/teenagent/resources.cpp
@@ -160,7 +160,7 @@ void Resources::loadOff(Graphics::Surface &surface, byte *palette, int id) {
off.read(id, buf, bufferSize);
byte *src = buf;
- byte *dst = (byte *)surface.pixels;
+ byte *dst = (byte *)surface.getPixels();
memcpy(dst, src, 64000);
memcpy(palette, buf + 64000, 768);
@@ -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/teenagent/scene.cpp b/engines/teenagent/scene.cpp
index bdeb11a841..f36a60932c 100644
--- a/engines/teenagent/scene.cpp
+++ b/engines/teenagent/scene.cpp
@@ -48,7 +48,6 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0),
onEnabled = true;
memset(palette, 0, sizeof(palette));
- background.pixels = 0;
FilePack varia;
varia.open("varia.res");
@@ -74,8 +73,7 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0),
}
Scene::~Scene() {
- if (background.pixels)
- background.free();
+ background.free();
delete[] ons;
ons = 0;
@@ -372,7 +370,7 @@ void Scene::init(int id, const Common::Point &pos) {
for (byte i = 0; i < 4; ++i)
customAnimation[i].free();
- if (background.pixels == NULL)
+ if (background.getPixels() == NULL)
background.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
warp(pos);
@@ -416,7 +414,7 @@ void Scene::init(int id, const Common::Point &pos) {
if (nowPlaying != _vm->res->dseg.get_byte(dsAddr_currentMusic))
_vm->music->load(_vm->res->dseg.get_byte(dsAddr_currentMusic));
- _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
+ _vm->_system->copyRectToScreen(background.getPixels(), background.pitch, 0, 0, background.w, background.h);
setPalette(0);
}
@@ -642,8 +640,8 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) {
return true;
}
- if (background.pixels && debugFeatures.feature[DebugFeatures::kShowBack]) {
- _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
+ if (background.getPixels() && debugFeatures.feature[DebugFeatures::kShowBack]) {
+ _vm->_system->copyRectToScreen(background.getPixels(), background.pitch, 0, 0, background.w, background.h);
} else
_vm->_system->fillScreen(0);
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index 0b48a18b26..e73f1100d6 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -399,7 +399,7 @@ bool TeenAgentEngine::showLogo() {
return true;
}
- _system->copyRectToScreen(s.pixels, s.w, s.x, s.y, s.w, s.h);
+ _system->copyRectToScreen(s.getPixels(), s.w, s.x, s.y, s.w, s.h);
_system->updateScreen();
_system->delayMillis(100);
diff --git a/engines/testbed/config-params.cpp b/engines/testbed/config-params.cpp
index e89da0b07f..47e5dfa933 100644
--- a/engines/testbed/config-params.cpp
+++ b/engines/testbed/config-params.cpp
@@ -38,6 +38,8 @@ ConfigParams::ConfigParams() {
_isInteractive = true;
_isGameDataFound = true;
_rerunTests = false;
+
+ _testbedConfMan = 0;
}
void ConfigParams::initLogging(const char *dirname, const char *filename, bool enable) {
diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp
index 6b56616c9b..a40d239ebf 100644
--- a/engines/testbed/config.cpp
+++ b/engines/testbed/config.cpp
@@ -213,22 +213,22 @@ void TestbedConfigManager::parseConfigFile() {
return;
}
_configFileInterface.loadFromStream(*rs);
- Common::ConfigFile::SectionList sections = _configFileInterface.getSections();
+ Common::INIFile::SectionList sections = _configFileInterface.getSections();
Testsuite *currTS = 0;
- for (Common::ConfigFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) {
+ for (Common::INIFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) {
if (i->name.equalsIgnoreCase("Global")) {
// Global params may be directly queried, ignore them
} else {
// A testsuite, process it.
currTS = getTestsuiteByName(i->name);
- Common::ConfigFile::SectionKeyList kList = i->getKeys();
+ Common::INIFile::SectionKeyList kList = i->getKeys();
if (!currTS) {
Testsuite::logPrintf("Warning! Error in config: Testsuite %s not found\n", i->name.c_str());
continue;
}
- for (Common::ConfigFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) {
+ for (Common::INIFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) {
if (j->key.equalsIgnoreCase("this")) {
currTS->enable(stringToBool(j->value));
} else {
diff --git a/engines/testbed/config.h b/engines/testbed/config.h
index fd5588aa31..7d479a74fd 100644
--- a/engines/testbed/config.h
+++ b/engines/testbed/config.h
@@ -24,7 +24,7 @@
#include "common/array.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/str-array.h"
#include "common/tokenizer.h"
@@ -62,7 +62,7 @@ public:
private:
Common::Array<Testsuite *> &_testsuiteList;
Common::String _configFileName;
- Common::ConfigFile _configFileInterface;
+ Common::INIFile _configFileInterface;
void parseConfigFile();
};
@@ -113,7 +113,7 @@ private:
class TestbedInteractionDialog : public GUI::Dialog {
public:
- TestbedInteractionDialog(uint x, uint y, uint w, uint h) : GUI::Dialog(x, y, w, h) {}
+ TestbedInteractionDialog(uint x, uint y, uint w, uint h) : GUI::Dialog(x, y, w, h), _xOffset(0), _yOffset(0) {}
~TestbedInteractionDialog() {}
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
void addButton(uint w, uint h, const Common::String name, uint32 cmd, uint xOffset = 0, uint yPadding = 8);
diff --git a/engines/testbed/configure.engine b/engines/testbed/configure.engine
new file mode 100644
index 0000000000..c0a68c8eb8
--- /dev/null
+++ b/engines/testbed/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine testbed "TestBed: the Testing framework" no
diff --git a/engines/testbed/events.cpp b/engines/testbed/events.cpp
index 78de87e133..4b9ced2a53 100644
--- a/engines/testbed/events.cpp
+++ b/engines/testbed/events.cpp
@@ -83,11 +83,10 @@ struct keycodeToChar {
char EventTests::keystrokeToChar() {
Common::EventManager *eventMan = g_system->getEventManager();
- bool quitLoop = false;
Common::Event event;
// handle all keybd events
- while (!quitLoop) {
+ while (true) {
while (eventMan->pollEvent(event)) {
// Quit if explicitly requested!
if (Engine::shouldQuit()) {
@@ -110,8 +109,6 @@ char EventTests::keystrokeToChar() {
}
}
}
-
- return 0;
}
Common::Rect EventTests::drawFinishZone() {
diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp
index 590e6c6d81..26e073d407 100644
--- a/engines/testbed/graphics.cpp
+++ b/engines/testbed/graphics.cpp
@@ -927,17 +927,29 @@ TestExitStatus GFXtests::overlayGraphics() {
Graphics::PixelFormat pf = g_system->getOverlayFormat();
- OverlayColor buffer[50 * 100];
- OverlayColor value = pf.RGBToColor(0, 255, 0);
+ byte *buffer = new byte[50 * 100 * pf.bytesPerPixel];
+ const uint32 value = pf.RGBToColor(0, 255, 0);
- for (int i = 0; i < 50 * 100; i++) {
- buffer[i] = value;
+ if (pf.bytesPerPixel == 2) {
+ uint16 *dst = (uint16 *)buffer;
+ for (int i = 50 * 100; i > 0; --i) {
+ *dst++ = value;
+ }
+ } else if (pf.bytesPerPixel == 4) {
+ uint32 *dst = (uint32 *)buffer;
+ for (int i = 50 * 100; i > 0; --i) {
+ *dst++ = value;
+ }
+ } else {
+ error("GFXtests::overlayGraphics: Unsupported color depth: %d", pf.bytesPerPixel);
}
g_system->showOverlay();
- g_system->copyRectToOverlay(buffer, 200, 270, 175, 100, 50);
+ g_system->copyRectToOverlay(buffer, 100 * pf.bytesPerPixel, 270, 175, 100, 50);
g_system->updateScreen();
+ delete[] buffer;
+
g_system->delayMillis(1000);
g_system->hideOverlay();
diff --git a/engines/testbed/midi.cpp b/engines/testbed/midi.cpp
index 70ede406d5..33fab03a5e 100644
--- a/engines/testbed/midi.cpp
+++ b/engines/testbed/midi.cpp
@@ -103,7 +103,7 @@ TestExitStatus MidiTests::playMidiMusic() {
return kTestFailed;
}
- Testsuite::logDetailedPrintf("Info! Midi: Succesfully opened the driver\n");
+ Testsuite::logDetailedPrintf("Info! Midi: Successfully opened the driver\n");
Common::MemoryWriteStreamDynamic ws(DisposeAfterUse::YES);
loadMusicInMemory(&ws);
diff --git a/engines/tinsel/POTFILES b/engines/tinsel/POTFILES
new file mode 100644
index 0000000000..714da378c8
--- /dev/null
+++ b/engines/tinsel/POTFILES
@@ -0,0 +1 @@
+engines/tinsel/saveload.cpp
diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp
index 106e1542d5..fa66b7ad8e 100644
--- a/engines/tinsel/bmv.cpp
+++ b/engines/tinsel/bmv.cpp
@@ -1031,7 +1031,7 @@ void BMVPlayer::CopyMovieToScreen() {
// The movie surface is slightly less high than the output screen (429 rows versus 432).
// Because of this, there's some extra line clearing above and below the displayed area
int yStart = (SCREEN_HEIGHT - SCREEN_HIGH) / 2;
- memset(_vm->screen().getBasePtr(0, 0), 0, yStart * SCREEN_WIDTH);
+ memset(_vm->screen().getPixels(), 0, yStart * SCREEN_WIDTH);
memcpy(_vm->screen().getBasePtr(0, yStart), ScreenBeg, SCREEN_WIDTH * SCREEN_HIGH);
memset(_vm->screen().getBasePtr(0, yStart + SCREEN_HIGH), 0,
(SCREEN_HEIGHT - SCREEN_HIGH - yStart) * SCREEN_WIDTH);
diff --git a/engines/tinsel/configure.engine b/engines/tinsel/configure.engine
new file mode 100644
index 0000000000..c0f3e0a18d
--- /dev/null
+++ b/engines/tinsel/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine tinsel "Tinsel" yes
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 2e4be33e53..a7ba8b28cb 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -67,7 +67,7 @@ bool TinselEngine::getIsADGFDemo() const {
return (bool)(_gameDescription->desc.flags & ADGF_DEMO);
}
-bool TinselEngine::isCD() const {
+bool TinselEngine::isV1CD() const {
return (bool)(_gameDescription->desc.flags & ADGF_CD);
}
diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h
index f05f39b319..cc8166f295 100644
--- a/engines/tinsel/detection_tables.h
+++ b/engines/tinsel/detection_tables.h
@@ -34,6 +34,8 @@ static const TinselGameDescription gameDescriptions[] = {
// TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine,
// and as far as we know there aren't any variations of this engine.
+ // ==== Discworld 1 early (TinselV0) entries ==============================
+
{ // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php
{
"dw",
@@ -51,6 +53,8 @@ static const TinselGameDescription gameDescriptions[] = {
TINSEL_V0,
},
+ // ==== Discworld 1 entries ===============================================
+
{ // CD Demo V1 version, with *.gra files
{
"dw",
@@ -474,6 +478,26 @@ static const TinselGameDescription gameDescriptions[] = {
},
#endif
+ { // Mac English CD, see tracker #3614864
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "114643df0d1f1530a0a9c5d4e38917bc", 1268553},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_CD,
+ GUIO0()
+ },
+ GID_DW1,
+ 0,
+ GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
{ // Mac multilanguage CD
{
"dw",
@@ -553,6 +577,9 @@ static const TinselGameDescription gameDescriptions[] = {
TINSEL_V1,
},
+ // ==== Discworld 2 entries ===============================================
+ // Note: All Discworld 2 versions are CD only, therefore we don't add the ADGF_CD flag
+
{ // English Discworld 2 demo
{
"dw2",
@@ -564,7 +591,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_DEMO | ADGF_CD,
+ ADGF_DEMO,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -584,7 +611,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_GRB,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -604,7 +631,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_USA,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -624,7 +651,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::FR_FRA,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -644,7 +671,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -665,7 +692,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -685,7 +712,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::ES_ESP,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
@@ -706,7 +733,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::RU_RUS,
Common::kPlatformDOS,
- ADGF_CD,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
GID_DW2,
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index 5dae984def..c4f341f6fe 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -798,7 +798,7 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
*/
void ClearScreen() {
byte blackColorIndex = (!TinselV1Mac) ? 0 : 255;
- void *pDest = _vm->screen().getBasePtr(0, 0);
+ void *pDest = _vm->screen().getPixels();
memset(pDest, blackColorIndex, SCREEN_WIDTH * SCREEN_HEIGHT);
g_system->fillScreen(blackColorIndex);
g_system->updateScreen();
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/music.cpp b/engines/tinsel/music.cpp
index 3144ea7f94..bf7257f876 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -91,28 +91,29 @@ static const int enhancedAudioGRAVersion[] = {
};
static const int enhancedAudioSCNVersion[] = {
- 301, 302, 2, 1, 1, 301, 302, 3, 3, 4, // 1-10
- 4, 5, 6, 1, 7, 8, 9, 10, 8, 11, // 11-20
- 11, 12, 13, 13, 13, 13, 13, 14, 13, 13, // 21-30
- 15, 16, 17, 15, 18, 19, 20, 338, 21, 21, // 31-40
- 341, 342, 22, 22, 23, 24, 25, 26, 27, 28, // 41-50
- 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, // 51-60
- 38, 39, 39, 39, 39, 40, 39, 41, 41, 42, // 61-70
- 43, 42, 44, 45, 41, 46, 48, 47, 48, 49, // 71-80
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 81-90
- 60, 61, 62, 63, 61, 64, 65, 66, 67, 68, // 91-100
- 69, 70, 68, 71, 72, 73, 74, 75, 12, 76, // 101-110
- 77, 78, 79, 80, 4, 4, 82, 83, 77, 4, // 111-120
- 84, 85, 86, 3124, 88, 89, 90, 88, 2, 2, // 121-130
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 131-140
- 3142, 91, 92, 93, 94, 94, 95, 96, 52, 4, // 141-150
- 97, 98, 99, 99 // 151-154
+ 301, 302, 2, 1, 1, 301, 302, 3, 3, 4, // 1-10
+ 4, 5, 6, 1, 7, 8, 9, 10, 8, 11, // 11-20
+ 11, 12, 13, 13, 13, 13, 13, 14, 13, 13, // 21-30
+ 15, 16, 17, 15, 18, 19, 20, 338, 21, 21, // 31-40
+ 341, 342, 22, 22, 23, 24, 25, 26, 27, 28, // 41-50
+ 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, // 51-60
+ 38, 39, 39, 39, 39, 40, 39, 41, 41, 42, // 61-70
+ 43, 42, 44, 45, 41, 46, 48, 47, 48, 49, // 71-80
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 81-90
+ 60, 61, 62, 63, 61, 64, 65, 66, 67, 68, // 91-100
+ 69, 70, 68, 71, 72, 73, 74, 75, 12, 76, // 101-110
+ 77, 78, 79, 80, 4, 4, 82, 83, 77, 4, // 111-120
+ 84, 85, 86, 3124, 88, 89, 90, 88, 2, 2, // 121-130
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 131-140
+ 3142, 91, 92, 93, 94, 94, 95, 96, 52, 4, // 141-150
+ 97, 98, 99, 99 // 151-154
};
int GetTrackNumber(SCNHANDLE hMidi) {
- for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
+ for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++) {
if (g_midiOffsets[i] == hMidi)
return i;
+ }
return -1;
}
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 b652e394a0..043b18b8c5 100644
--- a/engines/tinsel/scene.cpp
+++ b/engines/tinsel/scene.cpp
@@ -130,15 +130,15 @@ const SCENE_STRUC *GetSceneStruc(const byte *pStruc) {
const byte *p = pStruc;
memset(&g_tempStruc, 0, sizeof(SCENE_STRUC));
- g_tempStruc.numEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.numPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.numTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.defRefer = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.hSceneScript = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.hEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.hPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
- g_tempStruc.hTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32);
-
+ g_tempStruc.numEntrance = READ_32(p); p += sizeof(uint32);
+ g_tempStruc.numPoly = READ_32(p); p += sizeof(uint32);
+ g_tempStruc.numTaggedActor = READ_32(p); p += sizeof(uint32);
+ g_tempStruc.defRefer = READ_32(p); p += sizeof(uint32);
+ g_tempStruc.hSceneScript = READ_32(p); p += sizeof(uint32);
+ 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;
}
@@ -186,7 +186,7 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
void SendSceneTinselProcess(TINSEL_EVENT event) {
SCENE_STRUC *ss;
- if (g_SceneHandle != (SCNHANDLE)NULL) {
+ if (g_SceneHandle != 0) {
ss = (SCENE_STRUC *) FindChunk(g_SceneHandle, CHUNK_SCENE);
if (ss->hSceneScript) {
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index cadc754de6..416ee74127 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -75,7 +75,7 @@ SoundManager::~SoundManager() {
// playSample for DiscWorld 1
bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) {
// Floppy version has no sample file.
- if (!_vm->isCD())
+ if (!_vm->isV1CD())
return false;
// no sample driver?
@@ -207,10 +207,6 @@ void SoundManager::playDW1MacMusic(Common::File &s, uint32 length) {
bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int priority,
Audio::Mixer::SoundType type, Audio::SoundHandle *handle) {
- // Floppy version has no sample file
- if (!_vm->isCD())
- return false;
-
// no sample driver?
if (!_vm->_mixer->isReady())
return false;
@@ -501,8 +497,8 @@ void SoundManager::showSoundError(const char *errorMsg, const char *soundFile) {
* Opens and inits all sound sample files.
*/
void SoundManager::openSampleFiles() {
- // Floppy and demo versions have no sample files, except for the Discworld 2 demo
- if (!_vm->isCD())
+ // V1 Floppy and V0 demo versions have no sample files
+ if (TinselV0 || (TinselV1 && !_vm->isV1CD()))
return;
TinselFile f;
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 9075e1adb1..5d410e62c7 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -868,9 +868,6 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
}
TinselEngine::~TinselEngine() {
- if (_bmv->MoviePlaying())
- _bmv->FinishBMV();
-
_system->getAudioCDManager()->stop();
delete _bmv;
delete _sound;
@@ -1007,6 +1004,9 @@ Common::Error TinselEngine::run() {
g_system->delayMillis(10);
}
+ if (_bmv->MoviePlaying())
+ _bmv->FinishBMV();
+
// Write configuration
_vm->_config->writeToDisk();
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index ec504b69cd..5eb3b7d7b8 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -184,7 +184,7 @@ public:
uint32 getFlags() const;
Common::Platform getPlatform() const;
bool getIsADGFDemo() const;
- bool isCD() const;
+ bool isV1CD() const;
const char *getSampleIndex(LANGUAGE lang);
const char *getSampleFile(LANGUAGE lang);
@@ -226,7 +226,11 @@ public:
Graphics::Surface &screen() { return _screenSurface; }
Common::Point getMousePosition() const { return _mousePos; }
- void setMousePosition(const Common::Point &pt) {
+ void setMousePosition(Common::Point pt) {
+ // Clip mouse position to be within the screen coordinates
+ pt.x = CLIP<int16>(pt.x, 0, SCREEN_WIDTH - 1);
+ pt.y = CLIP<int16>(pt.y, 0, SCREEN_HEIGHT - 1);
+
int yOffset = TinselV2 ? (g_system->getHeight() - _screenSurface.h) / 2 : 0;
g_system->warpMouse(pt.x, pt.y + yOffset);
_mousePos = pt;
diff --git a/engines/toltecs/POTFILES b/engines/toltecs/POTFILES
new file mode 100644
index 0000000000..81adbb86a1
--- /dev/null
+++ b/engines/toltecs/POTFILES
@@ -0,0 +1,2 @@
+engines/toltecs/detection.cpp
+engines/toltecs/menu.cpp
diff --git a/engines/toltecs/configure.engine b/engines/toltecs/configure.engine
new file mode 100644
index 0000000000..be5533efa2
--- /dev/null
+++ b/engines/toltecs/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine toltecs "3 Skulls of the Toltecs" yes
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index c5652f0c8d..380f4a3a26 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -73,6 +73,20 @@ static const ToltecsGameDescription gameDescriptions[] = {
},
{
+ // 3 Skulls of the Toltecs English version (alternate)
+ // From bug #3614933
+ {
+ "toltecs",
+ 0,
+ AD_ENTRY1s("WESTERN", "a9c9cfef9d05b8f7a5573b626fa4ea87", 337643527),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
+ {
// 3 Skulls of the Toltecs Russian version
{
"toltecs",
diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp
index b52d7dad82..0850630c43 100644
--- a/engines/toltecs/menu.cpp
+++ b/engines/toltecs/menu.cpp
@@ -69,7 +69,7 @@ int MenuSystem::run(MenuID menuId) {
_vm->_screen->blastSprite(0x140 + _vm->_cameraX, 0x175 + _vm->_cameraY, 0, 1, 0x4000);
shadeRect(60, 39, 520, 247, 225, 229);
- memcpy(_background->pixels, _vm->_screen->_frontScreen, 640 * 400);
+ memcpy(_background->getPixels(), _vm->_screen->_frontScreen, 640 * 400);
while (_running) {
update();
@@ -229,7 +229,7 @@ void MenuSystem::initMenu(MenuID menuID) {
_items.clear();
- memcpy(_vm->_screen->_frontScreen, _background->pixels, 640 * 400);
+ memcpy(_vm->_screen->_frontScreen, _background->getPixels(), 640 * 400);
switch (menuID) {
case kMenuIdMain:
diff --git a/engines/toltecs/render.cpp b/engines/toltecs/render.cpp
index 4c41e6ce00..ae458d40a3 100644
--- a/engines/toltecs/render.cpp
+++ b/engines/toltecs/render.cpp
@@ -156,7 +156,7 @@ void RenderQueue::update() {
byte *srcp = _vm->_screen->_backScreen + _vm->_cameraX + _vm->_cameraY * _vm->_sceneWidth;
int16 w = MIN<int16>(640, _vm->_sceneWidth);
int16 h = MIN<int16>(400, _vm->_cameraHeight);
- while (h--) {
+ while (h--) {
memcpy(destp, srcp, w);
destp += 640;
srcp += _vm->_sceneWidth;
diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp
index 6c195a34c2..4edcc601b8 100644
--- a/engines/toltecs/saveload.cpp
+++ b/engines/toltecs/saveload.cpp
@@ -183,7 +183,7 @@ void ToltecsEngine::loadgame(const char *filename) {
_mouseDisabled = in->readUint16LE();
_system->warpMouse(_mouseX, _mouseY);
- _system->showMouse(_mouseDisabled == 0);
+ _system->showMouse(_mouseDisabled == 0);
_palette->loadState(in);
_script->loadState(in);
diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp
index 5e12773e1b..dd418be71f 100644
--- a/engines/toltecs/screen.cpp
+++ b/engines/toltecs/screen.cpp
@@ -599,7 +599,7 @@ int16 Screen::drawString(int16 x, int16 y, byte color, uint fontResIndex, const
if (ywobble)
yadd = *ywobble;
- while (len--) {
+ while (len--) {
byte ch = *text++;
if (ch <= 0x20) {
x += font.getWidth();
@@ -634,7 +634,7 @@ void Screen::drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, b
byte flags = charData[0] & 0xF0;
charData++;
if ((flags & 0x80) == 0) {
- if (flags & 0x10) {
+ if (flags & 0x10) {
memset(dest, color, count);
} else if (outline) {
memset(dest, 0, count);
@@ -651,7 +651,7 @@ void Screen::drawSurface(int16 x, int16 y, Graphics::Surface *surface) {
int16 skipX = 0;
int16 width = surface->w;
int16 height = surface->h;
- byte *surfacePixels = (byte *)surface->getBasePtr(0, 0);
+ byte *surfacePixels = (byte *)surface->getPixels();
byte *frontScreen;
// Not on screen, skip
diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp
index 476c3a4fcf..83c4ef15fe 100644
--- a/engines/toltecs/script.cpp
+++ b/engines/toltecs/script.cpp
@@ -65,7 +65,7 @@ ScriptInterpreter::ScriptInterpreter(ToltecsEngine *vm) : _vm(vm) {
_savedSp = 0;
_slots[kMaxScriptSlots - 1].size = 1024;
- _slots[kMaxScriptSlots - 1].data = new byte[_slots[kMaxScriptSlots - 1].size];
+ _slots[kMaxScriptSlots - 1].data = new byte[_slots[kMaxScriptSlots - 1].size];
setupScriptFunctions();
@@ -184,11 +184,11 @@ void ScriptInterpreter::loadScript(uint resIndex, uint slotIndex) {
delete[] _slots[slotIndex].data;
- _slots[slotIndex].resIndex = resIndex;
+ _slots[slotIndex].resIndex = resIndex;
Resource *scriptResource = _vm->_res->load(resIndex);
_slots[slotIndex].size = scriptResource->size;
- _slots[slotIndex].data = new byte[_slots[slotIndex].size];
- memcpy(_slots[slotIndex].data, scriptResource->data, _slots[slotIndex].size);
+ _slots[slotIndex].data = new byte[_slots[slotIndex].size];
+ memcpy(_slots[slotIndex].data, scriptResource->data, _slots[slotIndex].size);
}
void ScriptInterpreter::setMainScript(uint slotIndex) {
@@ -852,7 +852,7 @@ void ScriptInterpreter::sfFindMouseInRectIndex2() {
}
void ScriptInterpreter::sfDrawGuiImage() {
- _vm->_screen->drawGuiImage(arg16(5), arg16(3), arg16(7));
+ _vm->_screen->drawGuiImage(arg16(5), arg16(3), arg16(7));
}
void ScriptInterpreter::sfAddAnimatedSpriteNoLoop() {
diff --git a/engines/toltecs/segmap.cpp b/engines/toltecs/segmap.cpp
index b06c0af675..fea40f3277 100644
--- a/engines/toltecs/segmap.cpp
+++ b/engines/toltecs/segmap.cpp
@@ -373,7 +373,7 @@ void SegmentMap::loadSegmapMaskRectSurface(byte *maskData, SegmapMaskRect &maskR
maskRect.surface->create(maskRect.width, maskRect.height, Graphics::PixelFormat::createFormatCLUT8());
byte *backScreen = _vm->_screen->_backScreen + maskRect.x + (maskRect.y * _vm->_sceneWidth);
- byte *dest = (byte *)maskRect.surface->getBasePtr(0, 0);
+ byte *dest = (byte *)maskRect.surface->getPixels();
for (int16 h = 0; h < maskRect.height; h++) {
int16 w = maskRect.width;
diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp
index 188facd63c..8bd824cfee 100644
--- a/engines/toltecs/toltecs.cpp
+++ b/engines/toltecs/toltecs.cpp
@@ -235,7 +235,7 @@ void ToltecsEngine::loadScene(uint resIndex) {
byte *source = scene + 392;
byte *destp = _screen->_backScreen;
byte *destEnd = destp + _sceneWidth * _sceneHeight;
- while (destp < destEnd) {
+ while (destp < destEnd) {
int count = 1;
byte pixel = *source++;
if (pixel & 0x80) {
@@ -250,7 +250,7 @@ void ToltecsEngine::loadScene(uint resIndex) {
debug(0, "_sceneWidth = %d; _sceneHeight = %d", _sceneWidth, _sceneHeight);
// Load scene segmap
- _segmap->load(scene + imageSize + 4);
+ _segmap->load(scene + imageSize + 4);
_screen->_fullRefresh = true;
_screen->_renderQueue->clear();
@@ -574,9 +574,9 @@ void ToltecsEngine::walk(byte *walkData) {
if (ydelta > ABS(walkInfo.x1 - walkInfo.x2) * _walkSpeedX) {
v10 = 100 - walkInfo.scaling;
v11 = v8;
- } else {
+ } else {
v10 = v8;
- v11 = 100 - walkInfo.scaling;
+ v11 = 100 - walkInfo.scaling;
}
walkInfo.yerror += walkInfo.mulValue * v10;
diff --git a/engines/tony/configure.engine b/engines/tony/configure.engine
new file mode 100644
index 0000000000..f85f45d158
--- /dev/null
+++ b/engines/tony/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit"
diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp
index 1094950e2c..d355450153 100644
--- a/engines/tony/detection.cpp
+++ b/engines/tony/detection.cpp
@@ -154,26 +154,16 @@ void TonyMetaEngine::removeSaveState(const char *target, int slot) const {
SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::String saveName;
byte difficulty;
- byte thumbData[160 * 120 * 2];
-
- if (Tony::RMOptionScreen::loadThumbnailFromSaveState(slot, thumbData, saveName, difficulty)) {
- // Convert the 565 thumbnail data to the needed overlay format
- Common::MemoryReadStream thumbStream(thumbData, 160 * 120 * 2);
- Graphics::PixelFormat destFormat = g_system->getOverlayFormat();
- Graphics::Surface *to = new Graphics::Surface();
- to->create(160, 120, destFormat);
-
- OverlayColor *pixels = (OverlayColor *)to->pixels;
- for (int y = 0; y < to->h; ++y) {
- for (int x = 0; x < to->w; ++x) {
- uint8 r, g, b;
- Graphics::colorToRGB<Graphics::ColorMasks<555> >(thumbStream.readUint16LE(), r, g, b);
-
- // converting to current OSystem Color
- *pixels++ = destFormat.RGBToColor(r, g, b);
- }
- }
+ Graphics::Surface *to = new Graphics::Surface();
+ to->create(160, 120, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+
+ if (Tony::RMOptionScreen::loadThumbnailFromSaveState(slot, (byte *)to->getPixels(), saveName, difficulty)) {
+#ifdef SCUMM_BIG_ENDIAN
+ uint16 *pixels = (uint16 *)to->getPixels();
+ for (int i = 0; i < to->w * to->h; ++i)
+ pixels[i] = READ_LE_UINT16(pixels + i);
+#endif
// Create the return descriptor
SaveStateDescriptor desc(slot, saveName);
desc.setDeletableFlag(true);
@@ -183,6 +173,7 @@ SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int s
return desc;
}
+ delete to;
return SaveStateDescriptor();
}
diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h
index ee137927dc..ca16495903 100644
--- a/engines/tony/detection_tables.h
+++ b/engines/tony/detection_tables.h
@@ -196,6 +196,40 @@ static const TonyGameDescription gameDescriptions[] = {
},
},
+ {
+ // Tony Tough English Unpacked
+ {
+ "tony",
+ 0,
+ {
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "57c4a3860cf899443c357e0078ea6f49", 366773},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
+ {
+ // Tony Tough German "Shoe Box", reported in bug #3582420
+ {
+ "tony",
+ 0,
+ {
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "bc3471f098e591dc509dcad401a8d8a5", 389554},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
{ AD_TABLE_END_MARKER }
};
diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp
index 501a588ff5..ca7c07ad8c 100644
--- a/engines/tony/game.cpp
+++ b/engines/tony/game.cpp
@@ -508,7 +508,8 @@ void RMOptionScreen::refreshThumbnails() {
_curThumb[i] = NULL;
_curThumbName[i].clear();
_curThumbDiff[i] = 11;
- }
+ } else
+ _curThumb[i]->prepareImage();
}
}
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index dc82c78ee5..3433ad3024 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -117,6 +117,7 @@ RMGfxBuffer::operator void *() {
}
RMGfxBuffer::RMGfxBuffer(int dimx, int dimy, int nBpp) {
+ _origBuf = _buf = NULL;
create(dimx, dimy, nBpp);
}
@@ -1865,7 +1866,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..9e8f5225c0 100644
--- a/engines/tony/gfxcore.h
+++ b/engines/tony/gfxcore.h
@@ -208,8 +208,10 @@ public:
* 16-bit color source
*/
class RMGfxSourceBuffer16 : public RMGfxSourceBuffer {
-protected:
+public:
virtual void prepareImage();
+
+protected:
bool _bTrasp0;
public:
@@ -408,7 +410,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/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp
index cb27e20ab1..7bb25f59b9 100644
--- a/engines/tony/gfxengine.cpp
+++ b/engines/tony/gfxengine.cpp
@@ -530,7 +530,10 @@ void RMGfxEngine::disableMouse() {
#define TONY_SAVEGAME_VERSION 8
void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Common::String &name) {
- Common::OutSaveFile *f;
+ Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(fn);
+ if (f == NULL)
+ return;
+
byte *state;
char buf[4];
RMPoint tp = _tony.position();
@@ -549,10 +552,6 @@ void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Comm
buf[2] = 'S';
buf[3] = TONY_SAVEGAME_VERSION;
- f = g_system->getSavefileManager()->openForSaving(fn);
- if (f == NULL)
- return;
-
f->write(buf, 4);
f->writeUint32LE(thumbsize);
f->write(curThumb, thumbsize);
diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp
index 1a24c5a576..5f2452dcfe 100644
--- a/engines/tony/mpal/mpal.cpp
+++ b/engines/tony/mpal/mpal.cpp
@@ -409,7 +409,7 @@ static uint32 *getSelectList(uint32 i) {
sl[k++] = dialog->_choice[i]._select[j]._dwData;
}
- sl[k] = (uint32)NULL;
+ sl[k] = 0;
return sl;
}
@@ -436,7 +436,7 @@ static uint32 *GetItemList(uint32 nLoc) {
}
}
- il[j] = (uint32)NULL;
+ il[j] = 0;
return il;
}
@@ -521,14 +521,15 @@ static LpItem getItemData(uint32 nOrdItem) {
dat += dim;
}
- // Check if we've got to the end of the file
int i = READ_LE_UINT16(dat);
- if (i != 0xABCD)
- return NULL;
globalUnlock(hDat);
globalFree(hDat);
+ // Check if we've got to the end of the file
+ if (i != 0xABCD)
+ return NULL;
+
return ret;
}
@@ -831,7 +832,7 @@ void LocationPollThread(CORO_PARAM, const void *param) {
if (_ctx->k == 0)
// We can remove this item from the list
- _ctx->il[_ctx->i] = (uint32)NULL;
+ _ctx->il[_ctx->i] = 0;
else
_ctx->nRealItems++;
}
@@ -1875,14 +1876,11 @@ MpalHandle mpalQueryHANDLE(uint16 wQueryType, ...) {
* @remarks This is the specialised version of the original single mpalQuery
* method that needs to run within a co-routine context.
*/
-void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...) {
+void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet) {
CORO_BEGIN_CONTEXT;
uint32 dwRet;
CORO_END_CONTEXT(_ctx);
- va_list v;
- va_start(v, dwRet);
-
CORO_BEGIN_CODE(_ctx);
if (wQueryType == MPQ_DIALOG_WAITFORCHOICE) {
@@ -1908,8 +1906,6 @@ void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...) {
}
CORO_END_CODE;
-
- va_end(v);
}
/**
@@ -1939,7 +1935,7 @@ bool mpalExecuteScript(int nScript) {
// !!! New process management
if (CoroScheduler.createProcess(ScriptThread, &s, sizeof(LpMpalScript)) == CORO_INVALID_PID_VALUE)
- return false;
+ return false;
return true;
}
@@ -2039,7 +2035,13 @@ int mpalGetSaveStateSize() {
void mpalSaveState(byte *buf) {
lockVar();
WRITE_LE_UINT32(buf, GLOBALS._nVars);
- memcpy(buf + 4, (byte *)GLOBALS._lpmvVars, GLOBALS._nVars * sizeof(MpalVar));
+ buf += 4;
+ for (uint i = 0; i < GLOBALS._nVars; ++i) {
+ LpMpalVar var = &GLOBALS._lpmvVars[i];
+ WRITE_LE_UINT32(buf, var->_dwVal);
+ memcpy(buf + 4, var->_lpszVarName, sizeof(var->_lpszVarName));
+ buf += (4 + sizeof(var->_lpszVarName));
+ }
unlockVar();
}
@@ -2054,10 +2056,16 @@ int mpalLoadState(byte *buf) {
globalFree(GLOBALS._hVars);
GLOBALS._nVars = READ_LE_UINT32(buf);
+ buf += 4;
GLOBALS._hVars = globalAllocate(GMEM_ZEROINIT | GMEM_MOVEABLE, GLOBALS._nVars * sizeof(MpalVar));
lockVar();
- memcpy((byte *)GLOBALS._lpmvVars, buf + 4, GLOBALS._nVars * sizeof(MpalVar));
+ for (uint i = 0; i < GLOBALS._nVars; ++i) {
+ LpMpalVar var = &GLOBALS._lpmvVars[i];
+ var->_dwVal = READ_LE_UINT32(buf);
+ memcpy(var->_lpszVarName, buf + 4, sizeof(var->_lpszVarName));
+ buf += (4 + sizeof(var->_lpszVarName));
+ }
unlockVar();
return GLOBALS._nVars * sizeof(MpalVar) + 4;
diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h
index 779bdd6188..2d22ee8faf 100644
--- a/engines/tony/mpal/mpal.h
+++ b/engines/tony/mpal/mpal.h
@@ -417,7 +417,7 @@ MpalHandle mpalQueryHANDLE(uint16 wQueryType, ...);
* @remarks This is the specialised version of the original single mpalQuery
* method that needs to run within a co-routine context.
*/
-void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...);
+void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet);
/**
* Execute a script. The script runs on multitasking by a thread.
diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp
index 90ae241db0..547f31906e 100644
--- a/engines/tony/sound.cpp
+++ b/engines/tony/sound.cpp
@@ -500,7 +500,13 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 codec, int bufSiz
break;
case FPCODEC_ADPCM:
+#ifdef __amigaos4__
+ // HACK: AmigaOS 4 has weird performance problems with reading in the audio thread,
+ // so we read the whole stream into memory.
+ _rewindableStream = Audio::makeADPCMStream(_file.readStream(_size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, 44100, 2);
+#else
_rewindableStream = Audio::makeADPCMStream(&_file, DisposeAfterUse::NO, 0, Audio::kADPCMDVI, 44100, 2);
+#endif
break;
default:
diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp
index 61497a8066..a732862854 100644
--- a/engines/tony/window.cpp
+++ b/engines/tony/window.cpp
@@ -330,6 +330,14 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) {
src += RM_BBX * dezoom;
}
}
+
+#ifdef SCUMM_BIG_ENDIAN
+ if (lpDestBuf != NULL) {
+ for (int i = 0; i < dimx * dimy; i++) {
+ lpDestBuf[i] = SWAP_BYTES_16(lpDestBuf[i]);
+ }
+ }
+#endif
}
} // End of namespace Tony
diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index a6744568f7..19e997af34 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -41,7 +41,7 @@ bool Animation::loadAnimation(const Common::String &file) {
if (strncmp((char *)fileData, "KevinAguilar", 12))
return false;
- strcpy(_name, file.c_str());
+ Common::strlcpy(_name, file.c_str(), 32);
uint32 headerSize = READ_LE_UINT32(fileData + 16);
uint32 uncompressedBytes = READ_LE_UINT32(fileData + 20);
@@ -52,6 +52,7 @@ bool Animation::loadAnimation(const Common::String &file) {
_x2 = READ_LE_UINT32(fileData + 40);
_y2 = READ_LE_UINT32(fileData + 44);
_paletteEntries = READ_LE_UINT32(fileData + 56);
+ // CHECKME: Useless variable _fps
_fps = READ_LE_UINT32(fileData + 60);
uint32 paletteSize = READ_LE_UINT32(fileData + 64);
@@ -119,6 +120,10 @@ Animation::Animation(ToonEngine *vm) : _vm(vm) {
_palette = NULL;
_numFrames = 0;
_frames = NULL;
+
+ _x1 = _y1 = _x2 = _y2 = 0;
+ _fps = 0;
+ _paletteEntries = 0;
}
Animation::~Animation() {
@@ -190,7 +195,7 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int16 xx, int
int32 destPitch = surface.pitch;
uint8 *srcRow = _frames[frame]._data + offsX + (_frames[frame]._x2 - _frames[frame]._x1) * offsY;
- uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1 + offsY) * destPitch + (xx + _x1 + _frames[frame]._x1 + offsX);
+ uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1 + offsX, yy + _frames[frame]._y1 + _y1 + offsY);
for (int16 y = 0; y < rectY; y++) {
uint8 *cur = curRow;
uint8 *c = srcRow + y * (_frames[frame]._x2 - _frames[frame]._x1);
@@ -231,7 +236,7 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
uint8 *c = _frames[frame]._data;
- uint8 *curRow = (uint8 *)surface.pixels;
+ uint8 *curRow = (uint8 *)surface.getPixels();
uint8 *curRowMask = mask->getDataPtr();
bool shadowFlag = false;
@@ -341,7 +346,7 @@ void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int16 xx,
int32 destPitch = surface.pitch;
uint8 *c = _frames[frame]._data;
- uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1) * destPitch + (xx + _x1 + _frames[frame]._x1);
+ uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1, yy + _frames[frame]._y1 + _y1);
for (int16 y = 0; y < rectY; y++) {
unsigned char *cur = curRow;
for (int16 x = 0; x < rectX; x++) {
@@ -448,6 +453,7 @@ AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type)
_y = 0;
_z = 0;
_layerZ = 0;
+ _visible = false;
}
void AnimationInstance::render() {
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index bc0e051057..303f6774fa 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -228,6 +228,7 @@ void AudioManager::stopMusic() {
AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer, Common::SeekableReadStream *stream , bool looping, bool deleteFileStreamAtEnd) {
_compBufferSize = 0;
_buffer = NULL;
+ _bufferSize = 0;
_bufferMaxSize = 0;
_mixer = mixer;
_compBuffer = NULL;
@@ -255,6 +256,8 @@ AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer,
} else {
stopNow();
}
+
+ _soundType = Audio::Mixer::kPlainSoundType;
}
AudioStreamInstance::~AudioStreamInstance() {
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index 479f4965f3..baab8888cf 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -58,12 +58,14 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_animSpecialDefaultId = 0;
_currentPathNode = 0;
_currentWalkStamp = 0;
+ _currentFacingStamp = 0;
_visible = true;
_speed = 150; // 150 = nominal drew speed
_lastWalkTime = 0;
_numPixelToWalk = 0;
_nextIdleTime = _vm->_system->getMillis() + (_vm->randRange(0, 600) + 300) * _vm->getTickLength();
_lineToSayId = 0;
+ _time = 0;
}
Character::~Character(void) {
@@ -99,6 +101,9 @@ void Character::setFacing(int32 facing) {
if (_blockingWalk) {
_flags |= 2;
+ _currentFacingStamp++;
+ int32 localFacingStamp = _currentFacingStamp;
+
int32 dir = 0;
_lastWalkTime = _vm->_system->getMillis();
@@ -127,6 +132,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/toon/configure.engine b/engines/toon/configure.engine
new file mode 100644
index 0000000000..00c98f7d8a
--- /dev/null
+++ b/engines/toon/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine toon "Toonstruck" yes
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index e26ed92f83..2ba4eff652 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -32,6 +32,8 @@ FontRenderer::FontRenderer(ToonEngine *vm) : _vm(vm) {
_currentFontColor[1] = 0xc8;
_currentFontColor[2] = 0xcb;
_currentFontColor[3] = 0xce;
+
+ _currentFont = nullptr;
}
FontRenderer::~FontRenderer() {
@@ -195,8 +197,7 @@ void FontRenderer::renderMultiLineText(int16 x, int16 y, const Common::String &o
// divide the text in several lines
// based on number of characters or size of lines.
byte text[1024];
- strncpy((char *)text, origText.c_str(), 1023);
- text[1023] = 0;
+ Common::strlcpy((char *)text, origText.c_str(), 1024);
byte *lines[16];
int32 lineSize[16];
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index 8c85e20f7c..9e8514d0a8 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -85,7 +85,8 @@ void Movie::play(const Common::String &video, int32 flags) {
_playing = true;
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(0);
- _decoder->loadFile(video.c_str());
+ if (!_decoder->loadFile(video.c_str()))
+ error("Unable to play video %s", video.c_str());
playVideo(isFirstIntroVideo);
_vm->flushPalette(true);
if (flags & 1)
@@ -94,7 +95,7 @@ void Movie::play(const Common::String &video, int32 flags) {
_playing = false;
}
-bool Movie::playVideo(bool isFirstIntroVideo) {
+void Movie::playVideo(bool isFirstIntroVideo) {
debugC(1, kDebugMovie, "playVideo(isFirstIntroVideo: %d)", isFirstIntroVideo);
_decoder->start();
@@ -112,7 +113,7 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
}
_vm->_system->unlockScreen();
} else {
- _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, 0, 0, frame->w, frame->h);
+ _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
// WORKAROUND: There is an encoding glitch in the first intro video. This hides this using the adjacent pixels.
if (isFirstIntroVideo) {
@@ -135,13 +136,13 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
while (_vm->_system->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
_vm->dirtyAllScreen();
- return false;
+ return;
}
_vm->_system->delayMillis(10);
}
_vm->dirtyAllScreen();
- return !_vm->shouldQuit();
+ return;
}
} // End of namespace Toon
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 4dd6583bf6..14287d87fd 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -53,9 +53,8 @@ public:
bool isPlaying() { return _playing; }
protected:
- bool playVideo(bool isFirstIntroVideo);
+ void playVideo(bool isFirstIntroVideo);
ToonEngine *_vm;
- Audio::Mixer *_mixer;
ToonstruckSmackerDecoder *_decoder;
bool _playing;
};
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index 7914aed595..336847e73c 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -152,6 +152,8 @@ PathFinding::PathFinding() {
_heap = new PathFindingHeap();
_sq = NULL;
_numBlockingRects = 0;
+
+ _currentMask = nullptr;
}
PathFinding::~PathFinding(void) {
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index f59cdca064..4927f50e08 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -134,6 +134,11 @@ bool Picture::loadPicture(const Common::String &file) {
Picture::Picture(ToonEngine *vm) : _vm(vm) {
_data = NULL;
_palette = NULL;
+
+ _width = 0;
+ _height = 0;
+ _paletteEntries = 0;
+ _useFullPalette = false;
}
Picture::~Picture() {
@@ -170,7 +175,7 @@ void Picture::drawMask(Graphics::Surface &surface, int16 x, int16 y, int16 dx, i
int32 destPitch = surface.pitch;
int32 srcPitch = _width;
uint8 *c = _data + _width * dy + dx;
- uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x;
+ uint8 *curRow = (uint8 *)surface.getBasePtr(x, y);
for (int16 yy = 0; yy < ry; yy++) {
uint8 *curSrc = c;
@@ -205,7 +210,7 @@ void Picture::drawWithRectList(Graphics::Surface& surface, int16 x, int16 y, int
int16 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
- uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left);
+ uint8 *curRow = (uint8 *)surface.getBasePtr(x + rect.left, y + rect.top);
for (int16 yy = 0; yy < fillRy; yy++) {
uint8 *curSrc = c;
@@ -233,7 +238,7 @@ void Picture::draw(Graphics::Surface &surface, int16 x, int16 y, int16 dx, int16
int32 destPitch = surface.pitch;
int32 srcPitch = _width;
uint8 *c = _data + _width * dy + dx;
- uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x;
+ uint8 *curRow = (uint8 *)surface.getBasePtr(x, y);
for (int16 yy = 0; yy < ry; yy++) {
uint8 *curSrc = c;
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 2d419ec027..ffcabbd348 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -285,6 +285,7 @@ void PakFile::close() {
}
PakFile::PakFile() {
+ _numFiles = 0;
}
PakFile::~PakFile() {
diff --git a/engines/toon/resource.h b/engines/toon/resource.h
index c80ac2216e..b432a1d335 100644
--- a/engines/toon/resource.h
+++ b/engines/toon/resource.h
@@ -53,7 +53,6 @@ protected:
uint32 _numFiles;
Common::Array<File> _files;
- Common::File *_fileHandle;
};
class ToonEngine;
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index 69ae727bb5..d752c277db 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -59,6 +59,8 @@ EMCInterpreter::EMCInterpreter(ToonEngine *vm) : _vm(vm), _scriptData(0), _filen
};
_opcodes = opcodes;
#undef OPCODE
+
+ _parameter = 0;
}
EMCInterpreter::~EMCInterpreter() {
@@ -132,8 +134,7 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo
_scriptData->sysFuncs = opcodes;
- strncpy(_scriptData->filename, filename, 13);
- _scriptData->filename[12] = 0;
+ Common::strlcpy(_scriptData->filename, filename, 13);
_scriptData = 0;
_filename = 0;
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index 1fa4058114..70baaaef22 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -1060,9 +1060,9 @@ int32 ScriptFunc::sys_Cmd_Set_Location_Data(EMCState *state) {
// initial setup of locations
int32 locationId = stackPos(0);
debugC(0, 0, "setlocationdata(%d) %s %x %s %s %d %d", locationId, GetText(1, state), stackPos(2), GetText(3, state), GetText(4, state), stackPos(5), stackPos(6));
- strcpy(_vm->state()->_locations[locationId]._name, GetText(1, state));
- strcpy(_vm->state()->_locations[locationId]._music, GetText(3, state));
- strcpy(_vm->state()->_locations[locationId]._cutaway, GetText(4, state));
+ Common::strlcpy(_vm->state()->_locations[locationId]._name, GetText(1, state), 64);
+ Common::strlcpy(_vm->state()->_locations[locationId]._music, GetText(3, state), 64);
+ Common::strlcpy(_vm->state()->_locations[locationId]._cutaway, GetText(4, state), 64);
_vm->state()->_locations[locationId]._flags = stackPos(2);
_vm->state()->_locations[locationId]._visited = false;
_vm->state()->_locations[locationId]._numSceneAnimations = stackPos(5);
diff --git a/engines/toon/state.cpp b/engines/toon/state.cpp
index 8e4abbd709..fffa8cf529 100644
--- a/engines/toon/state.cpp
+++ b/engines/toon/state.cpp
@@ -115,6 +115,10 @@ State::State(void) {
#endif
memset(_conversationState, 0, sizeof(Conversation) * 60);
+
+ _conversationData = nullptr;
+ _currentConversationId = -1;
+ _exitConversation = true;
}
State::~State(void) {
diff --git a/engines/toon/tools.cpp b/engines/toon/tools.cpp
index added39940..f5c77aca69 100644
--- a/engines/toon/tools.cpp
+++ b/engines/toon/tools.cpp
@@ -136,6 +136,13 @@ uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
RncDecoder::RncDecoder() {
initCrc();
+
+ _bitBuffl = 0;
+ _bitBuffh = 0;
+ _bitCount = 0;
+ _srcPtr = nullptr;
+ _dstPtr = nullptr;
+ _inputByteLeft = 0;
}
RncDecoder::~RncDecoder() { }
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 7ad29ab8d8..7b1456b05c 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -466,8 +466,7 @@ void ToonEngine::doMagnifierEffect() {
int32 cy = CLIP<int32>(posY + y, 0, TOON_BACKBUFFER_HEIGHT-1);
for (int32 x = -12; x <= 12; x++) {
int32 cx = CLIP<int32>(posX + x, 0, TOON_BACKBUFFER_WIDTH-1);
- int32 destPitch = surface.pitch;
- uint8 *curRow = (uint8 *)surface.pixels + cy * destPitch + cx;
+ uint8 *curRow = (uint8 *)surface.getBasePtr(cx, cy);
tempBuffer[(y + 12) * 25 + x + 12] = *curRow;
}
}
@@ -479,8 +478,7 @@ void ToonEngine::doMagnifierEffect() {
if (dist > 144)
continue;
int32 cx = CLIP<int32>(posX + x, 0, TOON_BACKBUFFER_WIDTH-1);
- int32 destPitch = surface.pitch;
- uint8 *curRow = (uint8 *)surface.pixels + cy * destPitch + cx;
+ uint8 *curRow = (uint8 *)surface.getBasePtr(cx, cy);
int32 lerp = (512 + intSqrt[dist] * 256 / 12);
*curRow = tempBuffer[(y * lerp / 1024 + 12) * 25 + x * lerp / 1024 + 12];
}
@@ -501,7 +499,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) {
// we have to refresh everything in case of scrolling.
- _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels() + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
} else {
int32 offX = 0;
@@ -517,7 +515,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
}
rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
- _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ _system->copyRectToScreen((byte *)_mainSurface->getBasePtr(_oldDirtyRects[i].left + offX, _oldDirtyRects[i].top), TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
}
@@ -533,7 +531,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
}
rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
- _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ _system->copyRectToScreen((byte *)_mainSurface->getBasePtr(_dirtyRects[i].left + offX, _dirtyRects[i].top), TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
}
}
@@ -924,6 +922,48 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_gameVariant = 0;
break;
}
+
+ for (int i = 0; i < 64; i++) {
+ _sceneAnimationScripts[i]._lastTimer = 0;
+ _sceneAnimationScripts[i]._frozen = false;
+ _sceneAnimationScripts[i]._frozenForConversation = false;
+ _sceneAnimationScripts[i]._active = false;
+ }
+
+ _lastProcessedSceneScript = 0;
+ _animationSceneScriptRunFlag = false;
+ _updatingSceneScriptRunFlag = false;
+ _dirtyAll = false;
+ _cursorOffsetX = 0;
+ _cursorOffsetY = 0;
+ _currentTextLine = 0;
+ _currentTextLineId = 0;
+ _currentTextLineX = 0;
+ _currentTextLineY = 0;
+ _currentTextLineCharacterId = -1;
+ _oldScrollValue = 0;
+ _drew = nullptr;
+ _flux = nullptr;
+ _currentHotspotItem = 0;
+ _shouldQuit = false;
+ _scriptStep = 0;
+ _oldTimer = 0;
+ _oldTimer2 = 0;
+ _lastRenderTime = 0;
+ _firstFrame = false;
+ _needPaletteFlush = true;
+
+ _numVariant = 0;
+ _currentCutaway = nullptr;
+ for (int i = 0; i < 4; i++) {
+ _scriptState[i].ip = nullptr;
+ _scriptState[i].dataPtr = nullptr;
+ _scriptState[i].retValue = 0;
+ _scriptState[i].bp = 0;
+ _scriptState[i].sp = 0;
+ _scriptState[i].running = false;
+ }
+ _currentScriptRegion = 0;
}
ToonEngine::~ToonEngine() {
diff --git a/engines/touche/configure.engine b/engines/touche/configure.engine
new file mode 100644
index 0000000000..777578e623
--- /dev/null
+++ b/engines/touche/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 5c133ccbc6..b3e3ca5b50 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -51,6 +51,28 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
_saveLoadCurrentSlot = 0;
_hideInventoryTexts = false;
+ _numOpcodes = 0;
+ _compressedSpeechData = 0;
+ _textData = 0;
+ _backdropBuffer = 0;
+ _menuKitData = 0;
+ _convKitData = 0;
+
+ for (int i = 0; i < NUM_SEQUENCES; i++)
+ _sequenceDataTable[i] = 0;
+
+ _programData = 0;
+ _programDataSize = 0;
+ _mouseData = 0;
+ _iconData = 0;
+ _currentBitmapWidth = 0;
+ _currentBitmapHeight = 0;
+ _currentImageWidth = 0;
+ _currentImageHeight = 0;
+ _roomWidth = 0;
+ _programTextDataPtr = 0;
+ _offscreenBuffer = 0;
+
_screenRect = Common::Rect(kScreenWidth, kScreenHeight);
_roomAreaRect = Common::Rect(kScreenWidth, kRoomHeight);
@@ -88,6 +110,63 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
DebugMan.addDebugChannel(kDebugCharset, "Charset", "Charset debug level");
_console = new ToucheConsole(this);
+
+ _newEpisodeNum = 0;
+ _currentEpisodeNum = 0;
+ _currentAmountOfMoney = 0;
+ _giveItemToKeyCharNum = 0;
+ _giveItemToObjectNum = 0;
+ _giveItemToCounter = 0;
+ _currentRoomNum = 0;
+ _waitingSetKeyCharNum1 = 0;
+ _waitingSetKeyCharNum2 = 0;
+ _waitingSetKeyCharNum3 = 0;
+ _script.opcodeNum = 0;
+ _script.dataOffset = 0;
+ _script.keyCharNum = 0;
+ _script.dataPtr = 0;
+ _script.stackDataPtr = 0;
+ _script.stackDataBasePtr = 0;
+ _script.quitFlag = 0;
+ _opcodesTable = 0;
+
+ for (uint i = 0; i < NUM_SPRITES; i++)
+ memset(&_spritesTable[i], 0, sizeof(SpriteData));
+
+ for (uint i = 0; i < NUM_SEQUENCES; i++)
+ memset(&_sequenceEntryTable[i], 0, sizeof(SequenceEntry));
+
+ _talkListEnd = 0;
+ _talkListCurrent = 0;
+ _talkTextRectDefined = 0;
+ _talkTextDisplayed = 0;
+ _talkTextInitialized = 0;
+ _skipTalkText = 0;
+ _talkTextSpeed = 0;
+ _keyCharTalkCounter = 0;
+ _talkTableLastTalkingKeyChar = 0;
+ _talkTableLastOtherKeyChar = 0;
+ _talkTableLastStringNum = 0;
+
+ for (uint i = 0; i < NUM_TALK_ENTRIES; i++)
+ memset(&_talkTable[i], 0, sizeof(TalkEntry));
+
+ _conversationChoicesUpdated = 0;
+ _conversationReplyNum = 0;
+ _conversationEnded = 0;
+ _conversationNum = 0;
+ _scrollConversationChoiceOffset = 0;
+ _currentConversation = 0;
+ _disableConversationScript = 0;
+ _conversationAreaCleared = 0;
+
+ for (uint i = 0; i < NUM_CONVERSATION_CHOICES; i++)
+ memset(&_conversationChoicesTable[i], 0, sizeof(ConversationChoice));
+
+ for (uint i = 0; i < NUM_KEYCHARS; i++)
+ _sortedKeyCharsTable[i] = 0;
+
+ _currentKeyCharNum = 0;
}
ToucheEngine::~ToucheEngine() {
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index 6ac43e7dfe..9cc42b0c68 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -102,7 +102,7 @@ struct KeyChar {
int16 zPosPrev;
int16 prevWalkDataNum;
uint16 textColor;
- int16 inventoryItems[4];
+ int16 inventoryItems[5];
int16 money;
int16 pointsDataNum;
int16 currentWalkBox;
diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp
index 3aef18f4f0..be5fb4c7b7 100644
--- a/engines/tsage/blue_force/blueforce_logic.cpp
+++ b/engines/tsage/blue_force/blueforce_logic.cpp
@@ -454,9 +454,10 @@ void Timer::dispatch() {
if (_endFrame) {
uint32 frameNumber = BF_GLOBALS._events.getFrameNumber();
- if (frameNumber > _endFrame)
+ if (frameNumber > _endFrame) {
// Timer has expired
signal();
+ }
}
}
@@ -472,7 +473,8 @@ void Timer::set(uint32 delay, EventHandler *endHandler) {
/*--------------------------------------------------------------------------*/
TimerExt::TimerExt(): Timer() {
- _action = NULL;
+ _action = nullptr;
+ _newAction = nullptr;
}
void TimerExt::set(uint32 delay, EventHandler *endHandler, Action *newAction) {
@@ -646,8 +648,6 @@ void FocusObject::postInit(SceneObjectList *OwnerList) {
_lookLineNum = 43;
_talkLineNum = 44;
_useLineNum = -1;
- _v90 = 0;
- _v92 = 1;
SceneExt *scene = (SceneExt *)BF_GLOBALS._sceneManager._scene;
scene->_focusObject = this;
@@ -656,8 +656,11 @@ void FocusObject::postInit(SceneObjectList *OwnerList) {
void FocusObject::synchronize(Serializer &s) {
NamedObject::synchronize(s);
- s.syncAsSint16LE(_v90);
- s.syncAsSint16LE(_v92);
+ if (s.getVersion() < 12) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ }
}
void FocusObject::remove() {
@@ -678,7 +681,7 @@ void FocusObject::process(Event &event) {
BF_GLOBALS._events.setCursor(BF_GLOBALS._events.getCursor());
if ((event.eventType == EVENT_BUTTON_DOWN) && (BF_GLOBALS._events.getCursor() == CURSOR_WALK) &&
- (event.btnState == 3)) {
+ (event.btnState == BTNSHIFT_RIGHT)) {
BF_GLOBALS._events.setCursor(CURSOR_USE);
event.handled = true;
}
@@ -703,7 +706,6 @@ SceneExt::SceneExt(): Scene() {
_stripManager._onBegin = SceneExt::startStrip;
_stripManager._onEnd = SceneExt::endStrip;
- _field372 = _field37A = 0;
_savedPlayerEnabled = false;
_savedUiEnabled = false;
_savedCanWalk = false;
@@ -746,6 +748,7 @@ void SceneExt::process(Event &event) {
void SceneExt::dispatch() {
_timerList.dispatch();
+ /*
if (_field37A) {
if ((--_field37A == 0) && BF_GLOBALS._dayNumber) {
if (T2_GLOBALS._uiElements._active && BF_GLOBALS._player._enabled) {
@@ -755,6 +758,7 @@ void SceneExt::dispatch() {
_field37A = 0;
}
}
+ */
Scene::dispatch();
}
@@ -762,8 +766,6 @@ void SceneExt::dispatch() {
void SceneExt::loadScene(int sceneNum) {
Scene::loadScene(sceneNum);
- _v51C34.top = 0;
- _v51C34.bottom = 300;
BF_GLOBALS._sceneHandler->_delayTicks = 1;
}
@@ -831,7 +833,6 @@ void SceneExt::gunDisplay() {
void SceneExt::startStrip() {
SceneExt *scene = (SceneExt *)BF_GLOBALS._sceneManager._scene;
- scene->_field372 = 1;
scene->_savedPlayerEnabled = BF_GLOBALS._player._enabled;
if (scene->_savedPlayerEnabled) {
@@ -839,21 +840,20 @@ void SceneExt::startStrip() {
scene->_savedCanWalk = BF_GLOBALS._player._canWalk;
BF_GLOBALS._player.disableControl();
- if (!BF_GLOBALS._v50696 && T2_GLOBALS._uiElements._active)
+ if (T2_GLOBALS._uiElements._active)
T2_GLOBALS._uiElements.hide();
}
}
void SceneExt::endStrip() {
SceneExt *scene = (SceneExt *)BF_GLOBALS._sceneManager._scene;
- scene->_field372 = 0;
if (scene->_savedPlayerEnabled) {
BF_GLOBALS._player.enableControl();
BF_GLOBALS._player._uiEnabled = scene->_savedUiEnabled;
BF_GLOBALS._player._canWalk = scene->_savedCanWalk;
- if (!BF_GLOBALS._v50696 && T2_GLOBALS._uiElements._active)
+ if (T2_GLOBALS._uiElements._active)
T2_GLOBALS._uiElements.show();
}
}
@@ -865,30 +865,29 @@ void SceneExt::clearScreen() {
/*--------------------------------------------------------------------------*/
PalettedScene::PalettedScene(): SceneExt() {
- _field794 = 0;
+ _hasFader = false;
}
void PalettedScene::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field794);
+ s.syncAsSint16LE(_hasFader);
}
void PalettedScene::postInit(SceneObjectList *OwnerList) {
- _field794 = 0;
+ _hasFader = false;
_palette._field412 = 1;
SceneExt::postInit(OwnerList);
}
void PalettedScene::remove() {
SceneExt::remove();
- if (_field794 == 1) {
+ if (_hasFader) {
for (SynchronizedList<SceneObject *>::iterator i = BF_GLOBALS._sceneObjects->begin();
i != BF_GLOBALS._sceneObjects->end(); ++i)
(*i)->remove();
BF_GLOBALS._sceneObjects->draw();
BF_GLOBALS._scenePalette.loadPalette(2);
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager._hasPalette = true;
}
@@ -896,7 +895,7 @@ void PalettedScene::remove() {
}
PaletteFader *PalettedScene::addFader(const byte *arrBufferRGB, int step, Action *action) {
- _field794 = 1;
+ _hasFader = true;
return BF_GLOBALS._scenePalette.addFader(arrBufferRGB, 1, step, action);
}
@@ -909,6 +908,7 @@ void PalettedScene::add2Faders(const byte *arrBufferRGB, int step, int paletteNu
void PalettedScene::transition(const byte *arrBufferRGB, int percent, int paletteNum, Action *action, int fromColor1, int fromColor2, int toColor1, int toColor2, bool flag) {
byte tmpPalette[768];
+ memset(tmpPalette, 0, 768);
_palette.loadPalette(paletteNum);
_palette.loadPalette(2);
@@ -1260,8 +1260,6 @@ void BlueForceInvObjectList::alterInventory(int mode) {
setObjectScene(INV_TICKET_BOOK, 60);
setObjectScene(INV_MIRANDA_CARD, 60);
- BF_GLOBALS._v4CEC4 = 0;
-
switch (mode) {
case 2:
if (hasPrintout)
diff --git a/engines/tsage/blue_force/blueforce_logic.h b/engines/tsage/blue_force/blueforce_logic.h
index 59bc2b7a51..0045980820 100644
--- a/engines/tsage/blue_force/blueforce_logic.h
+++ b/engines/tsage/blue_force/blueforce_logic.h
@@ -139,14 +139,17 @@ public:
class NamedObject2: public NamedObject {
public:
- int _v1, _v2;
+ int _talkCount;
- NamedObject2() { _v1 = _v2 = 0; }
+ NamedObject2() { _talkCount = 0; }
virtual Common::String getClassName() { return "NamedObject2"; }
virtual void synchronize(Serializer &s) {
NamedObject::synchronize(s);
- s.syncAsSint16LE(_v1);
- s.syncAsSint16LE(_v2);
+ if (s.getVersion() < 12) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ }
+ s.syncAsSint16LE(_talkCount);
}
};
@@ -177,7 +180,6 @@ public:
class FocusObject: public NamedObject {
public:
- int _v90, _v92;
GfxSurface _img;
FocusObject();
@@ -196,16 +198,12 @@ private:
static void endStrip();
public:
AObjectArray _timerList, _objArray2;
- int _field372;
bool _savedPlayerEnabled;
bool _savedUiEnabled;
bool _savedCanWalk;
- int _field37A;
EventHandler *_focusObject;
Visage _cursorVisage;
-
- Rect _v51C34;
public:
SceneExt();
@@ -228,7 +226,7 @@ public:
class PalettedScene: public SceneExt {
public:
ScenePalette _palette;
- int _field794;
+ bool _hasFader;
public:
PalettedScene();
diff --git a/engines/tsage/blue_force/blueforce_scenes0.cpp b/engines/tsage/blue_force/blueforce_scenes0.cpp
index 95598babc6..06be605c1a 100644
--- a/engines/tsage/blue_force/blueforce_scenes0.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes0.cpp
@@ -343,7 +343,7 @@ void Scene50::synchronize(Serializer &s) {
void Scene50::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
T2_GLOBALS._uiElements._active = false;
BF_GLOBALS._player.postInit();
BF_GLOBALS._player.setVisage(830);
@@ -419,6 +419,8 @@ void Scene50::postInit(SceneObjectList *OwnerList) {
tooltip = &_location8;
xp = 75;
break;
+ default:
+ error("Unexpected tooltip value %d", selectedTooltip);
}
_timer.set(240, this);
@@ -888,6 +890,7 @@ void Scene60::Action1::signal() {
break;
case 4:
remove();
+ break;
case 5:
setDelay(120);
break;
@@ -939,7 +942,6 @@ void Scene60::Action3::signal() {
scene->_stripManager.start(71, this);
break;
case 2:
- scene->_field1222 = true;
BF_GLOBALS._player.enableControl();
remove();
break;
@@ -953,7 +955,6 @@ Scene60::Scene60(): SceneExt() {
_sceneNumber = 0;
_visage = 0;
_cursorId = CURSOR_NONE;
- _field1222 = false;
}
void Scene60::synchronize(Serializer &s) {
@@ -963,7 +964,10 @@ void Scene60::synchronize(Serializer &s) {
s.syncAsSint16LE(_sceneNumber);
s.syncAsSint16LE(_visage);
s.syncAsSint16LE(_cursorId);
- s.syncAsSint16LE(_field1222);
+ if (s.getVersion() < 11) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ }
}
void Scene60::postInit(SceneObjectList *OwnerList) {
diff --git a/engines/tsage/blue_force/blueforce_scenes0.h b/engines/tsage/blue_force/blueforce_scenes0.h
index dd502c5f30..e7ee06e779 100644
--- a/engines/tsage/blue_force/blueforce_scenes0.h
+++ b/engines/tsage/blue_force/blueforce_scenes0.h
@@ -174,8 +174,6 @@ public:
int _sceneNumber;
int _visage;
CursorType _cursorId;
- // TODO: Check if really useless in original
- bool _field1222;
Scene60();
virtual void synchronize(Serializer &s);
diff --git a/engines/tsage/blue_force/blueforce_scenes1.cpp b/engines/tsage/blue_force/blueforce_scenes1.cpp
index 9f1e9ce36e..fa877ea6c9 100644
--- a/engines/tsage/blue_force/blueforce_scenes1.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes1.cpp
@@ -176,7 +176,6 @@ void Scene100::postInit(SceneObjectList *OwnerList) {
loadScene(101);
}
BF_GLOBALS._scenePalette.loadPalette(2);
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
g_globals->_player.postInit();
@@ -232,7 +231,6 @@ void Scene109::Action1::signal() {
scene->_text.setup(BF_19840515, this);
break;
case 3:
- BF_GLOBALS._v51C44 = 1;
scene->loadScene(115);
scene->_protaginist2.show();
@@ -246,7 +244,6 @@ void Scene109::Action1::signal() {
scene->_beerSign.show();
scene->_beerSign.setAction(&scene->_action2);
- BF_GLOBALS._v501FC = 170;
setDelay(60);
break;
case 4:
@@ -401,12 +398,10 @@ void Scene110::Action1::signal() {
scene->_object6.show();
scene->_object9.show();
scene->_object10.show();
- BF_GLOBALS._v51C44 = 1;
scene->loadScene(110);
setDelay(10);
break;
case 2:
- BF_GLOBALS._v51C44 = 1;
scene->_object1.animate(ANIM_MODE_5, this);
break;
case 3: {
@@ -1833,8 +1828,6 @@ void Scene125::Action2::signal() {
setDelay(20);
break;
case 2: {
- BF_GLOBALS._v501FA = 10;
- BF_GLOBALS._v51C44 = 1;
Common::Point destPos(202, 94);
NpcMover *mover = new NpcMover();
BF_GLOBALS._player.addMover(mover, &destPos, this);
@@ -2311,7 +2304,6 @@ void Scene140::Action1::signal() {
setDelay(60);
// No break on purpose
case 13:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(150);
default:
break;
@@ -2337,9 +2329,6 @@ void Scene140::postInit(SceneObjectList *OwnerList) {
_object1.changeZoom(100);
_object1.hide();
- BF_GLOBALS._v5020C = 0;
- BF_GLOBALS._v501F8 = 300;
- BF_GLOBALS._v501FC = 90;
BF_GLOBALS._sound1.play(7);
_object2.setAction(&_action1);
@@ -2640,7 +2629,6 @@ void Scene160::Action2::signal() {
BF_GLOBALS._sound1.stop();
// End of hack
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(200);
break;
default:
@@ -2649,7 +2637,7 @@ void Scene160::Action2::signal() {
}
void Scene160::Action2::process(Event &event) {
- if ((event.handled) || (event.eventType == 5))
+ if ((event.handled) || ((event.eventType != EVENT_BUTTON_DOWN) && (event.eventType != EVENT_KEYPRESS)))
return;
if (_actionIndex == 25) {
@@ -2788,9 +2776,6 @@ void Scene180::postInit(SceneObjectList *OwnerList) {
setZoomPercents(121, 60, 125, 70);
if ((BF_GLOBALS._bookmark == bLyleStoppedBy) && (BF_GLOBALS._dayNumber == 1)) {
- BF_GLOBALS._v501FC = 87;
- BF_GLOBALS._v501FA = _sceneBounds.left + 10;
- // CHECKME: BF_GLOBALS._v50206 = 18; ??
_sceneMessage.setup(THE_NEXT_DAY);
_sceneMode = 6;
setAction(&_sceneMessage, this);
@@ -2799,9 +2784,6 @@ void Scene180::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._mapLocationId = 4;
} else if (((BF_GLOBALS._bookmark == bDroppedOffLyle) && (BF_GLOBALS._dayNumber == 3)) ||
((BF_GLOBALS._bookmark == bDoneAtLyles) && (BF_GLOBALS._dayNumber == 4))) {
- BF_GLOBALS._v501FC = 87;
- BF_GLOBALS._v501FA = _sceneBounds.left + 10;
- // CHECKME: BF_GLOBALS._v50206 = 18; ??
_sceneMessage.setup(THE_NEXT_DAY);
_sceneMode = 6;
setAction(&_sceneMessage, this);
@@ -3237,7 +3219,7 @@ void Scene190::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._player.postInit();
BF_GLOBALS._player.disableControl();
- // Initialise objects
+ // Initialize objects
_door.postInit();
_door.setVisage(190);
_door.setStrip(1);
diff --git a/engines/tsage/blue_force/blueforce_scenes2.cpp b/engines/tsage/blue_force/blueforce_scenes2.cpp
index c992afe620..1b0ed2a145 100644
--- a/engines/tsage/blue_force/blueforce_scenes2.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes2.cpp
@@ -1603,7 +1603,6 @@ void Scene271::signal() {
}
break;
case 12:
- BF_GLOBALS._v51C44 = 0;
BF_GLOBALS._sound1.changeSound(67);
BF_GLOBALS._sceneManager.changeScene(280);
break;
@@ -1617,7 +1616,6 @@ void Scene271::signal() {
_field2E16 = 1;
break;
case 2704:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sound1.fadeOut2(NULL);
BF_GLOBALS._sceneManager.changeScene(690);
break;
@@ -1649,7 +1647,6 @@ void Scene271::signal() {
addFader((const byte *)&black, 2, this);
break;
case 2712:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sound1.fadeOut2(NULL);
BF_GLOBALS._sceneManager.changeScene(180);
break;
@@ -1657,7 +1654,6 @@ void Scene271::signal() {
BF_GLOBALS._player.enableControl();
break;
case 2714:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(560);
break;
case 2715:
diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp
index 81e4af6e97..feaf789392 100644
--- a/engines/tsage/blue_force/blueforce_scenes3.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes3.cpp
@@ -564,7 +564,6 @@ void Scene300::dispatch() {
if ((BF_GLOBALS._player._position.y < 59) && (BF_GLOBALS._player._position.x > 137) &&
(_sceneMode != 6308) && (_sceneMode != 7308)) {
- // The original was setting a useless global variable (removed)
_sceneMode = 6308;
BF_GLOBALS._player.disableControl();
ADD_MOVER(BF_GLOBALS._player, BF_GLOBALS._player._position.x + 20,
@@ -967,7 +966,6 @@ void Scene315::Action1::signal() {
/*--------------------------------------------------------------------------*/
Scene315::Scene315() {
- BF_GLOBALS._v51C44 = 1;
_field1B6C = _field139C = 0;
if (BF_GLOBALS._dayNumber == 0)
BF_GLOBALS._dayNumber = 1;
@@ -977,12 +975,19 @@ Scene315::Scene315() {
_doorOpened = false;
_invGreenCount = _bookGreenCount = 0;
_invGangCount = _bookGangCount = 0;
+
+ _stripNumber = 0;
+ _field1398 = 0;
+ _currentCursor = INV_NONE;
}
void Scene315::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field1390);
+ if (s.getVersion() < 11) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ }
s.syncAsSint16LE(_stripNumber);
s.syncAsSint16LE(_field1398);
s.syncAsSint16LE(_invGreenCount);
@@ -1399,7 +1404,7 @@ bool Scene325::Item1::startAction(CursorType action, Event &event) {
void Scene325::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
loadScene(325);
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
BF_GLOBALS.clearFlag(fCanDrawGun);
if (BF_GLOBALS._dayNumber == 0)
@@ -1973,12 +1978,7 @@ void Scene340::Action8::signal() {
setDelay(6);
break;
- case 4:
- remove();
- break;
default:
- // This is present in the original game
- warning("Bugs");
remove();
break;
}
@@ -2868,9 +2868,9 @@ void Scene350::checkGun() {
void Scene355::Doorway::synchronize(Serializer &s) {
NamedObject::synchronize(s);
- s.syncAsSint16LE(_v1);
- s.syncAsSint16LE(_v2);
- s.syncAsSint16LE(_v3);
+ s.syncAsSint16LE(_mode1356Count);
+ s.syncAsSint16LE(_talkCount);
+ s.syncAsSint16LE(_onDuty);
}
bool Scene355::Doorway::startAction(CursorType action, Event &event) {
@@ -2890,9 +2890,9 @@ bool Scene355::Doorway::startAction(CursorType action, Event &event) {
return true;
case CURSOR_TALK:
if (BF_GLOBALS._dayNumber >= 5) {
- switch (_v2) {
+ switch (_talkCount) {
case 0:
- ++_v2;
+ ++_talkCount;
BF_GLOBALS._sound1.play(109);
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 0;
@@ -2920,7 +2920,7 @@ bool Scene355::Doorway::startAction(CursorType action, Event &event) {
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 3562;
scene->setAction(&scene->_sequenceManager, scene, 3562, &BF_GLOBALS._player, NULL);
- _v3 = !_v3 ? 1 : 0;
+ _onDuty = !_onDuty;
return true;
default:
break;
@@ -3355,14 +3355,14 @@ bool Scene355::Item11::startAction(CursorType action, Event &event) {
return true;
case CURSOR_TALK:
if (BF_GLOBALS._dayNumber == 5) {
- switch (scene->_doorway._v2) {
+ switch (scene->_doorway._talkCount) {
case 0:
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 0;
BF_GLOBALS.setFlag(fTookTrailerAmmo);
scene->_stripManager.start(3575, scene);
scene->_lyle._flag = 1;
- scene->_doorway._v2 = 1;
+ scene->_doorway._talkCount = 1;
break;
case 1:
BF_GLOBALS._player.disableControl();
@@ -3534,28 +3534,28 @@ void Scene355::postInit(SceneObjectList *OwnerList) {
_doorway.setVisage(355);
_doorway.setPosition(Common::Point(193, 105));
_doorway.fixPriority(18);
- _doorway._v1 = 0;
- _doorway._v3 = 0;
+ _doorway._mode1356Count = 0;
+ _doorway._onDuty = false;
BF_GLOBALS._sceneItems.push_back(&_doorway);
switch (BF_GLOBALS._dayNumber) {
case 1:
if (!BF_GLOBALS.getFlag(onDuty))
- _doorway._v3 = 1;
+ _doorway._onDuty = true;
else if (BF_INVENTORY.getObjectScene(INV_GREENS_GUN) == 320)
- _doorway._v3 = 1;
+ _doorway._onDuty = true;
break;
case 2:
case 3:
case 4:
- _doorway._v3 = 1;
+ _doorway._onDuty = true;
break;
default:
break;
}
if (BF_GLOBALS._dayNumber == 5)
- _doorway._v2 = BF_GLOBALS.getFlag(fTookTrailerAmmo) ? 1 : 0;
+ _doorway._talkCount = BF_GLOBALS.getFlag(fTookTrailerAmmo) ? 1 : 0;
_object8.postInit();
_object8.setVisage(355);
@@ -3614,8 +3614,8 @@ void Scene355::postInit(SceneObjectList *OwnerList) {
_object11.animate(ANIM_MODE_2);
_doorway.setPosition(Common::Point(146, 107));
- _doorway._v3 = 0;
- _doorway._v2 = 2;
+ _doorway._onDuty = false;
+ _doorway._talkCount = 2;
_lyle._flag = 2;
_green.postInit();
@@ -3713,16 +3713,16 @@ void Scene355::signal() {
_stripManager.start(BF_GLOBALS.getFlag(fBackupIn350) ? 3559 : 3554, this);
break;
case 1356:
- switch (_doorway._v1) {
+ switch (_doorway._mode1356Count) {
case 0:
- ++_doorway._v1;
+ ++_doorway._mode1356Count;
_sceneMode = 9999;
_stripManager.start(3550, this);
break;
case 1:
_sceneMode = 9999;
_stripManager.start(3551, this);
- ++_doorway._v1;
+ ++_doorway._mode1356Count;
break;
default:
break;
@@ -3787,7 +3787,7 @@ void Scene355::signal() {
T2_GLOBALS._uiElements.addScore(10);
}
- SceneItem::display2(355, !_doorway._v3 ? 24 : 25);
+ SceneItem::display2(355, !_doorway._onDuty ? 24 : 25);
BF_GLOBALS._player.enableControl();
break;
case 4550:
@@ -3796,8 +3796,8 @@ void Scene355::signal() {
BF_GLOBALS._sound1.play(90);
BF_GLOBALS._player._regionBitList |= 0x10;
- _doorway._v3 = 0;
- _doorway._v2 = 2;
+ _doorway._onDuty = false;
+ _doorway._talkCount = 2;
_lyle._flag = 2;
BF_GLOBALS._player.enableControl();
break;
@@ -3867,13 +3867,13 @@ void Scene355::signal() {
case 9984:
if (BF_GLOBALS._dayNumber == 5) {
_sceneMode = 0;
- switch (_doorway._v2) {
+ switch (_doorway._talkCount) {
case 0:
BF_GLOBALS._sound1.play(109);
BF_GLOBALS.setFlag(fTookTrailerAmmo);
_stripManager.start(3575, this);
_lyle._flag = 1;
- ++_doorway._v2;
+ ++_doorway._talkCount;
break;
case 1:
_stripManager.start(3573, this);
@@ -3884,7 +3884,7 @@ void Scene355::signal() {
break;
}
} else if (BF_GLOBALS.getFlag(greenTaken) || (BF_GLOBALS._dayNumber > 1)) {
- if (_doorway._v3) {
+ if (_doorway._onDuty) {
SceneItem::display2(355, 23);
_sceneMode = 0;
signal();
@@ -4009,14 +4009,14 @@ void Scene355::signal() {
}
case 9997:
_sceneMode = 9999;
- _doorway._v1 = 2;
+ _doorway._mode1356Count = 2;
_stripManager.start(3562, this);
break;
case 9998:
error("Talkdoor state");
break;
case 9999:
- if (_doorway._v1 != 2) {
+ if (_doorway._mode1356Count != 2) {
BF_GLOBALS._player.enableControl();
BF_GLOBALS._player._canWalk = false;
} else if (BF_GLOBALS.getFlag(gunDrawn)) {
@@ -4439,7 +4439,6 @@ void Scene360::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._player.enableControl();
if ((BF_GLOBALS._sceneManager._previousScene == 355) || (BF_GLOBALS._sceneManager._previousScene != 370)) {
- // The original was using there a useless variable (now removed)
BF_GLOBALS._player.setPosition(Common::Point(253, 135));
BF_GLOBALS._player.setStrip(2);
@@ -4527,7 +4526,7 @@ void Scene360::signal() {
BF_GLOBALS._player.enableControl();
break;
case 3608:
- BF_GLOBALS._sceneManager.changeScene(355);
+ BF_GLOBALS._sceneManager.changeScene(355);
break;
case 3610:
BF_GLOBALS._sceneManager.changeScene(666);
@@ -4652,10 +4651,10 @@ bool Scene370::Green::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_LOOK:
- SceneItem::display2(370, (_v2 < 3) ? 10 : 0);
+ SceneItem::display2(370, (_talkCount < 3) ? 10 : 0);
return true;
case CURSOR_USE:
- if (_v2 != 3)
+ if (_talkCount != 3)
SceneItem::display2(370, 1);
else if (BF_INVENTORY.getObjectScene(INV_HANDCUFFS) == 1)
SceneItem::display2(370, 26);
@@ -4671,14 +4670,14 @@ bool Scene370::Green::startAction(CursorType action, Event &event) {
return true;
case CURSOR_TALK:
BF_GLOBALS._player.disableControl();
- switch (_v2) {
+ switch (_talkCount) {
case 0:
- ++_v2;
+ ++_talkCount;
scene->_sceneMode = 3706;
scene->setAction(&scene->_sequenceManager, scene, 3706, NULL);
break;
case 1:
- ++_v2;
+ ++_talkCount;
scene->_sceneMode = 3707;
scene->_object5.postInit();
@@ -4690,7 +4689,7 @@ bool Scene370::Green::startAction(CursorType action, Event &event) {
scene->setAction(&scene->_sequenceManager, scene, 3707, &scene->_harrison, &scene->_object5, NULL);
break;
case 2:
- ++_v2;
+ ++_talkCount;
scene->_sceneMode = 3708;
scene->setAction(&scene->_sequenceManager, scene, 3708, this, &scene->_laura, &scene->_harrison,
&scene->_object5, &scene->_greensGun, NULL);
@@ -4716,7 +4715,7 @@ bool Scene370::Green::startAction(CursorType action, Event &event) {
}
return true;
case INV_HANDCUFFS:
- if (_v2 != 3)
+ if (_talkCount != 3)
SceneItem::display2(370, 2);
else {
T2_GLOBALS._uiElements.addScore(50);
@@ -4753,7 +4752,7 @@ bool Scene370::Harrison::startAction(CursorType action, Event &event) {
SceneItem::display2(370, 8);
return true;
case CURSOR_TALK:
- if (scene->_green._v2 != 3) {
+ if (scene->_green._talkCount != 3) {
scene->_sceneMode = 3;
scene->_stripManager.start(3714, scene);
} else if ((BF_INVENTORY.getObjectScene(INV_GREENS_KNIFE) == 1) ||
diff --git a/engines/tsage/blue_force/blueforce_scenes3.h b/engines/tsage/blue_force/blueforce_scenes3.h
index ea9d5f7311..894c3e5ffd 100644
--- a/engines/tsage/blue_force/blueforce_scenes3.h
+++ b/engines/tsage/blue_force/blueforce_scenes3.h
@@ -210,7 +210,6 @@ public:
WestExit _westExit;
SouthWestExit _swExit;
Action1 _action1;
- int _field1390;
int _stripNumber;
int _field1398;
int _invGreenCount, _bookGreenCount, _invGangCount;
@@ -494,9 +493,10 @@ class Scene355: public PalettedScene {
/* Objects */
class Doorway: public NamedObject {
public:
- int _v1, _v2, _v3;
+ int _mode1356Count, _talkCount;
+ bool _onDuty;
- Doorway() { _v1 = _v2 = _v3 = 0; }
+ Doorway() { _mode1356Count = _talkCount = 0; _onDuty = false; }
virtual Common::String getClassName() { return "Scene355_Doorway"; }
virtual void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
diff --git a/engines/tsage/blue_force/blueforce_scenes4.cpp b/engines/tsage/blue_force/blueforce_scenes4.cpp
index a10f311791..e4a349bc93 100644
--- a/engines/tsage/blue_force/blueforce_scenes4.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes4.cpp
@@ -39,7 +39,7 @@ namespace BlueForce {
void Scene410::Action1::signal() {
Scene410 *scene = (Scene410 *)BF_GLOBALS._sceneManager._scene;
- switch (scene->_field1FB6++) {
+ switch (scene->_action1Count++) {
case 0:
if (BF_GLOBALS.getFlag(fTalkedDriverNoBkup)) {
setDelay(3);
@@ -136,11 +136,11 @@ void Scene410::Action5::signal() {
switch (_actionIndex++) {
case 0:
- if (scene->_field1FC4 == 0) {
+ if (!scene->_harrisonMovedFl) {
ADD_PLAYER_MOVER(114, 133);
} else {
ADD_PLAYER_MOVER(195, 139);
- }
+ }
break;
case 1:
BF_GLOBALS._player.updateAngle(scene->_passenger._position);
@@ -167,7 +167,7 @@ void Scene410::Action6::signal() {
switch (_actionIndex++) {
case 0:
- if (scene->_field1FC4 == 0) {
+ if (!scene->_harrisonMovedFl) {
ADD_PLAYER_MOVER(114, 133);
} else {
ADD_PLAYER_MOVER(126, 99);
@@ -243,7 +243,7 @@ bool Scene410::Motorcycle::startAction(CursorType action, Event &event) {
} else if (BF_GLOBALS.getFlag(fSearchedTruck) && !BF_GLOBALS._sceneObjects->contains(&scene->_harrison)) {
scene->_sceneMode = 4103;
scene->signal();
- } else if (scene->_field1FBC != 0) {
+ } else if (scene->_cuffedDriverFl) {
SceneItem::display2(410, 12);
} else {
scene->_sceneMode = 4103;
@@ -260,7 +260,7 @@ bool Scene410::TruckFront::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_USE:
- if ((BF_GLOBALS._bookmark < bStoppedFrankie) && (!scene->_field1FBC || !scene->_field1FBA))
+ if ((BF_GLOBALS._bookmark < bStoppedFrankie) && (!scene->_cuffedDriverFl || !scene->_harrissonTalkFl))
break;
else if (BF_GLOBALS.getFlag(fSearchedTruck))
SceneItem::display2(410, 13);
@@ -293,11 +293,11 @@ bool Scene410::Driver::startAction(CursorType action, Event &event) {
} else {
SceneItem::display2(410, 7);
}
- } else if (!scene->_field1FBC) {
+ } else if (!scene->_cuffedDriverFl) {
SceneItem::display2(410, 7);
} else if (!scene->_field1FC0) {
scene->_sceneMode = 4124;
- scene->_field1FC0 = 1;
+ scene->_field1FC0 = true;
T2_GLOBALS._uiElements.addScore(30);
scene->signal();
} else {
@@ -309,13 +309,13 @@ bool Scene410::Driver::startAction(CursorType action, Event &event) {
return true;
case INV_HANDCUFFS:
if (BF_GLOBALS.getFlag(fCalledBackup)) {
- if ((scene->_talkCount < 5) || (scene->_field1FB6 < 1) || (scene->_field1FBC != 0))
+ if ((scene->_talkCount < 5) || (scene->_action1Count < 1) || scene->_cuffedDriverFl)
break;
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 4123;
scene->_stripManager.start(4125, scene);
- scene->_field1FBC = 1;
+ scene->_cuffedDriverFl = true;
T2_GLOBALS._uiElements.addScore(30);
} else {
if (BF_GLOBALS.getFlag(fTalkedDriverNoBkup)) {
@@ -328,14 +328,14 @@ bool Scene410::Driver::startAction(CursorType action, Event &event) {
case INV_TICKET_BOOK:
if (!BF_GLOBALS.getFlag(fDriverOutOfTruck)) {
return startAction(CURSOR_TALK, event);
- } else if (!scene->_field1FC4) {
+ } else if (!scene->_harrisonMovedFl) {
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 2;
scene->setAction(&scene->_sequenceManager1, scene, 4120, &scene->_passenger, &BF_GLOBALS._player, NULL);
- } else if ((scene->_field1FBC != 0) || (scene->_field1FC2 != 0)) {
+ } else if (scene->_cuffedDriverFl || scene->_driverOutOfTruckFl) {
break;
} else {
- scene->_field1FC2 = 1;
+ scene->_driverOutOfTruckFl = true;
T2_GLOBALS._uiElements.addScore(30);
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 4127;
@@ -343,7 +343,7 @@ bool Scene410::Driver::startAction(CursorType action, Event &event) {
}
return true;
case INV_MIRANDA_CARD:
- if (scene->_field1FBC == 0)
+ if (!scene->_cuffedDriverFl)
return false;
if (BF_GLOBALS.getFlag(readFrankRights)) {
@@ -379,15 +379,15 @@ bool Scene410::Passenger::startAction(CursorType action, Event &event) {
SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2,
SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 96, SET_EXT_BGCOLOR, 99,
SET_EXT_FGCOLOR, 13, LIST_END);
- } else if (!scene->_field1FBA) {
+ } else if (!scene->_harrissonTalkFl) {
SceneItem::display(410, 5, SET_WIDTH, 300,
SET_X, 10 + GLOBALS._sceneManager._scene->_sceneBounds.left,
SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2,
SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 96, SET_EXT_BGCOLOR, 99,
SET_EXT_FGCOLOR, 13, LIST_END);
- } else if (!scene->_field1FBE) {
+ } else if (!scene->_cuffedPassengerFl) {
scene->_sceneMode = 4121;
- scene->_field1FBE = 1;
+ scene->_cuffedPassengerFl = true;
T2_GLOBALS._uiElements.addScore(50);
scene->signal();
} else
@@ -398,7 +398,7 @@ bool Scene410::Passenger::startAction(CursorType action, Event &event) {
return true;
case INV_HANDCUFFS:
if (BF_GLOBALS.getFlag(fCalledBackup)) {
- if ((scene->_talkCount < 5) || (scene->_field1FBA != 0))
+ if ((scene->_talkCount < 5) || (scene->_harrissonTalkFl))
break;
BF_GLOBALS._player.disableControl();
@@ -413,7 +413,7 @@ bool Scene410::Passenger::startAction(CursorType action, Event &event) {
}
return true;
case INV_MIRANDA_CARD:
- if (!scene->_field1FBA)
+ if (!scene->_harrissonTalkFl)
break;
if (BF_GLOBALS.getFlag(readFrankRights)) {
@@ -455,7 +455,7 @@ bool Scene410::Harrison::startAction(CursorType action, Event &event) {
SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 32, SET_EXT_BGCOLOR, 49,
SET_EXT_FGCOLOR, 13, LIST_END);
}
- } else if ((scene->_field1FBA != 0) && (scene->_field1FBC != 0)) {
+ } else if (scene->_harrissonTalkFl && scene->_cuffedDriverFl) {
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 4112;
scene->_stripManager.start(4113, scene);
@@ -463,27 +463,27 @@ bool Scene410::Harrison::startAction(CursorType action, Event &event) {
BF_GLOBALS.set2Flags(f1098Frankie);
BF_GLOBALS.clearFlag(f1098Marina);
} else if ((BF_INVENTORY.getObjectScene(INV_HANDCUFFS) == 1) ||
- (!scene->_field1FBA && (scene->_talkCount < 5))) {
+ (!scene->_harrissonTalkFl && (scene->_talkCount < 5))) {
SceneItem::display(350, 13, SET_WIDTH, 300,
SET_X, 10 + GLOBALS._sceneManager._scene->_sceneBounds.left,
SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2,
SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 32, SET_EXT_BGCOLOR, 49,
SET_EXT_FGCOLOR, 13, LIST_END);
- } else if (!scene->_field1FBA) {
+ } else if (!scene->_harrissonTalkFl) {
BF_GLOBALS._player.disableControl();
- scene->_field1FBA = 1;
- scene->_field1FBE = 1;
+ scene->_harrissonTalkFl = true;
+ scene->_cuffedPassengerFl = true;
BF_GLOBALS._walkRegions.enableRegion(22);
scene->_sceneMode = 4122;
scene->_stripManager.start(4112, scene);
- } else if (scene->_field1FB6 < 1) {
+ } else if (scene->_action1Count < 1) {
break;
- } else if (scene->_field1FBC != 0) {
+ } else if (scene->_cuffedDriverFl) {
error("Error - want to cuff driver, but he's cuffed already");
} else {
BF_GLOBALS._player.disableControl();
- scene->_field1FBC = 1;
- scene->_field1FC0 = 1;
+ scene->_cuffedDriverFl = true;
+ scene->_field1FC0 = true;
BF_GLOBALS._walkRegions.enableRegion(22);
scene->_sceneMode = 4109;
scene->_stripManager.start(4112, scene);
@@ -500,20 +500,24 @@ bool Scene410::Harrison::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
Scene410::Scene410(): SceneExt() {
- _field1FB6 = _talkCount = _field1FBA = _field1FBC = 0;
- _field1FBE = _field1FC0 = _field1FC2 = _field1FC4 = 0;
+ _cuffedDriverFl = _harrissonTalkFl = _driverOutOfTruckFl = false;
+ _harrisonMovedFl = false;
+
+ _action1Count = _talkCount = 0;
+ _cuffedPassengerFl = false;
+ _field1FC0 = false;
}
void Scene410::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field1FB6);
+ s.syncAsSint16LE(_action1Count);
s.syncAsSint16LE(_talkCount);
- s.syncAsSint16LE(_field1FBA);
- s.syncAsSint16LE(_field1FBC);
- s.syncAsSint16LE(_field1FBE);
+ s.syncAsSint16LE(_harrissonTalkFl);
+ s.syncAsSint16LE(_cuffedDriverFl);
+ s.syncAsSint16LE(_cuffedPassengerFl);
s.syncAsSint16LE(_field1FC0);
- s.syncAsSint16LE(_field1FC2);
- s.syncAsSint16LE(_field1FC4);
+ s.syncAsSint16LE(_driverOutOfTruckFl);
+ s.syncAsSint16LE(_harrisonMovedFl);
}
void Scene410::postInit(SceneObjectList *OwnerList) {
@@ -593,7 +597,7 @@ void Scene410::postInit(SceneObjectList *OwnerList) {
_patrolCar.fixPriority(148);
_patrolCar.setPosition(Common::Point(39, 168));
- _field1FC4 = 1;
+ _harrisonMovedFl = true;
_sceneMode = 0;
signal();
break;
@@ -603,10 +607,10 @@ void Scene410::postInit(SceneObjectList *OwnerList) {
_driver.remove();
_sceneMode = 0;
} else {
- _field1FC4 = BF_GLOBALS._v50CC8;
- _field1FBA = BF_GLOBALS._v50CC2;
- _talkCount = BF_GLOBALS._v50CC6;
- _field1FB6 = BF_GLOBALS._v50CC4;
+ _harrisonMovedFl = BF_GLOBALS._scene410HarrisonMovedFl;
+ _harrissonTalkFl = BF_GLOBALS._scene410HarrisonTalkFl;
+ _talkCount = BF_GLOBALS._scene410TalkCount;
+ _action1Count = BF_GLOBALS._scene410Action1Count;
_passenger.setVisage(418);
_passenger.setStrip(6);
@@ -617,7 +621,7 @@ void Scene410::postInit(SceneObjectList *OwnerList) {
_passenger.setStrip(2);
_passenger.setFrame(5);
}
- if (_field1FBA) {
+ if (_harrissonTalkFl) {
_passenger.setVisage(415);
_passenger.setStrip(6);
_passenger.setFrame(8);
@@ -651,7 +655,7 @@ void Scene410::postInit(SceneObjectList *OwnerList) {
_patrolCar.setDetails(410, 8, 9, 10, 1, (SceneItem *)NULL);
_patrolCar.fixPriority(148);
- if (_field1FC4) {
+ if (_harrisonMovedFl) {
_harrison.setPosition(Common::Point(108, 112));
_patrolCar.fixPriority(148);
_patrolCar.setPosition(Common::Point(39, 168));
@@ -664,7 +668,7 @@ void Scene410::postInit(SceneObjectList *OwnerList) {
_sceneMode = 0;
}
- _field1FC4 = 1;
+ _harrisonMovedFl = true;
}
break;
case 50:
@@ -686,10 +690,10 @@ void Scene410::signal() {
BF_GLOBALS.set2Flags(f1097Frankie);
BF_GLOBALS.clearFlag(f1097Marina);
- BF_GLOBALS._v50CC8 = _field1FC4;
- BF_GLOBALS._v50CC2 = _field1FBA;
- BF_GLOBALS._v50CC6 = _talkCount;
- BF_GLOBALS._v50CC4 = _field1FB6;
+ BF_GLOBALS._scene410HarrisonMovedFl = _harrisonMovedFl;
+ BF_GLOBALS._scene410HarrisonTalkFl = _harrissonTalkFl;
+ BF_GLOBALS._scene410TalkCount = _talkCount;
+ BF_GLOBALS._scene410Action1Count = _action1Count;
BF_GLOBALS._sceneManager.changeScene(60);
break;
case 2:
@@ -730,7 +734,7 @@ void Scene410::signal() {
case 9:
_sceneMode = 4106;
_stripManager.start(4111, this);
- _field1FBA = 1;
+ _harrissonTalkFl = true;
BF_GLOBALS.setFlag(fCuffedFrankie);
T2_GLOBALS._uiElements.addScore(30);
break;
@@ -760,7 +764,7 @@ void Scene410::signal() {
break;
case 4104:
// After call for backup, patrol car is coming
- _field1FC4 = 1;
+ _harrisonMovedFl = true;
BF_GLOBALS._player.disableControl();
_sceneMode = 0;
setAction(&_sequenceManager1, this, 4104, &_patrolCar, &_harrison, NULL);
@@ -1432,21 +1436,21 @@ bool Scene450::Manager::startAction(CursorType action, Event &event) {
} else {
animate(ANIM_MODE_8, 1, NULL);
- if (scene->_field19AC) {
+ if (scene->_managerCallsWeaselFl) {
scene->_sceneMode = 2;
- if (scene->_field19AE) {
+ if (scene->_talkManagerFl) {
scene->_stripManager.start(4521, scene);
} else {
- scene->_field19AE = 1;
+ scene->_talkManagerFl = true;
scene->_stripManager.start(4512, scene);
}
} else {
scene->_sceneMode = 4506;
- if (scene->_field19AE) {
+ if (scene->_talkManagerFl) {
scene->setAction(&scene->_sequenceManager, scene, 4518, &BF_GLOBALS._player, this, NULL);
} else {
scene->_sceneMode = 4506;
- scene->_field19AE = 1;
+ scene->_talkManagerFl = true;
scene->setAction(&scene->_sequenceManager, scene, 4506, &BF_GLOBALS._player, this, NULL);
}
}
@@ -1524,13 +1528,13 @@ bool Scene450::Exit::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
Scene450::Scene450(): SceneExt() {
- _field19AC = _field19AE = 0;
+ _managerCallsWeaselFl = _talkManagerFl = false;
}
void Scene450::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field19AC);
- s.syncAsSint16LE(_field19AE);
+ s.syncAsSint16LE(_managerCallsWeaselFl);
+ s.syncAsSint16LE(_talkManagerFl);
}
void Scene450::postInit(SceneObjectList *OwnerList) {
@@ -1654,7 +1658,7 @@ void Scene450::signal() {
case 4510:
case 4511:
BF_GLOBALS.setFlag(fMgrCallsWeasel);
- _field19AC = 1;
+ _managerCallsWeaselFl = true;
_sceneMode = 4503;
setAction(&_sequenceManager, this, 4503, &_weasel, &_door, &_manager, NULL);
break;
diff --git a/engines/tsage/blue_force/blueforce_scenes4.h b/engines/tsage/blue_force/blueforce_scenes4.h
index 937c015a4c..92e91c93b2 100644
--- a/engines/tsage/blue_force/blueforce_scenes4.h
+++ b/engines/tsage/blue_force/blueforce_scenes4.h
@@ -116,9 +116,12 @@ public:
SpeakerDriver _driverSpeaker;
SpeakerShooter _shooterSpeaker;
ASoundExt _sound1;
- int _field1FB6, _talkCount, _field1FBA;
- int _field1FBC, _field1FBE;
- int _field1FC0, _field1FC2, _field1FC4;
+ int _action1Count, _talkCount;
+ bool _harrissonTalkFl;
+ bool _cuffedDriverFl;
+ bool _cuffedPassengerFl;
+ bool _field1FC0;
+ bool _driverOutOfTruckFl, _harrisonMovedFl;
Scene410();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -254,7 +257,8 @@ public:
NamedObject _door, _counterDoor;
Exit _exit;
NamedHotspot _interior, _shelf, _counter;
- int _field19AC, _field19AE;
+ bool _managerCallsWeaselFl;
+ bool _talkManagerFl;
Scene450();
virtual void synchronize(Serializer &s);
diff --git a/engines/tsage/blue_force/blueforce_scenes5.cpp b/engines/tsage/blue_force/blueforce_scenes5.cpp
index abadc4300a..101a39c4b7 100644
--- a/engines/tsage/blue_force/blueforce_scenes5.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes5.cpp
@@ -1220,7 +1220,7 @@ void Scene560::SafeInset::process(Event &event) {
}
if ((event.eventType == EVENT_BUTTON_DOWN) && (BF_GLOBALS._events.getCursor() == CURSOR_WALK) &&
- (event.btnState == 3)) {
+ (event.btnState == BTNSHIFT_RIGHT)) {
BF_GLOBALS._events.setCursor(CURSOR_USE);
event.handled = true;
}
@@ -1459,7 +1459,7 @@ void Scene560::postInit(SceneObjectList *OwnerList) {
_lamp.setDetails(Rect(197, 43, 214, 56), 560, 7, 19, 30, 1, NULL);
_item4.setDetails(Rect(121, 18, 156, 54), 560, 8, 20, 31, 1, NULL);
_trophy.setDetails(Rect(259, 52, 275, 63), 560, 10, 22, 33, 1, NULL);
- _watercolours.setDetails(Rect(214, 48, 239, 64), 560, 12, 24, 35, 1, NULL);
+ _waterColors.setDetails(Rect(214, 48, 239, 64), 560, 12, 24, 35, 1, NULL);
_fileCabinets.setDetails(Rect(0, 47, 49, 100), 560, 14, 26, 37, 1, NULL);
_certificate.setDetails(Rect(280, 51, 292, 62), 560, 11, 23, 34, 1, NULL);
_bookcase.setDetails(Rect(176, 0, 319, 103), 560, 9, 21, 32, 1, NULL);
@@ -1772,12 +1772,12 @@ void Scene570::IconManager::refreshList() {
}
void Scene570::IconManager::addItem(Icon *item) {
- item->_mode = _mode;
_list.push_back(item);
}
Scene570::Icon::Icon(): NamedObject() {
_iconId = _folderId = 0;
+ _parentFolderId = 0;
}
void Scene570::Icon::synchronize(Serializer &s) {
@@ -1785,7 +1785,10 @@ void Scene570::Icon::synchronize(Serializer &s) {
s.syncAsSint16LE(_iconId);
s.syncAsSint16LE(_folderId);
s.syncAsSint16LE(_parentFolderId);
- s.syncAsSint16LE(_mode);
+ if (s.getVersion() < 11) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ }
}
void Scene570::Icon::remove() {
@@ -1906,7 +1909,7 @@ bool Scene570::Icon::startAction(CursorType action, Event &event) {
}
}
-void Scene570::Icon::setDetails(int iconId, int folderId, int parentFolderId, int unused, const Common::String &msg) {
+void Scene570::Icon::setDetails(int iconId, int folderId, int parentFolderId, const Common::String &msg) {
Scene570 *scene = (Scene570 *)BF_GLOBALS._sceneManager._scene;
NamedObject::postInit();
@@ -2073,23 +2076,23 @@ void Scene570::signal() {
_printerIcon.setDetails(570, 14, 15, -1, 2, (SceneItem *)NULL);
_iconManager.setup(2);
- _folder1.setDetails(1, 1, 0, 2, SCENE570_C_DRIVE);
- _folder2.setDetails(1, 2, 1, 2, SCENE570_RING);
- _folder3.setDetails(1, 3, 1, 2, SCENE570_PROTO);
- _folder4.setDetails(1, 4, 1, 2, SCENE570_WACKY);
+ _folder1.setDetails(1, 1, 0, SCENE570_C_DRIVE);
+ _folder2.setDetails(1, 2, 1, SCENE570_RING);
+ _folder3.setDetails(1, 3, 1, SCENE570_PROTO);
+ _folder4.setDetails(1, 4, 1, SCENE570_WACKY);
if (!BF_GLOBALS.getFlag(fDecryptedBluePrints))
- _icon1.setDetails(3, 5, 0, 2, SCENE570_COBB);
- _icon2.setDetails(2, 7, 0, 2, SCENE570_LETTER);
+ _icon1.setDetails(3, 5, 0, SCENE570_COBB);
+ _icon2.setDetails(2, 7, 0, SCENE570_LETTER);
if (BF_GLOBALS.getFlag(fDecryptedBluePrints))
- _icon3.setDetails(7, 6, 0, 2, SCENE570_COBB);
+ _icon3.setDetails(7, 6, 0, SCENE570_COBB);
- _icon4.setDetails(6, 8, 1, 2, SCENE570_RINGEXE);
- _icon5.setDetails(5, 9, 1, 2, SCENE570_RINGDATA);
- _icon6.setDetails(6, 10, 2, 2, SCENE570_PROTOEXE);
- _icon7.setDetails(5, 11, 2, 2, SCENE570_PROTODATA);
- _icon8.setDetails(6, 12, 3, 2, SCENE570_WACKYEXE);
- _icon9.setDetails(5, 13, 3, 2, SCENE570_WACKYDATA);
+ _icon4.setDetails(6, 8, 1, SCENE570_RINGEXE);
+ _icon5.setDetails(5, 9, 1, SCENE570_RINGDATA);
+ _icon6.setDetails(6, 10, 2, SCENE570_PROTOEXE);
+ _icon7.setDetails(5, 11, 2, SCENE570_PROTODATA);
+ _icon8.setDetails(6, 12, 3, SCENE570_WACKYEXE);
+ _icon9.setDetails(5, 13, 3, SCENE570_WACKYDATA);
_iconManager.refreshList();
BF_GLOBALS._player.enableControl();
@@ -2104,7 +2107,7 @@ void Scene570::signal() {
_object3.setFrame(1);
_object3.fixPriority(1);
- _icon3.setDetails(7, 6, 0, 2, SCENE570_COBB);
+ _icon3.setDetails(7, 6, 0, SCENE570_COBB);
_iconManager.refreshList();
T2_GLOBALS._uiElements._active = true;
T2_GLOBALS._uiElements.show();
diff --git a/engines/tsage/blue_force/blueforce_scenes5.h b/engines/tsage/blue_force/blueforce_scenes5.h
index 73d323fc54..71c7f3d8f1 100644
--- a/engines/tsage/blue_force/blueforce_scenes5.h
+++ b/engines/tsage/blue_force/blueforce_scenes5.h
@@ -225,7 +225,7 @@ public:
NamedObject _object6;
PicturePart _picture1, _picture2, _picture3, _picture4;
Computer _computer;
- NamedHotspot _chair, _lamp, _item4, _trophy, _watercolours, _fileCabinets;
+ NamedHotspot _chair, _lamp, _item4, _trophy, _waterColors, _fileCabinets;
NamedHotspot _certificate, _bookcase, _desk, _carpet, _item12, _office;
ASound _sound1;
bool _field380;
@@ -257,7 +257,7 @@ class Scene570: public SceneExt {
class Icon: public NamedObject {
public:
SceneText _sceneText;
- int _iconId, _folderId, _parentFolderId, _mode;
+ int _iconId, _folderId, _parentFolderId;
Common::String _text;
Icon();
@@ -266,7 +266,7 @@ class Scene570: public SceneExt {
virtual void remove();
virtual bool startAction(CursorType action, Event &event);
- void setDetails(int iconId, int folderId, int parentFolderId, int unused, const Common::String &msg);
+ void setDetails(int iconId, int folderId, int parentFolderId, const Common::String &msg);
};
class IconManager: public EventHandler {
public:
diff --git a/engines/tsage/blue_force/blueforce_scenes6.cpp b/engines/tsage/blue_force/blueforce_scenes6.cpp
index 9467df7917..b20092492f 100644
--- a/engines/tsage/blue_force/blueforce_scenes6.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes6.cpp
@@ -79,7 +79,6 @@ void Scene600::Action1::signal() {
}
BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
- BF_GLOBALS._v51C44 = 1;
scene->loadScene(999);
setDelay(5);
break;
@@ -88,7 +87,6 @@ void Scene600::Action1::signal() {
setDelay(5);
break;
case 7:
- BF_GLOBALS._v51C44 = 0;
remove();
break;
default:
@@ -275,7 +273,7 @@ bool Scene666::Item1::startAction(CursorType action, Event &event) {
void Scene666::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._sound1.play(27);
SceneExt::postInit();
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
loadScene(999);
BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
diff --git a/engines/tsage/blue_force/blueforce_scenes7.cpp b/engines/tsage/blue_force/blueforce_scenes7.cpp
index 4cdd2f3f15..2f52c4df95 100644
--- a/engines/tsage/blue_force/blueforce_scenes7.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes7.cpp
@@ -148,7 +148,7 @@ void Scene710::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._sound1.fadeSound(14);
_soundExt1.fadeSound(48);
- _v51C34.set(40, 0, 280, 240);
+
BF_GLOBALS._player.postInit();
BF_GLOBALS._player.hide();
BF_GLOBALS._player._moveDiff = Common::Point(4, 2);
diff --git a/engines/tsage/blue_force/blueforce_scenes8.cpp b/engines/tsage/blue_force/blueforce_scenes8.cpp
index 5a60cd7c5e..f78a332be9 100644
--- a/engines/tsage/blue_force/blueforce_scenes8.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes8.cpp
@@ -577,17 +577,15 @@ bool Scene810::Lyle::startAction(CursorType action, Event &event) {
if ((BF_GLOBALS.getFlag(shownLyleRapsheet)) || (BF_GLOBALS.getFlag(shownLyleCrate1))){
scene->_sceneMode = 8141;
} else {
- // Doublecheck on shownLyleCrate1 removed: useless
scene->_sceneMode = 8144;
}
} else {
if ((BF_GLOBALS.getFlag(shownLyleRapsheet)) || (BF_GLOBALS.getFlag(shownLyleCrate1))) {
scene->_sceneMode = 8129;
- } else { // if (BF_GLOBALS.getFlag(shownLyleCrate1)) {
+ } else {
scene->_sceneMode = 8132;
- // doublecheck Present in the original, may hide a bug in the original
- //} else
- // scene->_sceneMode = 8121;
+ // Double check on ShownLyleCrate1 present in the original, may hide a bug in the original
+ // The original was then setting _sceneMode 8121
}
}
}
@@ -1071,7 +1069,6 @@ void Scene810::postInit(SceneObjectList *OwnerList) {
setAction(&_sequenceManager1, this, 8107, &BF_GLOBALS._player, &_lyle, NULL);
break;
case 935:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._scenePalette.loadPalette(2);
_lyle.remove();
@@ -1804,13 +1801,11 @@ void Scene830::signal() {
_sceneMode = 832;
BF_GLOBALS._scenePalette.clearListeners();
addFader((const byte *)&black, 5, this);
- BF_GLOBALS._v51C44 = 0;
break;
case 12:
_sceneMode = 831;
BF_GLOBALS._scenePalette.clearListeners();
addFader((const byte *)&black, 5, this);
- BF_GLOBALS._v51C44 = 0;
break;
case 13:
BF_GLOBALS._sceneManager.changeScene(850);
@@ -1963,7 +1958,7 @@ void Scene840::BoatKeysInset::postInit(SceneObjectList *OwnerList) {
_waveKeys.setDetails(840, 53, 8, -1, 2, (SceneItem *)NULL);
}
- _v1B4 = _v1B6 = 0;
+ _usedRentalKeys = _usedWaveKeys = false;
}
void Scene840::BoatKeysInset::remove() {
@@ -1984,7 +1979,7 @@ void Scene840::BoatKeysInset::process(Event &event) {
CursorType cursorId = BF_GLOBALS._events.getCursor();
BF_GLOBALS._events.setCursor(cursorId);
- if ((event.eventType == EVENT_BUTTON_DOWN) && (cursorId == CURSOR_WALK) && (event.btnState == 3)) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (cursorId == CURSOR_WALK) && (event.btnState == BTNSHIFT_RIGHT)) {
BF_GLOBALS._events.setCursor(CURSOR_USE);
event.handled = true;
}
@@ -2072,7 +2067,7 @@ bool Scene840::BoatKeysInset::RentalKeys::startAction(CursorType action, Event &
BF_INVENTORY.setObjectScene(INV_RENTAL_KEYS, 1);
T2_GLOBALS._uiElements.addScore(30);
- scene->_boatKeysInset._v1B4 = 1;
+ scene->_boatKeysInset._usedRentalKeys = true;
remove();
}
return true;
@@ -2090,7 +2085,7 @@ bool Scene840::BoatKeysInset::WaveKeys::startAction(CursorType action, Event &ev
SceneItem::display2(840, 56);
BF_INVENTORY.setObjectScene(INV_WAVE_KEYS, 1);
T2_GLOBALS._uiElements.addScore(50);
- scene->_boatKeysInset._v1B6 = 1;
+ scene->_boatKeysInset._usedWaveKeys = true;
remove();
} else {
SceneItem::display2(840, 9);
@@ -2101,6 +2096,15 @@ bool Scene840::BoatKeysInset::WaveKeys::startAction(CursorType action, Event &ev
}
}
+void Scene840::BoatKeysInset::synchronize(Serializer &s) {
+ FocusObject::synchronize(s);
+
+ if (s.getVersion() >= 12) {
+ s.syncAsSint16LE(_usedWaveKeys);
+ s.syncAsSint16LE(_usedRentalKeys);
+ }
+}
+
bool Scene840::BoatKeys::startAction(CursorType action, Event &event) {
Scene840 *scene = (Scene840 *)BF_GLOBALS._sceneManager._scene;
@@ -2472,10 +2476,10 @@ void Scene840::signal() {
_boatKeysInset.setDetails(840, 50, 8, 51);
break;
case 8412:
- if (_boatKeysInset._v1B6) {
+ if (_boatKeysInset._usedWaveKeys) {
_sceneMode = 8409;
setAction(&_sequenceManager1, this, 8409, &BF_GLOBALS._player, &_carter, &_doors, NULL);
- } else if (!_boatKeysInset._v1B4) {
+ } else if (!_boatKeysInset._usedRentalKeys) {
BF_GLOBALS._player.enableControl();
} else {
_sceneMode = 3;
diff --git a/engines/tsage/blue_force/blueforce_scenes8.h b/engines/tsage/blue_force/blueforce_scenes8.h
index ef5ef81563..b9e6ebd640 100644
--- a/engines/tsage/blue_force/blueforce_scenes8.h
+++ b/engines/tsage/blue_force/blueforce_scenes8.h
@@ -348,8 +348,9 @@ class Scene840: public PalettedScene {
public:
RentalKeys _rentalKeys;
WaveKeys _waveKeys;
- int _v1B4, _v1B6;
+ bool _usedRentalKeys,_usedWaveKeys;
+ virtual void synchronize(Serializer &s);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void process(Event &event);
diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp
index 1cb8191640..2b42dc8625 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes9.cpp
@@ -705,6 +705,10 @@ void Scene900::process(Event &event) {
void Scene900::dispatch() {
SceneExt::dispatch();
+ // WORKAROUND:: Fix for invalid data in the Blue Force floppy version when opening gate
+ if (_sceneMode == 9006 && (g_vm->getFeatures() & GF_FLOPPY) && BF_GLOBALS._player._endFrame == 8)
+ BF_GLOBALS._player._endFrame = 6;
+
if (BF_GLOBALS.getFlag(fWithLyle) && _lyle.isNoMover()) {
_lyle.updateAngle(BF_GLOBALS._player._position);
}
@@ -836,14 +840,14 @@ bool Scene910::Nico::startAction(CursorType action, Event &event) {
if (BF_GLOBALS._nico910State >= 4)
return NamedObject::startAction(action, event);
- if (BF_GLOBALS._v4CEE6 < 4)
- BF_GLOBALS._v4CEE6++;
+ if (BF_GLOBALS._nico910Talk < 4)
+ BF_GLOBALS._nico910Talk++;
- if (BF_GLOBALS._v4CEE6 == 2) {
+ if (BF_GLOBALS._nico910Talk == 2) {
scene->_sceneMode = 13;
scene->_stripManager.start(9105, scene);
} else
- scene->_stripManager.start(9103 + BF_GLOBALS._v4CEE6, &BF_GLOBALS._stripProxy);
+ scene->_stripManager.start(9103 + BF_GLOBALS._nico910Talk, &BF_GLOBALS._stripProxy);
return true;
break;
case INV_COLT45:
@@ -883,14 +887,14 @@ bool Scene910::Nico::startAction(CursorType action, Event &event) {
if (BF_GLOBALS._nico910State >= 4)
return NamedObject::startAction(action, event);
- if (BF_GLOBALS._v4CEE6 < 4)
- BF_GLOBALS._v4CEE6++;
+ if (BF_GLOBALS._nico910Talk < 4)
+ BF_GLOBALS._nico910Talk++;
- if (BF_GLOBALS._v4CEE6 == 2) {
+ if (BF_GLOBALS._nico910Talk == 2) {
scene->_sceneMode = 13;
scene->_stripManager.start(9105, scene);
} else
- scene->_stripManager.start(9103 + BF_GLOBALS._v4CEE6, &BF_GLOBALS._stripProxy);
+ scene->_stripManager.start(9103 + BF_GLOBALS._nico910Talk, &BF_GLOBALS._stripProxy);
return true;
break;
@@ -962,16 +966,16 @@ bool Scene910::Stuart::startAction(CursorType action, Event &event) {
return true;
break;
case CURSOR_TALK:
- if (BF_GLOBALS._v4CEE8 < 3)
- BF_GLOBALS._v4CEE8++;
+ if (BF_GLOBALS._stuart910Talk < 3)
+ BF_GLOBALS._stuart910Talk++;
- scene->_stripManager.start(9107 + BF_GLOBALS._v4CEE8, &BF_GLOBALS._stripProxy);
+ scene->_stripManager.start(9107 + BF_GLOBALS._stuart910Talk, &BF_GLOBALS._stripProxy);
return true;
break;
case INV_COLT45:
if ((BF_GLOBALS.getFlag(gunDrawn)) && (BF_GLOBALS.getFlag(fGunLoaded)) && (BF_GLOBALS.getHasBullets())){
BF_GLOBALS._player.disableControl();
- if (BF_GLOBALS._v4CEE4 == 2) {
+ if (BF_GLOBALS._stuart910State == 2) {
scene->_sceneMode = 9132;
scene->setAction(&scene->_sequenceManager1, scene, 9132, &scene->_stuart, NULL);
return NamedObject::startAction(action, event);
@@ -1418,6 +1422,10 @@ void Scene910::Object13::setupBreaker(int x, int y, int mode, int8 frameNumber)
BF_GLOBALS._sceneItems.push_front(this);
}
+Scene910::Object25::Object25() {
+ _field90 = _field92 = 0;
+}
+
void Scene910::Object25::synchronize(Serializer &s) {
NamedObject::synchronize(s);
s.syncAsSint16LE(_field90);
@@ -1870,7 +1878,7 @@ bool Scene910::Item2::startAction(CursorType action, Event &event) {
bool Scene910::Item3::startAction(CursorType action, Event &event) {
Scene910 *scene = (Scene910 *)BF_GLOBALS._sceneManager._scene;
- if ((action == CURSOR_TALK) && (BF_GLOBALS._nico910State == 4) && (BF_GLOBALS._v4CEE4 == 0)) {
+ if ((action == CURSOR_TALK) && (BF_GLOBALS._nico910State == 4) && (BF_GLOBALS._stuart910State == 0)) {
BF_GLOBALS._player.disableControl();
scene->_sceneMode = 15;
scene->_stripManager.start(9102, scene);
@@ -1958,7 +1966,6 @@ void Scene910::postInit(SceneObjectList *OwnerList) {
loadScene(910);
BF_GLOBALS._sound1.changeSound(99);
- BF_GLOBALS._v51C44 = 0;
_stripManager.addSpeaker(&_gameTextSpeaker);
_stripManager.addSpeaker(&_jakeJacketSpeaker);
@@ -2050,7 +2057,7 @@ void Scene910::postInit(SceneObjectList *OwnerList) {
|| (BF_GLOBALS._sceneManager._previousScene == 300)) {
BF_GLOBALS._sceneManager._previousScene = 900;
BF_GLOBALS._nico910State = 0;
- BF_GLOBALS._v4CEE4 = 0;
+ BF_GLOBALS._stuart910State = 0;
}
_field2DE0 = 0;
@@ -2142,7 +2149,7 @@ void Scene910::postInit(SceneObjectList *OwnerList) {
_nico.setVisage(913);
_nico.setPosition(Common::Point(262, 124));
_nico.setStrip(6);
- BF_GLOBALS._v4CEE6 = 0;
+ BF_GLOBALS._nico910Talk = 0;
BF_GLOBALS._nico910State = 1;
_nico.setDetails(910, 63, 64, 67, 5, &_item4);
BF_GLOBALS._v4CECA = 2;
@@ -2269,7 +2276,6 @@ void Scene910::signal() {
break;
case 10:
BF_GLOBALS._player.disableControl();
- BF_GLOBALS._v51C44 = 0;
BF_GLOBALS._sceneManager.changeScene(935);
break;
case 11:
@@ -2303,12 +2309,11 @@ void Scene910::signal() {
case 15:
_stuart.postInit();
_stuart.setDetails(910, 66, 67, 68, 5, &_nico);
- BF_GLOBALS._v4CEE8 = 0;
+ BF_GLOBALS._stuart910Talk = 0;
_sceneMode = 9121;
setAction(&_sequenceManager1, this, 9121, &_stuart, NULL);
break;
case 14:
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(940);
break;
case 16:
@@ -2344,7 +2349,7 @@ void Scene910::signal() {
case 18:
BF_GLOBALS._player._strip = 7;
BF_GLOBALS._player._frame = 1;
- if (BF_GLOBALS._v4CEE4 == 3) {
+ if (BF_GLOBALS._stuart910State == 3) {
if (_field2DE4 == 0) {
_field2DE4 = 1;
_sceneMode = 9142;
@@ -2368,7 +2373,6 @@ void Scene910::signal() {
break;
case 19:
BF_GLOBALS._deathReason = 14;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 20:
@@ -2384,7 +2388,6 @@ void Scene910::signal() {
BF_GLOBALS.clearFlag(fGotPointsForSearchingDA);
else
BF_GLOBALS.setFlag(fGotPointsForSearchingDA);
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(900);
break;
case 9102:
@@ -2457,7 +2460,7 @@ void Scene910::signal() {
BF_GLOBALS._player.disableControl();
_nico.postInit();
_nico.setDetails(910, 63, 64, 65, 5, &_item4);
- BF_GLOBALS._v4CEE6 = 0;
+ BF_GLOBALS._nico910Talk = 0;
_shadow.postInit();
_action2.remove();
_sceneMode = 9116;
@@ -2478,7 +2481,6 @@ void Scene910::signal() {
// No break on purpose
case 9137:
BF_GLOBALS._deathReason = 16;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 9119:
@@ -2496,7 +2498,7 @@ void Scene910::signal() {
break;
case 9121:
_item3.setDetails(7, 910, 96, 60, 61, 3);
- BF_GLOBALS._v4CEE4 = 2;
+ BF_GLOBALS._stuart910State = 2;
if (BF_GLOBALS._nico910State == 4) {
_sceneMode = 20;
_stripManager.start(9115, this);
@@ -2580,7 +2582,7 @@ void Scene910::signal() {
_yellowCord.hide();
_sceneMode = 9136;
setAction(&_sequenceManager1, this, 9136, &BF_GLOBALS._player, &_stuart, &_yellowCord, NULL);
- BF_GLOBALS._v4CEE4 = 3;
+ BF_GLOBALS._stuart910State = 3;
break;
case 11:
_sceneMode = 9137;
@@ -2603,13 +2605,13 @@ void Scene910::signal() {
_stuart.postInit();
_nico.setDetails(910, 72, 73, 74, 3, (SceneItem *)NULL);
_stuart.setDetails(910, 66, 67, 68, 5, &_nico);
- BF_GLOBALS._v4CEE8 = 0;
+ BF_GLOBALS._stuart910Talk = 0;
_sceneMode = 9121;
setAction(&_sequenceManager1, this, 9121, &_stuart, NULL);
break;
case 9126:
_sceneMode = 19;
- if (BF_GLOBALS._v4CEE4 == 0)
+ if (BF_GLOBALS._stuart910State == 0)
signal();
else
_stripManager.start(9115, this);
@@ -2618,7 +2620,6 @@ void Scene910::signal() {
// No break on purpose
case 9134:
BF_GLOBALS._deathReason = 17;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 9130:
@@ -2629,14 +2630,12 @@ void Scene910::signal() {
break;
case 9132:
BF_GLOBALS._player.enableControl();
- BF_GLOBALS._v4CEE4 = 4;
+ BF_GLOBALS._stuart910State = 4;
BF_GLOBALS._deathReason = 13;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 9135:
BF_GLOBALS._deathReason = 15;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 9136:
@@ -2681,7 +2680,6 @@ void Scene910::signal() {
break;
case 9143:
if (BF_GLOBALS._nico910State == 0) {
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(920);
} else {
SceneItem::display(910, 89, SET_WIDTH, 312,
@@ -2700,7 +2698,6 @@ void Scene910::signal() {
break;
case 9148:
BF_GLOBALS._deathReason = 23;
- BF_GLOBALS._v51C44 = 1;
BF_GLOBALS._sceneManager.changeScene(666);
break;
case 9149:
@@ -3573,7 +3570,7 @@ void Scene935::postInit(SceneObjectList *OwnerList) {
PalettedScene::postInit();
loadScene(935);
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
BF_GLOBALS._player.disableControl();
_visualSpeaker._textMode = ALIGN_CENTER;
_visualSpeaker._hideObjects = false;
@@ -3808,7 +3805,7 @@ void Scene940::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._sound1.play(115);
BF_GLOBALS._dayNumber = 6;
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
T2_GLOBALS._uiElements._active = false;
_gameTextSpeaker2._speakerName = "SENTTEXT";
diff --git a/engines/tsage/blue_force/blueforce_scenes9.h b/engines/tsage/blue_force/blueforce_scenes9.h
index 74708b94de..8bf7f343a1 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.h
+++ b/engines/tsage/blue_force/blueforce_scenes9.h
@@ -188,6 +188,7 @@ class Scene910: public PalettedScene {
class Object25: public NamedObject {
int _field90, _field92;
public:
+ Object25();
void setupHiddenSwitch(int x, int y, int arg8, int argA);
virtual void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
diff --git a/engines/tsage/blue_force/blueforce_speakers.cpp b/engines/tsage/blue_force/blueforce_speakers.cpp
index 2a57616640..b15d2f4716 100644
--- a/engines/tsage/blue_force/blueforce_speakers.cpp
+++ b/engines/tsage/blue_force/blueforce_speakers.cpp
@@ -63,8 +63,8 @@ void VisualSpeaker::synchronize(Serializer &s) {
s.syncAsSint16LE(_offsetPos.y);
}
-void VisualSpeaker::proc12(Action *action) {
- Speaker::proc12(action);
+void VisualSpeaker::startSpeaking(Action *action) {
+ Speaker::startSpeaking(action);
_textPos = Common::Point(_offsetPos.x + BF_GLOBALS._sceneManager._scene->_sceneBounds.left,
_offsetPos.y + BF_GLOBALS._sceneManager._scene->_sceneBounds.top);
_numFrames = 0;
diff --git a/engines/tsage/blue_force/blueforce_speakers.h b/engines/tsage/blue_force/blueforce_speakers.h
index e406a50fbe..e9150df056 100644
--- a/engines/tsage/blue_force/blueforce_speakers.h
+++ b/engines/tsage/blue_force/blueforce_speakers.h
@@ -51,7 +51,7 @@ public:
virtual Common::String getClassName() { return "VisualSpeaker"; }
virtual void synchronize(Serializer &s);
virtual void remove();
- virtual void proc12(Action *action);
+ virtual void startSpeaking(Action *action);
virtual void setText(const Common::String &msg);
};
diff --git a/engines/tsage/configure.engine b/engines/tsage/configure.engine
new file mode 100644
index 0000000000..2b8edf8266
--- /dev/null
+++ b/engines/tsage/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine tsage "TsAGE" yes
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
index de5ac62425..f7c1dd24e6 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,12 +444,20 @@ 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();
g_globals->_events.showCursor();
+ // WORKAROUND: On-screen dialogs are really meant to use a GfxManager instance
+ // for their lifetime, which prevents saving or loading. Since I don't want to spend a lot
+ // of time refactoring this already working dialog, fake it by putting a dummy gfxmanager at
+ // the end of the gfx manager list so as to prevent saving or loading
+ GfxManager gfxManager;
+ GLOBALS._gfxManagers.push_back(&gfxManager);
+
// Event handling loop
Event event;
while (!g_vm->shouldQuit()) {
@@ -501,6 +509,7 @@ int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
// Remove the dialog
remove();
+ GLOBALS._gfxManagers.remove(&gfxManager);
return _selectedIndex;
}
@@ -513,6 +522,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 +534,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 +543,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 +564,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 +573,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 +600,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 +656,7 @@ void StripManager::reset() {
_activeSpeaker = NULL;
_textShown = false;
_callbackObject = NULL;
+ _exitMode = 0;
_obj44List.clear();
if (!_script.empty()) {
@@ -679,6 +704,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();
@@ -688,7 +715,7 @@ void StripManager::synchronize(Serializer &s) {
for (int i = 0; i < arrSize; ++i)
_obj44List[i].synchronize(s);
- // Synhcronise script data
+ // Synchronize script data
int scriptSize = _script.size();
s.syncAsUint16LE(scriptSize);
if (s.isLoading())
@@ -708,14 +735,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]->stopSpeaking();
+ }
+ }
+
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;
@@ -725,10 +762,24 @@ void StripManager::remove() {
if (_onEnd)
_onEnd();
+ if (g_vm->getGameID() == GType_Ringworld2)
+ _endHandler = NULL;
+
Action::remove();
}
+void StripManager::dispatch() {
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ if (_activeSpeaker)
+ _activeSpeaker->dispatch();
+ }
+
+ Action::dispatch();
+}
+
void StripManager::signal() {
+ int strIndex = 0;
+
if (_textShown) {
_activeSpeaker->removeText();
_textShown = false;
@@ -760,12 +811,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:
@@ -782,39 +831,101 @@ void StripManager::signal() {
}
}
+ _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);
+ // If no entry found, get the default response
+ if (!delayFlag) {
+ idx = 0;
+ while (obj44._list[idx + 1]._id)
+ ++idx;
+
+ choiceList.push_back((const char *)&_script[0] + obj44._list[idx]._scriptOffset);
+ strIndex = idx;
+ delayFlag = true;
}
} 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]) {
+ // WORKAROUND: The _lookupList isn't always correctly initialized. But it always
+ // seems to be set to the R2_GLOBALS._stripManager_lookupList, so manually set it
+ if (!_lookupList)
+ _lookupList = R2_GLOBALS._stripManager_lookupList;
+
+ 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 = idx; listIdx < (OBJ0A_LIST_SIZE - 1); ++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;
+ }
+
+ --idx;
+ continue;
+ }
+ }
+ }
+ }
+
+ // 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);
@@ -831,7 +942,7 @@ void StripManager::signal() {
g_globals->_sceneManager._scene->loadScene(_sceneNumber);
}
- _activeSpeaker->proc12(this);
+ _activeSpeaker->startSpeaking(this);
}
if (_callbackObject) {
@@ -843,11 +954,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);
- _textShown = true;
- _activeSpeaker->setText(choiceList[strIndex]);
+ if (speaker) {
+ speaker->_speakerMode = obj44._speakerMode;
+ if (!choiceList[strIndex].empty())
+ speaker->animateSpeaker();
+ }
+
+ if (!choiceList[strIndex].empty()) {
+ _textShown = true;
+ _activeSpeaker->setText(choiceList[strIndex]);
+ } else if (!obj44._speakerMode) {
+ _delayFrames = 1;
+ } else {
+ _delayFrames = 0;
+ speaker->animateSpeaker();
+ }
+ } else {
+ _textShown = true;
+ _activeSpeaker->setText(choiceList[strIndex]);
+ }
}
_obj44Index = getNewIndex(obj44._list[strIndex]._id);
@@ -915,6 +1043,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) {
@@ -966,7 +1096,7 @@ void Speaker::remove() {
SceneObjectList::deactivate();
}
-void Speaker::proc12(Action *action) {
+void Speaker::startSpeaking(Action *action) {
_action = action;
if (_newSceneNumber != -1) {
_oldSceneNumber = g_globals->_sceneManager._sceneNumber;
diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h
index 0c4eb9539d..e7b8e811ca 100644
--- a/engines/tsage/converse.h
+++ b/engines/tsage/converse.h
@@ -91,9 +91,10 @@ public:
virtual Common::String getClassName() { return "Speaker"; }
virtual void synchronize(Serializer &s);
virtual void remove();
- virtual void proc12(Action *action);
+ virtual void startSpeaking(Action *action);
virtual void setText(const Common::String &msg);
virtual void removeText();
+ virtual void stopSpeaking() {}
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;
@@ -230,6 +237,7 @@ public:
virtual void synchronize(Serializer &s);
virtual void remove();
+ virtual void dispatch();
virtual void signal();
virtual void process(Event &event);
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index 4a90e23a33..596f056bfe 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -860,6 +860,8 @@ void PlayerMover::doStepsOfNpcMovement(const Common::Point &srcPos, const Common
int PlayerMover::calculateRestOfRoute(int *routeList, int srcRegion, int destRegion, bool &foundRoute) {
// Make a copy of the provided route. The first entry is the size.
int tempList[REGION_LIST_SIZE + 1];
+ memset(tempList, 0, sizeof(tempList));
+
foundRoute = false;
for (int idx = 0; idx <= *routeList; ++idx)
tempList[idx] = routeList[idx];
@@ -1151,6 +1153,13 @@ void PaletteRotation::signal() {
if (flag)
_currIndex = _start;
}
+
+ // Added in Return to Ringworld
+ if (_currIndex < _start) {
+ flag = decDuration();
+ if (flag)
+ _currIndex = _end;
+ }
break;
case 2:
_currIndex += _idxChange;
@@ -1179,7 +1188,7 @@ void PaletteRotation::signal() {
int count = _end - _currIndex;
g_system->getPaletteManager()->setPalette((const byte *)&_palette[_currIndex * 3], _start, count);
- if (count2) {
+ if (count2 > 0) {
g_system->getPaletteManager()->setPalette((const byte *)&_palette[_start * 3], _start + count, count2);
}
}
@@ -1516,6 +1525,10 @@ void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) {
g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface,
tempRect, Rect(0, 0, tempRect.width(), tempRect.height()), NULL);
+ if (g_vm->getGameID() == GType_Ringworld2 && !GLOBALS._player._uiEnabled
+ && T2_GLOBALS._interfaceY == UI_INTERFACE_Y) {
+ g_globals->_screenSurface.fillRect(Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT - 1), 0);
+ }
for (SynchronizedList<PaletteModifier *>::iterator i = tempPalette._listeners.begin(); i != tempPalette._listeners.end(); ++i)
delete *i;
@@ -1532,7 +1545,11 @@ void ScenePalette::synchronize(Serializer &s) {
s.syncAsSint32LE(_colors.foreground);
s.syncAsSint32LE(_colors.background);
- s.syncAsSint32LE(_field412);
+ if (s.getVersion() < 12) {
+ int useless = 0;
+ s.syncAsSint32LE(useless);
+ }
+
s.syncAsByte(_redColor);
s.syncAsByte(_greenColor);
s.syncAsByte(_blueColor);
@@ -1615,7 +1632,8 @@ void SceneItem::display(int resNum, int lineNum, ...) {
Common::String msg = (!resNum || (resNum == -1)) ? Common::String() :
g_resourceManager->getMessage(resNum, lineNum);
- if ((g_vm->getGameID() != GType_Ringworld) && T2_GLOBALS._uiElements._active)
+ if ((g_vm->getGameID() != GType_Ringworld) && (g_vm->getGameID() != GType_Ringworld2)
+ && T2_GLOBALS._uiElements._active)
T2_GLOBALS._uiElements.hide();
if (g_globals->_sceneObjects->contains(&g_globals->_sceneText)) {
@@ -1725,9 +1743,13 @@ void SceneItem::display(int resNum, int lineNum, ...) {
font.setFontNumber(g_globals->_sceneText._fontNumber);
font.getStringBounds(msg.c_str(), textRect, maxWidth);
+ Rect screenBounds = g_globals->gfxManager()._bounds;
+ if (g_vm->getGameID() == GType_Ringworld2)
+ screenBounds.collapse(20, 15);
+
// Center the text at the specified position, and then constrain it to be-
textRect.center(pos.x, pos.y);
- textRect.contain(g_globals->gfxManager()._bounds);
+ textRect.contain(screenBounds);
if (centerText) {
g_globals->_sceneText._color1 = g_globals->_sceneText._color2;
@@ -1745,9 +1767,22 @@ void SceneItem::display(int resNum, int lineNum, ...) {
}
g_globals->_sceneText.fixPriority(255);
+
+ // In Return to Ringworld, if in voice mode only, don't show the text
+ if ((g_vm->getGameID() == GType_Ringworld2) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)
+ && !(R2_GLOBALS._speechSubtitles & SPEECH_TEXT))
+ g_globals->_sceneText.hide();
+
g_globals->_sceneObjects->draw();
}
+ // For Return to Ringworld, play the voice overs in sequence
+ if ((g_vm->getGameID() == GType_Ringworld2) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)
+ && !playList.empty()) {
+ R2_GLOBALS._playStream.play(*playList.begin(), NULL);
+ playList.pop_front();
+ }
+
// Unless the flag is set to keep the message on-screen, show it until a mouse or keypress, then remove it
if (!keepOnscreen && !msg.empty()) {
Event event;
@@ -1757,18 +1792,31 @@ void SceneItem::display(int resNum, int lineNum, ...) {
EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) {
GLOBALS._screenSurface.updateScreen();
g_system->delayMillis(10);
- }
- // For Return to Ringworld, play the voice overs in sequence
- if ((g_vm->getGameID() == GType_Ringworld2) && !playList.empty() && !R2_GLOBALS._playStream.isPlaying()) {
- R2_GLOBALS._playStream.play(*playList.begin(), NULL);
- playList.pop_front();
+ if ((g_vm->getGameID() == GType_Ringworld2) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
+ // Allow the play stream to do processing
+ R2_GLOBALS._playStream.dispatch();
+ if (!R2_GLOBALS._playStream.isPlaying()) {
+ // Check if there are further voice samples to play
+ if (!playList.empty()) {
+ R2_GLOBALS._playStream.play(*playList.begin(), NULL);
+ playList.pop_front();
+ } else if (!(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) {
+ // If not showing text, don't both waiting for a click to end
+ break;
+ }
+ }
+ }
}
+ if (g_vm->getGameID() == GType_Ringworld2)
+ R2_GLOBALS._playStream.stop();
+
g_globals->_sceneText.remove();
}
- if ((g_vm->getGameID() != GType_Ringworld) && T2_GLOBALS._uiElements._active) {
+ if ((g_vm->getGameID() != GType_Ringworld) && (g_vm->getGameID() != GType_Ringworld2)
+ && T2_GLOBALS._uiElements._active) {
// Show user interface
T2_GLOBALS._uiElements.show();
@@ -2062,18 +2110,18 @@ SceneObject::SceneObject() : SceneHotspot() {
_visage = 0;
_strip = 0;
_frame = 0;
- _effect = 0;
- _shade = _shade2 = 0;
+ _effect = EFFECT_NONE;
+ _shade = _oldShade = 0;
_linkedActor = NULL;
- _field8A = Common::Point(0, 0);
+ _actorDestPos = Common::Point(0, 0);
_angle = 0;
_xs = 0;
_xe = 0;
_endFrame = 0;
_field68 = 0;
_regionIndex = 0;
- _field9C = NULL;
+ _shadowMap = NULL;
}
SceneObject::SceneObject(const SceneObject &so) : SceneHotspot() {
@@ -2111,8 +2159,13 @@ int SceneObject::getFrameCount() {
void SceneObject::animEnded() {
_animateMode = ANIM_MODE_NONE;
- if (_endAction)
- _endAction->signal();
+ if (_endAction) {
+ Action *endAction = _endAction;
+ if (g_vm->getGameID() == GType_Ringworld2)
+ _endAction = NULL;
+
+ endAction->signal();
+ }
}
int SceneObject::changeFrame() {
@@ -2361,12 +2414,17 @@ void SceneObject::animate(AnimateMode animMode, ...) {
case ANIM_MODE_8:
case ANIM_MODE_9:
- _field68 = va_arg(va, int);
- _endAction = va_arg(va, Action *);
- _frameChange = 1;
- _endFrame = getFrameCount();
- if (_frame == _endFrame)
- setFrame(getNewFrame());
+ if (_animateMode == ANIM_MODE_9 && g_vm->getGameID() == GType_Ringworld2) {
+ _frameChange = -1;
+ _field2E = _position;
+ } else {
+ _field68 = va_arg(va, int);
+ _endAction = va_arg(va, Action *);
+ _frameChange = 1;
+ _endFrame = getFrameCount();
+ if (_frame == _endFrame)
+ setFrame(getNewFrame());
+ }
break;
}
va_end(va);
@@ -2450,8 +2508,8 @@ void SceneObject::synchronize(Serializer &s) {
s.syncAsSint16LE(_moveDiff.x); s.syncAsSint16LE(_moveDiff.y);
s.syncAsSint32LE(_moveRate);
if (g_vm->getGameID() == GType_Ringworld2) {
- s.syncAsSint16LE(_field8A.x);
- s.syncAsSint16LE(_field8A.y);
+ s.syncAsSint16LE(_actorDestPos.x);
+ s.syncAsSint16LE(_actorDestPos.y);
}
SYNC_POINTER(_endAction);
s.syncAsUint32LE(_regionBitList);
@@ -2459,7 +2517,7 @@ void SceneObject::synchronize(Serializer &s) {
if (g_vm->getGameID() == GType_Ringworld2) {
s.syncAsSint16LE(_effect);
s.syncAsSint16LE(_shade);
- s.syncAsSint16LE(_shade2);
+ s.syncAsSint16LE(_oldShade);
SYNC_POINTER(_linkedActor);
}
}
@@ -2468,10 +2526,11 @@ void SceneObject::postInit(SceneObjectList *OwnerList) {
if (!OwnerList)
OwnerList = g_globals->_sceneObjects;
- if (!OwnerList->contains(this)) {
+ bool isExisting = OwnerList->contains(this);
+ if (!isExisting || ((_flags & OBJFLAG_REMOVE) != 0)) {
_percent = 100;
_priority = 255;
- _flags = 4;
+ _flags = OBJFLAG_ZOOMED;
_visage = 0;
_strip = 1;
_frame = 1;
@@ -2487,7 +2546,8 @@ void SceneObject::postInit(SceneObjectList *OwnerList) {
_numFrames = 10;
_regionBitList = 0;
- OwnerList->push_back(this);
+ if (!isExisting)
+ OwnerList->push_back(this);
_flags |= OBJFLAG_PANES;
}
}
@@ -2505,9 +2565,9 @@ void SceneObject::remove() {
void SceneObject::dispatch() {
if (g_vm->getGameID() == GType_Ringworld2) {
- if (_shade != _shade2)
+ if (_shade != _oldShade)
_flags |= OBJFLAG_PANES;
- _shade2 = _shade;
+ _oldShade = _shade;
}
uint32 currTime = g_globals->_events.getFrameNumber();
@@ -2625,8 +2685,9 @@ void SceneObject::dispatch() {
_linkedActor->setFrame(_frame);
}
- if ((_effect == 1) && (getRegionIndex() < 11))
- _shade = 0;
+ int regionIndex = getRegionIndex();
+ if ((_effect == EFFECT_SHADED) && (regionIndex < 11))
+ _shade = regionIndex;
}
}
@@ -2655,11 +2716,46 @@ void SceneObject::removeObject() {
GfxSurface SceneObject::getFrame() {
_visageImages.setVisage(_visage, _strip);
- return _visageImages.getFrame(_frame);
+ GfxSurface frame = _visageImages.getFrame(_frame);
+
+ // Reset any centroid adjustment flags, in
+ frame._flags &= ~(FRAME_FLIP_CENTROID_X | FRAME_FLIP_CENTROID_Y);
+
+ // For later games, check whether the appropriate object flags are set for flipping
+ if (g_vm->getGameID() != GType_Ringworld) {
+ if ((_flags & OBJFLAG_FLIP_CENTROID_X) || _visageImages._flipHoriz)
+ frame._flags |= FRAME_FLIP_CENTROID_X;
+ if ((_flags & OBJFLAG_FLIP_CENTROID_Y) || _visageImages._flipVert)
+ frame._flags |= FRAME_FLIP_CENTROID_Y;
+ }
+
+ // If shading is needed, post apply the shadiing onto the frame
+ if ((g_vm->getGameID() == GType_Ringworld2) && (_shade >= 1)) {
+ Graphics::Surface s = frame.lockSurface();
+ byte *p = (byte *)s.getPixels();
+ byte *endP = p + s.w * s.h;
+
+ while (p < endP) {
+ if (*p != frame._transColor)
+ *p = R2_GLOBALS._fadePaletteMap[_shade - 1][*p];
+ ++p;
+ }
+
+ frame.unlockSurface();
+ }
+
+ return frame;
}
void SceneObject::reposition() {
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ if (!(_flags & OBJFLAG_ZOOMED)) {
+ setZoom(g_globals->_sceneManager._scene->_zoomPercents[MIN(_position.y, (int16)255)]);
+ }
+ }
+
GfxSurface frame = getFrame();
+
_bounds.resize(frame, _position.x, _position.y - _yDiff, _percent);
_xs = _bounds.left;
_xe = _bounds.right;
@@ -2670,11 +2766,27 @@ void SceneObject::reposition() {
*/
void SceneObject::draw() {
Rect destRect = _bounds;
- destRect.translate(-g_globals->_sceneManager._scene->_sceneBounds.left,
- -g_globals->_sceneManager._scene->_sceneBounds.top);
- Region *priorityRegion = g_globals->_sceneManager._scene->_priorities.find(_priority);
+ Scene *scene = g_globals->_sceneManager._scene;
+ destRect.translate(-scene->_sceneBounds.left, -scene->_sceneBounds.top);
GfxSurface frame = getFrame();
- g_globals->gfxManager().copyFrom(frame, destRect, priorityRegion);
+ Region *priorityRegion = scene->_priorities.find(_priority);
+
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ switch (_effect) {
+ case EFFECT_SHADOW_MAP: {
+ if (!_shadowMap)
+ _shadowMap = static_cast<Ringworld2::SceneExt *>(scene)->_shadowPaletteMap;
+
+ GLOBALS.gfxManager().getSurface().copyFrom(frame, frame.getBounds(),
+ destRect, priorityRegion, _shadowMap);
+ return;
+ }
+ default:
+ break;
+ }
+ }
+
+ GLOBALS.gfxManager().copyFrom(frame, destRect, priorityRegion);
}
/**
@@ -2724,7 +2836,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);
@@ -2750,18 +2864,39 @@ void BackgroundSceneObject::draw() {
g_globals->_sceneManager._scene->_backSurface.copyFrom(frame, destRect, priorityRegion);
}
-void BackgroundSceneObject::setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority, int32 arg10) {
- warning("TODO: Implement properly BackgroundSceneObject::setup2()");
+SceneObject *BackgroundSceneObject::clone() const {
+ BackgroundSceneObject *obj = new BackgroundSceneObject(*this);
+ return obj;
+}
+
+void BackgroundSceneObject::setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority, int effect) {
+ // Check if the given object is already in the background object list
+ if (R2_GLOBALS._sceneManager._scene->_bgSceneObjects.contains(this)) {
+ _flags |= OBJFLAG_REMOVE;
+
+ // Clone the item
+ SceneObject *obj = clone();
+ obj->_flags |= OBJFLAG_CLONED;
+ R2_GLOBALS._sceneManager._scene->_bgSceneObjects.push_back(obj);
+
+ _flags |= ~OBJFLAG_REMOVE;
+ }
+
postInit();
setVisage(visage);
setStrip(stripFrameNum);
setFrame(frameNum);
- setPosition(Common::Point(posX, posY), 0);
+ setPosition(Common::Point(posX, posY));
fixPriority(priority);
}
-void BackgroundSceneObject::proc27() {
- warning("STUB: BackgroundSceneObject::proc27()");
+void BackgroundSceneObject::copySceneToBackground() {
+ GLOBALS._sceneManager._scene->_backSurface.copyFrom(g_globals->gfxManager().getSurface(), 0, 0);
+
+ // WORKAROUND: Since savegames don't store the active screen data, once we copy the
+ // foreground objects to the background, we have to prevent the scene being saved.
+ if (g_vm->getGameID() == GType_Ringworld2)
+ ((Ringworld2::SceneExt *)GLOBALS._sceneManager._scene)->_preventSaving = true;
}
/*--------------------------------------------------------------------------*/
@@ -3103,6 +3238,7 @@ Visage::Visage() {
_rlbNum = -1;
_data = NULL;
_flipHoriz = false;
+ _flipVert = false;
}
Visage::Visage(const Visage &v) {
@@ -3112,6 +3248,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 +3292,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 +3319,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 +3329,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 +3342,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() {
@@ -3236,8 +3393,9 @@ void Player::postInit(SceneObjectList *OwnerList) {
{
_moveDiff.x = 3;
_moveDiff.y = 2;
- _effect = 1;
+ _effect = EFFECT_SHADED;
_shade = 0;
+ _linkedActor = NULL;
setObjectWrapper(new SceneObjectWrapper());
setPosition(_characterPos[_characterIndex]);
@@ -3249,20 +3407,24 @@ void Player::postInit(SceneObjectList *OwnerList) {
void Player::disableControl() {
_canWalk = false;
- _uiEnabled = false;
g_globals->_events.setCursor(CURSOR_NONE);
_enabled = false;
- if ((g_vm->getGameID() != GType_Ringworld) && T2_GLOBALS._uiElements._active)
- T2_GLOBALS._uiElements.hide();
+ if (g_vm->getGameID() != GType_Ringworld2) {
+ _uiEnabled = false;
+
+ if ((g_vm->getGameID() != GType_Ringworld) && T2_GLOBALS._uiElements._active)
+ T2_GLOBALS._uiElements.hide();
+ }
}
void Player::enableControl() {
CursorType cursor;
_canWalk = true;
- _uiEnabled = true;
_enabled = true;
+ if (g_vm->getGameID() != GType_Ringworld2)
+ _uiEnabled = true;
switch (g_vm->getGameID()) {
case GType_BlueForce:
@@ -3270,7 +3432,7 @@ void Player::enableControl() {
cursor = g_globals->_events.getCursor();
g_globals->_events.setCursor(cursor);
- if (T2_GLOBALS._uiElements._active)
+ if (g_vm->getGameID() == GType_BlueForce && T2_GLOBALS._uiElements._active)
T2_GLOBALS._uiElements.show();
break;
@@ -3968,7 +4130,7 @@ int WalkRegions::indexOf(const Common::Point &pt, const Common::List<int> *index
}
void WalkRegions::synchronize(Serializer &s) {
- // Synchronise the list of disabled regions as a list of values terminated with a '-1'
+ // Synchronize the list of disabled regions as a list of values terminated with a '-1'
int regionId = 0;
if (s.isLoading()) {
_disabledRegions.clear();
@@ -4180,11 +4342,11 @@ void SceneHandler::process(Event &event) {
g_vm->_debugger->onFrame();
}
- if ((event.eventType == EVENT_KEYPRESS) && g_globals->_player._enabled && g_globals->_player._canWalk) {
+ if ((event.eventType == EVENT_KEYPRESS) && g_globals->_player._enabled) {
// Keyboard shortcuts for different actions
switch (event.kbd.keycode) {
case Common::KEYCODE_w:
- g_globals->_events.setCursor(CURSOR_WALK);
+ g_globals->_events.setCursor(GLOBALS._player._canWalk ? CURSOR_WALK : CURSOR_USE);
event.handled = true;
break;
case Common::KEYCODE_l:
@@ -4218,9 +4380,10 @@ void SceneHandler::process(Event &event) {
// Scan the item list to find one the mouse is within
SynchronizedList<SceneItem *>::iterator i;
for (i = g_globals->_sceneItems.begin(); i != g_globals->_sceneItems.end(); ++i) {
- if ((*i)->contains(event.mousePos)) {
+ SceneItem *item = *i;
+ if (item->contains(event.mousePos)) {
// Pass the action to the item
- bool handled = (*i)->startAction(g_globals->_events.getCursor(), event);
+ bool handled = item->startAction(g_globals->_events.getCursor(), event);
if (!handled)
// Item wasn't handled, keep scanning
continue;
@@ -4267,10 +4430,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..3286ee1448 100644
--- a/engines/tsage/core.h
+++ b/engines/tsage/core.h
@@ -466,17 +466,23 @@ enum AnimateMode {ANIM_MODE_NONE = 0, ANIM_MODE_1 = 1, ANIM_MODE_2 = 2, ANIM_MOD
ANIM_MODE_9 = 9
};
+// Actor effect enumeration used in Return to Ringworld 2
+enum Effect { EFFECT_NONE = 0, EFFECT_SHADED = 1, EFFECT_3 = 3,
+ EFFECT_SHADOW_MAP = 5, EFFECT_SHADED2 = 6 };
+
class SceneObject;
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);
@@ -509,7 +515,8 @@ public:
enum ObjectFlags {OBJFLAG_FIXED_PRIORITY = 1, OBJFLAG_NO_UPDATES = 2, OBJFLAG_ZOOMED = 4,
OBJFLAG_SUPPRESS_DISPATCH = 8, OBJFLAG_HIDE = 0x100, OBJFLAG_HIDING = 0x200, OBJFLAG_REMOVE = 0x400,
OBJFLAG_CLONED = 0x800, OBJFLAG_CHECK_REGION = 0x1000, OBJFLAG_PANE_0 = 0x4000, OBJFLAG_PANE_1 = 0x8000,
- OBJFLAG_PANES = OBJFLAG_PANE_0 | OBJFLAG_PANE_1
+ OBJFLAG_PANES = OBJFLAG_PANE_0 | OBJFLAG_PANE_1,
+ OBJFLAG_FLIP_CENTROID_X = 0x10000, OBJFLAG_FLIP_CENTROID_Y = 0x20000
};
class SceneObject : public SceneHotspot {
@@ -542,13 +549,13 @@ public:
EventHandler *_mover;
Common::Point _moveDiff;
int _moveRate;
- Common::Point _field8A;
+ Common::Point _actorDestPos;
Action *_endAction;
uint32 _regionBitList;
// Ringworld 2 specific fields
- byte *_field9C;
- int _shade, _shade2;
+ byte *_shadowMap;
+ int _shade, _oldShade;
int _effect;
SceneObject *_linkedActor;
public:
@@ -573,7 +580,6 @@ public:
int getRegionIndex();
int checkRegion(const Common::Point &pt);
void animate(AnimateMode animMode, ...);
- SceneObject *clone() const;
void checkAngle(const SceneObject *obj);
void checkAngle(const Common::Point &pt);
void hide();
@@ -600,6 +606,7 @@ public:
virtual void changeAngle(int angle);
// New methods introduced by Ringworld 2
virtual void copy(SceneObject *src);
+ virtual SceneObject *clone() const;
void setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority);
void setup(int visage, int stripFrameNum, int frameNum);
@@ -610,8 +617,10 @@ public:
virtual Common::String getClassName() { return "BackgroundSceneObject"; }
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void draw();
- void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority, int32 arg10);
- void proc27();
+ virtual SceneObject *clone() const;
+
+ void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority, int effect);
+ static void copySceneToBackground();
};
class SceneText : public SceneObject {
@@ -898,6 +907,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/debugger.cpp b/engines/tsage/debugger.cpp
index 82645f2d62..c7da5f5d30 100644
--- a/engines/tsage/debugger.cpp
+++ b/engines/tsage/debugger.cpp
@@ -632,57 +632,57 @@ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) {
DebugPrintf("Available objects for this game are:\n");
DebugPrintf("1 - R2_OPTO_DISK\n");
- DebugPrintf("2 - R2_2\n");
+ DebugPrintf("2 - R2_READER\n");
DebugPrintf("3 - R2_NEGATOR_GUN\n");
DebugPrintf("4 - R2_STEPPING_DISKS\n");
- DebugPrintf("5 - R2_5\n");
- DebugPrintf("6 - R2_6\n");
- DebugPrintf("7 - R2_7\n");
- DebugPrintf("8 - R2_8\n");
- DebugPrintf("9 - R2_9\n");
- DebugPrintf("10 - R2_10\n");
- DebugPrintf("11 - R2_11\n");
- DebugPrintf("12 - R2_12\n");
- DebugPrintf("13 - R2_13\n");
- DebugPrintf("14 - R2_14\n");
- DebugPrintf("15 - R2_15\n");
- DebugPrintf("16 - R2_16\n");
- DebugPrintf("17 - R2_17\n");
- DebugPrintf("18 - R2_18\n");
- DebugPrintf("19 - R2_19\n");
- DebugPrintf("20 - R2_20\n");
- DebugPrintf("21 - R2_21\n");
- DebugPrintf("22 - R2_22\n");
- DebugPrintf("23 - R2_23\n");
- DebugPrintf("24 - R2_24\n");
- DebugPrintf("25 - R2_25\n");
- DebugPrintf("26 - R2_26\n");
- DebugPrintf("27 - R2_27\n");
- DebugPrintf("28 - R2_28\n");
- DebugPrintf("29 - R2_29\n");
- DebugPrintf("30 - R2_30\n");
- DebugPrintf("31 - R2_31\n");
- DebugPrintf("32 - R2_32\n");
- DebugPrintf("33 - R2_33\n");
- DebugPrintf("34 - R2_34\n");
- DebugPrintf("35 - R2_35\n");
- DebugPrintf("36 - R2_36\n");
- DebugPrintf("37 - R2_37\n");
- DebugPrintf("38 - R2_38\n");
- DebugPrintf("39 - R2_39\n");
- DebugPrintf("40 - R2_40\n");
- DebugPrintf("41 - R2_41\n");
- DebugPrintf("42 - R2_42\n");
- DebugPrintf("43 - R2_43\n");
- DebugPrintf("44 - R2_44\n");
- DebugPrintf("45 - R2_45\n");
- DebugPrintf("46 - R2_46\n");
- DebugPrintf("47 - R2_47\n");
- DebugPrintf("48 - R2_48\n");
- DebugPrintf("49 - R2_49\n");
- DebugPrintf("50 - R2_50\n");
- DebugPrintf("51 - R2_51\n");
- DebugPrintf("52 - R2_52\n");
+ DebugPrintf("5 - R2_ATTRACTOR_UNIT\n");
+ DebugPrintf("6 - R2_SENSOR_PROBE\n");
+ DebugPrintf("7 - R2_SONIC_STUNNER\n");
+ DebugPrintf("8 - R2_CABLE_HARNESS\n");
+ DebugPrintf("9 - R2_COM_SCANNER\n");
+ DebugPrintf("10 - R2_SPENT_POWER_CAPSULE\n");
+ DebugPrintf("11 - R2_CHARGED_POWER_CAPSULE\n");
+ DebugPrintf("12 - R2_AEROSOL\n");
+ DebugPrintf("13 - R2_REMOTE_CONTROL\n");
+ DebugPrintf("14 - R2_OPTICAL_FIBRE\n");
+ DebugPrintf("15 - R2_CLAMP\n");
+ DebugPrintf("16 - R2_ATTRACTOR_CABLE_HARNESS\n");
+ DebugPrintf("17 - R2_FUEL_CELL\n");
+ DebugPrintf("18 - R2_GYROSCOPE\n");
+ DebugPrintf("19 - R2_AIRBAG\n");
+ DebugPrintf("20 - R2_REBREATHER_TANK\n");
+ DebugPrintf("21 - R2_RESERVE_REBREATHER_TANK\n");
+ DebugPrintf("22 - R2_GUIDANCE_MODULE\n");
+ DebugPrintf("23 - R2_THRUSTER_VALVE\n");
+ DebugPrintf("24 - R2_BALLOON_BACKPACK\n");
+ DebugPrintf("25 - R2_RADAR_MECHANISM\n");
+ DebugPrintf("26 - R2_JOYSTICK\n");
+ DebugPrintf("27 - R2_IGNITOR\n");
+ DebugPrintf("28 - R2_DIAGNOSTICS_DISPLAY\n");
+ DebugPrintf("29 - R2_GLASS_DOME\n");
+ DebugPrintf("30 - R2_WICK_LAMP\n");
+ DebugPrintf("31 - R2_SCRITH_KEY\n");
+ DebugPrintf("32 - R2_TANNER_MASK\n");
+ DebugPrintf("33 - R2_PURE_GRAIN_ALCOHOL\n");
+ DebugPrintf("34 - R2_SAPPHIRE_BLUE\n");
+ DebugPrintf("35 - R2_ANCIENT_SCROLLS\n");
+ DebugPrintf("36 - R2_FLUTE\n");
+ DebugPrintf("37 - R2_GUNPOWDER\n");
+ DebugPrintf("38 - R2_NONAME\n");
+ DebugPrintf("39 - R2_COM_SCANNER_2\n");
+ DebugPrintf("40 - R2_SUPERCONDUCTOR_WIRE\n");
+ DebugPrintf("41 - R2_PILLOW\n");
+ DebugPrintf("42 - R2_FOOD_TRAY\n");
+ DebugPrintf("43 - R2_LASER_HACKSAW\n");
+ DebugPrintf("44 - R2_PHOTON_STUNNER\n");
+ DebugPrintf("45 - R2_BATTERY\n");
+ DebugPrintf("46 - R2_SOAKED_FACEMASK\n");
+ DebugPrintf("47 - R2_LIGHT_BULB\n");
+ DebugPrintf("48 - R2_ALCOHOL_LAMP\n");
+ DebugPrintf("49 - R2_ALCOHOL_LAMP_2\n");
+ DebugPrintf("50 - R2_ALCOHOL_LAMP_3\n");
+ DebugPrintf("51 - R2_BROKEN_DISPLAY\n");
+ DebugPrintf("52 - R2_TOOLBOX\n");
return true;
}
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index a35d663b93..5eae7557d2 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -75,7 +75,6 @@ class TSageMetaEngine : public AdvancedMetaEngine {
public:
TSageMetaEngine() : AdvancedMetaEngine(TsAGE::gameDescriptions, sizeof(TsAGE::tSageGameDescription), tSageGameTitles) {
_singleid = "tsage";
- _guioptions = GUIO1(GUIO_NOSPEECH);
}
virtual const char *getName() const {
diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h
index b374dbc98b..0f7f1e49bb 100644
--- a/engines/tsage/detection_tables.h
+++ b/engines/tsage/detection_tables.h
@@ -165,7 +165,7 @@ static const tSageGameDescription gameDescriptions[] = {
AD_ENTRY1s("r2rw.rlb", "df6c25622387007788ca36d99362c1f0", 47586928),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_CD | ADGF_UNSTABLE,
+ ADGF_CD | ADGF_TESTING,
GUIO0()
},
GType_Ringworld2,
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/events.cpp b/engines/tsage/events.cpp
index 8f07a8243b..6baa654214 100644
--- a/engines/tsage/events.cpp
+++ b/engines/tsage/events.cpp
@@ -71,7 +71,7 @@ bool EventsClass::pollEvent() {
break;
default:
- break;
+ break;
}
return true;
@@ -113,7 +113,7 @@ bool EventsClass::getEvent(Event &evt, int eventMask) {
case Common::EVENT_RBUTTONUP:
case Common::EVENT_MBUTTONUP:
evt.eventType = EVENT_BUTTON_UP;
- evt.btnState = 0;
+ evt.btnState = BTNSHIFT_LEFT;
break;
case Common::EVENT_KEYDOWN:
evt.eventType = EVENT_KEYPRESS;
@@ -271,13 +271,18 @@ void EventsClass::setCursor(CursorType cursorType) {
_currentCursor = cursorType;
cursor = g_resourceManager->getSubResource(5, 1, cursorType - R2CURSORS_START, &size);
break;
+
+ case R2_CURSOR_ROPE:
+ _currentCursor = cursorType;
+ cursor = g_resourceManager->getSubResource(5, 4, 1, &size);
+ break;
}
// Decode the cursor
GfxSurface s = surfaceFromRes(cursor);
Graphics::Surface surface = s.lockSurface();
- const byte *cursorData = (const byte *)surface.getBasePtr(0, 0);
+ const byte *cursorData = (const byte *)surface.getPixels();
CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
s.unlockSurface();
@@ -333,7 +338,7 @@ void EventsClass::pushCursor(CursorType cursorType) {
GfxSurface s = surfaceFromRes(cursor);
Graphics::Surface surface = s.lockSurface();
- const byte *cursorData = (const byte *)surface.getBasePtr(0, 0);
+ const byte *cursorData = (const byte *)surface.getPixels();
CursorMan.pushCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
s.unlockSurface();
@@ -346,7 +351,7 @@ void EventsClass::popCursor() {
}
void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Common::Point &hotspot, CursorType cursorId) {
- const byte *cursorData = (const byte *)cursor.getBasePtr(0, 0);
+ const byte *cursorData = (const byte *)cursor.getPixels();
CursorMan.replaceCursor(cursorData, cursor.w, cursor.h, hotspot.x, hotspot.y, transColor);
_currentCursor = cursorId;
@@ -355,7 +360,7 @@ void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Com
void EventsClass::setCursor(GfxSurface &cursor) {
Graphics::Surface s = cursor.lockSurface();
- const byte *cursorData = (const byte *)s.getBasePtr(0, 0);
+ const byte *cursorData = (const byte *)s.getPixels();
CursorMan.replaceCursor(cursorData, cursor.getBounds().width(), cursor.getBounds().height(),
cursor._centroid.x, cursor._centroid.y, cursor._transColor);
diff --git a/engines/tsage/events.h b/engines/tsage/events.h
index a1e9da3477..9ef4813e47 100644
--- a/engines/tsage/events.h
+++ b/engines/tsage/events.h
@@ -108,6 +108,7 @@ enum CursorType {
EXITCURSOR_NE = 0x800D, EXITCURSOR_SE = 0x800E, EXITCURSOR_SW = 0x800F, EXITCURSOR_NW = 0x8010,
SHADECURSOR_UP = 0x8011, SHADECURSOR_DOWN = 0x8012, SHADECURSOR_HAND = 0x8013,
R2_CURSOR_20 = 0x8014, R2_CURSOR_21 = 0x8015, R2_CURSOR_22 = 0x8016, R2_CURSOR_23 = 0x8017,
+ R2_CURSOR_ROPE = 0x8025,
// Cursors
CURSOR_WALK = 0x100, CURSOR_LOOK = 0x200, CURSOR_700 = 700, CURSOR_USE = 0x400, CURSOR_TALK = 0x800,
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index 4589a926c9..388f6f7686 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -26,6 +26,8 @@
#include "tsage/ringworld/ringworld_demo.h"
#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/ringworld2/ringworld2_logic.h"
+#include "tsage/ringworld2/ringworld2_scenes0.h"
+#include "tsage/staticres.h"
namespace TsAGE {
@@ -46,6 +48,11 @@ static SavedObject *classFactoryProc(const Common::String &className) {
if (className == "SceneObjectWrapper") return new SceneObjectWrapper();
if (className == "PaletteRotation") return new PaletteRotation();
if (className == "PaletteFader") return new PaletteFader();
+ if (className == "SceneText") return new SceneText();
+
+ // Return to Ringworld specific classes
+ if (className == "Scene205_Star") return new Ringworld2::Star();
+
return NULL;
}
@@ -118,8 +125,11 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
_sounds.push_back(&_soundHandler);
_sounds.push_back(&_sequenceManager._soundHandler);
- _scrollFollower = NULL;
- _inventory = NULL;
+ _scrollFollower = nullptr;
+
+ _inventory = nullptr;
+ _game = nullptr;
+ _sceneHandler = nullptr;
switch (g_vm->getGameID()) {
case GType_Ringworld:
@@ -144,6 +154,7 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
_sceneHandler = new Ringworld2::SceneHandlerExt();
break;
}
+
}
Globals::~Globals() {
@@ -203,6 +214,11 @@ void Globals::dispatchSounds() {
/*--------------------------------------------------------------------------*/
+TsAGE2Globals::TsAGE2Globals() {
+ _onSelectItem = NULL;
+ _interfaceY = 0;
+}
+
void TsAGE2Globals::reset() {
Globals::reset();
@@ -223,15 +239,46 @@ void TsAGE2Globals::synchronize(Serializer &s) {
namespace BlueForce {
BlueForceGlobals::BlueForceGlobals(): TsAGE2Globals() {
+ _hiddenDoorStatus = 0;
+ _nico910State = 0;
+ _stuart910State = 0;
+ _nico910Talk = 0;
+ _stuart910Talk = 0;
+ _deziTopic = 0;
+ _deathReason = 0;
+ _driveFromScene = 300;
+ _driveToScene = 0;
+ _subFlagBitArr1 = 0;
+ _subFlagBitArr2 = 0;
+ _scene410HarrisonTalkFl = false;
+ _scene410Action1Count = 0;
+ _scene410TalkCount = 0;
+ _scene410HarrisonMovedFl = false;
+ _bookmark = bNone;
+ _mapLocationId = 1;
+ _clip1Bullets = 8;
+ _clip2Bullets = 8;
+
+ _dayNumber = 0;
+ _tonyDialogCtr = 0;
+ _marinaWomanCtr = 0;
+ _kateDialogCtr = 0;
+ _v4CEB6 = 0;
+ _safeCombination = 0;
+ _gateStatus = 0;
+ _greenDay5TalkCtr = 0;
+ _v4CEC8 = 1;
+ _v4CECA = 0;
+ _v4CECC = 0;
}
void BlueForceGlobals::synchronize(Serializer &s) {
TsAGE2Globals::synchronize(s);
+ int16 useless = 0;
s.syncAsSint16LE(_dayNumber);
if (s.getVersion() < 9) {
- int tmpVar = 0;
- s.syncAsSint16LE(tmpVar);
+ s.syncAsSint16LE(useless);
}
s.syncAsSint16LE(_tonyDialogCtr);
s.syncAsSint16LE(_marinaWomanCtr);
@@ -240,7 +287,8 @@ void BlueForceGlobals::synchronize(Serializer &s) {
s.syncAsSint16LE(_safeCombination);
s.syncAsSint16LE(_gateStatus);
s.syncAsSint16LE(_greenDay5TalkCtr);
- s.syncAsSint16LE(_v4CEC4);
+ if (s.getVersion() < 11)
+ s.syncAsSint16LE(useless);
s.syncAsSint16LE(_v4CEC8);
s.syncAsSint16LE(_v4CECA);
s.syncAsSint16LE(_v4CECC);
@@ -248,26 +296,30 @@ void BlueForceGlobals::synchronize(Serializer &s) {
s.syncAsByte(_breakerBoxStatusArr[i]);
s.syncAsSint16LE(_hiddenDoorStatus);
s.syncAsSint16LE(_nico910State);
- s.syncAsSint16LE(_v4CEE4);
- s.syncAsSint16LE(_v4CEE6);
- s.syncAsSint16LE(_v4CEE8);
+ s.syncAsSint16LE(_stuart910State);
+ s.syncAsSint16LE(_nico910Talk);
+ s.syncAsSint16LE(_stuart910Talk);
s.syncAsSint16LE(_deziTopic);
s.syncAsSint16LE(_deathReason);
s.syncAsSint16LE(_driveFromScene);
s.syncAsSint16LE(_driveToScene);
- s.syncAsSint16LE(_v501F8);
- s.syncAsSint16LE(_v501FA);
- s.syncAsSint16LE(_v501FC);
- s.syncAsSint16LE(_v5020C);
- s.syncAsSint16LE(_v50696);
+ if (s.getVersion() < 11) {
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ }
s.syncAsSint16LE(_subFlagBitArr1);
s.syncAsSint16LE(_subFlagBitArr2);
- s.syncAsSint16LE(_v50CC2);
- s.syncAsSint16LE(_v50CC4);
- s.syncAsSint16LE(_v50CC6);
- s.syncAsSint16LE(_v50CC8);
- s.syncAsSint16LE(_v51C42);
- s.syncAsSint16LE(_v51C44);
+ s.syncAsSint16LE(_scene410HarrisonTalkFl);
+ s.syncAsSint16LE(_scene410Action1Count);
+ s.syncAsSint16LE(_scene410TalkCount);
+ s.syncAsSint16LE(_scene410HarrisonMovedFl);
+ if (s.getVersion() < 11) {
+ s.syncAsSint16LE(useless);
+ s.syncAsSint16LE(useless);
+ }
s.syncAsSint16LE(_bookmark);
s.syncAsSint16LE(_mapLocationId);
s.syncAsSint16LE(_clip1Bullets);
@@ -297,7 +349,6 @@ void BlueForceGlobals::reset() {
_safeCombination = 0;
_gateStatus = 0;
_greenDay5TalkCtr = 0;
- _v4CEC4 = 0;
_v4CEC8 = 1;
_v4CECA = 0;
_v4CECC = 0;
@@ -321,24 +372,17 @@ void BlueForceGlobals::reset() {
_breakerBoxStatusArr[17] = 0;
_hiddenDoorStatus = 0;
_nico910State = 0;
- _v4CEE4 = 0;
- _v4CEE6 = 0;
- _v4CEE8 = 0;
+ _stuart910State = 0;
+ _nico910Talk = 0;
+ _stuart910Talk = 0;
_deziTopic = 0;
_deathReason = 0;
- _v501F8 = 0;
- _v501FA = 0;
- _v501FC = 0;
- _v5020C = 0;
- _v50696 = 0;
_subFlagBitArr1 = 0;
_subFlagBitArr2 = 0;
- _v50CC2 = 0;
- _v50CC4 = 0;
- _v50CC6 = 0;
- _v50CC8 = 0;
- _v51C42 = 0;
- _v51C44 = 1;
+ _scene410HarrisonTalkFl = false;
+ _scene410Action1Count = 0;
+ _scene410TalkCount = 0;
+ _scene410HarrisonMovedFl = false;
_clip1Bullets = 8;
_clip2Bullets = 8;
}
@@ -366,107 +410,158 @@ bool BlueForceGlobals::removeFlag(int flagNum) {
namespace Ringworld2 {
+Ringworld2Globals::Ringworld2Globals() {
+ _scannerDialog = new ScannerDialog();
+ _speechSubtitles = SPEECH_TEXT;
+
+ // Register the inner sound objects for each of the global ASoundExt fields.
+ // Normally the ASound constructor would do this, but because they're fields
+ // of the globals, the g_globals reference isn't ready for them to use
+ _sounds.push_back(&_sound1);
+ _sounds.push_back(&_sound2);
+ _sounds.push_back(&_sound3);
+ _sounds.push_back(&_sound4);
+
+ // Initialize fields
+ _stripModifier = 0;
+ _flubMazeArea = 1;
+ _flubMazeEntryDirection = 0;
+ _maze3800SceneNumb = 3800;
+ _landerSuitNumber = 2;
+ _desertStepsRemaining = 5;
+ _desertCorrectDirection = 0;
+ _desertPreviousDirection = 0;
+ _desertWrongDirCtr = -1;
+ _balloonAltitude = 5;
+ _scene1925CurrLevel = 0;
+ _walkwaySceneNumber = 0;
+ _mirandaJailState = 0;
+ _scientistConvIndex = 0;
+ _ductMazePanel1State = 1;
+ _ductMazePanel2State = 1;
+ _ductMazePanel3State = 1;
+ _scene180Mode = -1;
+ _v57709 = 0;
+ _v5780C = 0;
+ _v5780E = 0;
+ _v57810 = 0;
+
+ _fadePaletteFlag = false;
+ _insetUp = 0;
+ _frameEdgeColor = 2;
+ _animationCtr = 0;
+ _electromagnetChangeAmount = 0;
+ _electromagnetZoom = 0;
+ _tractorField = false;
+ _cableAttached = 0;
+ _foodCount = 0;
+ _rimLocation = 0;
+ _rimTransportLocation = 0;
+}
+
+Ringworld2Globals::~Ringworld2Globals() {
+ delete _scannerDialog;
+}
+
void Ringworld2Globals::reset() {
Globals::reset();
+ if (!_scannerDialog)
+ _scannerDialog = new ScannerDialog();
+
+ // Default to Quinn as the active character
+ T2_GLOBALS._player._characterIndex = R2_QUINN;
+
// 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;
- _v5589E.set(0, 0, 0, 0);
- _v558B6.set(0, 0, 0, 0);
- _v558C2 = 0;
- _animationCtr = 0;
- _v5657C = 0;
- _v565E1 = 0;
- _v565E3 = 0;
- _v565E5 = 0;
- _v565E7 = 0;
- _v565E9 = -5;
- _v565EB = 26;
- _v565F5 = 0;
- _v565F6 = 0;
- _v565FA = 0;
- _v565AE = 0;
- _v56605[0] = 0;
- _v56605[1] = 3;
- _v56605[2] = 5;
- _v56605[3] = 1;
- _v56605[4] = 2;
- _v56605[5] = 5;
- _v56605[6] = 9;
- _v56605[7] = 14;
- _v56605[8] = 15;
- _v56605[9] = 18;
- _v56605[10] = 20;
- _v56605[11] = 25;
- _v56605[12] = 27;
- _v56605[13] = 31;
+ Common::fill(&_fadePaletteMap[0][0], &_fadePaletteMap[9][256], 0);
+ Common::fill(&_paletteMap[0], &_paletteMap[4096], 0);
+ _fadePaletteFlag = false;
+ _animationCtr = 0;
+ _electromagnetChangeAmount = 0;
+ _electromagnetZoom = 0;
+ _tractorField = false;
+ _cableAttached = 0;
+ _foodCount = 0;
+ _rimLocation = 0;
+ _rimTransportLocation = 0;
+ _stripModifier = 0;
+ _spillLocation[0] = 0;
+ _spillLocation[1] = 3;
+ _spillLocation[R2_SEEKER] = 5;
+ _spillLocation[3] = 1;
+ _spillLocation[4] = 2;
+ _spillLocation[5] = 5;
+ _spillLocation[6] = 9;
+ _spillLocation[7] = 14;
+ _spillLocation[8] = 15;
+ _spillLocation[9] = 18;
+ _spillLocation[10] = 20;
+ _spillLocation[11] = 25;
+ _spillLocation[12] = 27;
+ _spillLocation[13] = 31;
+
+ // Initialize the vampire data within the Flub maze
for (int i = 0; i < 18; i++) {
- _v56613[(i * 4) ] = 1;
- _v56613[(i * 4) + 2] = 0;
- _v56613[(i * 4) + 3] = 0;
+ _vampireData[i]._isAlive = true;
+ _vampireData[i]._position = Common::Point();
}
- _v56613[( 0 * 4) + 1] = 1;
- _v56613[( 1 * 4) + 1] = 2;
- _v56613[( 2 * 4) + 1] = 2;
- _v56613[( 3 * 4) + 1] = 3;
- _v56613[( 4 * 4) + 1] = 2;
- _v56613[( 5 * 4) + 1] = 2;
- _v56613[( 6 * 4) + 1] = 3;
- _v56613[( 7 * 4) + 1] = 1;
- _v56613[( 8 * 4) + 1] = 1;
- _v56613[( 9 * 4) + 1] = 3;
- _v56613[(10 * 4) + 1] = 3;
- _v56613[(11 * 4) + 1] = 1;
- _v56613[(12 * 4) + 1] = 2;
- _v56613[(13 * 4) + 1] = 3;
- _v56613[(14 * 4) + 1] = 2;
- _v56613[(15 * 4) + 1] = 3;
- _v56613[(16 * 4) + 1] = 1;
- _v56613[(17 * 4) + 1] = 1;
-
- _v566A6 = 3800;
- _v566A3 = 2;
- _v566A4 = 1;
- _v566A5 = 0;
- _v566A8 = 5;
- _v566A9 = 0;
- _v566AA = 0;
+ _vampireData[0]._shotsRequired = 1;
+ _vampireData[1]._shotsRequired = 2;
+ _vampireData[2]._shotsRequired = 2;
+ _vampireData[3]._shotsRequired = 3;
+ _vampireData[4]._shotsRequired = 2;
+ _vampireData[5]._shotsRequired = 2;
+ _vampireData[6]._shotsRequired = 3;
+ _vampireData[7]._shotsRequired = 1;
+ _vampireData[8]._shotsRequired = 1;
+ _vampireData[9]._shotsRequired = 3;
+ _vampireData[10]._shotsRequired = 3;
+ _vampireData[11]._shotsRequired = 1;
+ _vampireData[12]._shotsRequired = 2;
+ _vampireData[13]._shotsRequired = 3;
+ _vampireData[14]._shotsRequired = 2;
+ _vampireData[15]._shotsRequired = 3;
+ _vampireData[16]._shotsRequired = 1;
+ _vampireData[17]._shotsRequired = 1;
+
+ _maze3800SceneNumb = 3800;
+ _landerSuitNumber = 2;
+ _flubMazeArea = 1;
+ _flubMazeEntryDirection = 0;
+ _desertStepsRemaining = 5;
+ _desertCorrectDirection = 0;
+ _desertPreviousDirection = 0;
for (int i = 0; i < 1000; i++)
- _v566AB[i] = 0;
- _v56A93 = -1;
- _v56A99 = 5;
+ _desertMovements[i] = 0;
+ _desertWrongDirCtr = -1;
+ _balloonAltitude = 5;
_scene1925CurrLevel = 0; //_v56A9C
- _v56A9E = 0;
- _v56AA0 = 0;
- _v56AA1 = 0;
- _v56AA2 = 60;
- _v56AA4 = 660;
- _v56AA6 = 1;
- _v56AA7 = 1;
- _v56AA8 = 1;
- _v56AAB = 0;
+ _walkwaySceneNumber = 0;
+ _mirandaJailState = 0;
+ _scientistConvIndex = 0;
+ _ventCellPos = Common::Point(60, 660);
+ _ductMazePanel1State = 1;
+ _ductMazePanel2State = 1;
+ _ductMazePanel3State = 1;
_scene180Mode = -1;
_v57709 = 0;
_v5780C = 0;
_v5780E = 0;
_v57810 = 0;
- _v57C2C = 0;
- _v565EC[0] = 0;
- _v565EC[1] = 27;
- _v565EC[2] = 27;
- _v565EC[3] = 4;
- _v565EC[4] = 4;
- Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 1);
- _speechSubtitles = SPEECH_VOICE | SPEECH_TEXT;
+ _s1550PlayerArea[R2_QUINN] = Common::Point(27, 4);
+ _s1550PlayerArea[R2_SEEKER] = Common::Point(27, 4);
+ Common::fill(&_scannerFrequencies[0], &_scannerFrequencies[MAX_CHARACTERS], 1);
_insetUp = 0;
- _frameEdgeColour = 2;
+ _frameEdgeColor = 2;
Common::fill(&_stripManager_lookupList[0], &_stripManager_lookupList[12], 0);
_stripManager_lookupList[0] = 1;
_stripManager_lookupList[1] = 1;
@@ -479,76 +574,86 @@ void Ringworld2Globals::reset() {
_stripManager_lookupList[10] = 1;
_stripManager_lookupList[11] = 1;
+ // Reset junk/component data in scene 1550
+ Common::copy(&scene1550JunkLocationsDefault[0], &scene1550JunkLocationsDefault[508],
+ &_scene1550JunkLocations[0]);
+
// Reset fields stored in the player class
_player._characterIndex = R2_QUINN;
- _player._characterScene[1] = 100;
- _player._characterScene[2] = 300;
- _player._characterScene[3] = 300;
+ _player._characterScene[R2_QUINN] = 100;
+ _player._characterScene[R2_SEEKER] = 300;
+ _player._characterScene[R2_MIRANDA] = 300;
}
void Ringworld2Globals::synchronize(Serializer &s) {
TsAGE2Globals::synchronize(s);
int i;
- _v5589E.synchronize(s);
- _v558B6.synchronize(s);
-
- s.syncAsSint16LE(_v558C2);
s.syncAsSint16LE(_animationCtr);
- s.syncAsSint16LE(_v5657C);
- s.syncAsSint16LE(_v565E1);
- s.syncAsSint16LE(_v565E3);
- s.syncAsSint16LE(_v565E5);
- s.syncAsSint16LE(_v565E7);
- s.syncAsSint16LE(_v565E9);
- s.syncAsSint16LE(_v565EB);
- s.syncAsSint16LE(_v565F5);
- s.syncAsSint16LE(_v565F6);
- s.syncAsSint16LE(_v565FA);
- s.syncAsSint16LE(_v566A3);
- s.syncAsSint16LE(_v566A6);
- s.syncAsSint16LE(_v56A93);
+ s.syncAsSint16LE(_electromagnetChangeAmount);
+ s.syncAsSint16LE(_electromagnetZoom);
+ s.syncAsSint16LE(_tractorField);
+ s.syncAsSint16LE(_cableAttached);
+ s.syncAsSint16LE(_foodCount);
+ s.syncAsSint32LE(_rimLocation);
+ s.syncAsSint16LE(_rimTransportLocation);
+ s.syncAsSint16LE(_landerSuitNumber);
+ s.syncAsSint16LE(_maze3800SceneNumb);
+ s.syncAsSint16LE(_desertWrongDirCtr);
s.syncAsSint16LE(_scene1925CurrLevel); // _v56A9C
- s.syncAsSint16LE(_v56A9E);
- s.syncAsSint16LE(_v56AA2);
- s.syncAsSint16LE(_v56AA4);
- s.syncAsSint16LE(_v56AAB);
+ s.syncAsSint16LE(_walkwaySceneNumber);
+ s.syncAsSint16LE(_ventCellPos.x);
+ s.syncAsSint16LE(_ventCellPos.y);
s.syncAsSint16LE(_scene180Mode);
s.syncAsSint16LE(_v57709);
s.syncAsSint16LE(_v5780C);
s.syncAsSint16LE(_v5780E);
s.syncAsSint16LE(_v57810);
- s.syncAsSint16LE(_v57C2C);
- s.syncAsSint16LE(_speechSubtitles);
- for (i = 0; i < 5; i++)
- s.syncAsByte(_v565EC[i]);
+ s.syncAsByte(_s1550PlayerArea[R2_QUINN].x);
+ s.syncAsByte(_s1550PlayerArea[R2_SEEKER].x);
+ s.syncAsByte(_s1550PlayerArea[R2_QUINN].y);
+ s.syncAsByte(_s1550PlayerArea[R2_SEEKER].y);
for (i = 0; i < MAX_CHARACTERS; ++i)
- s.syncAsByte(_v565F1[i]);
-
- s.syncAsByte(_v565AE);
- s.syncAsByte(_v566A4);
- s.syncAsByte(_v566A5);
- s.syncAsByte(_v566A8);
- s.syncAsByte(_v566A9);
- s.syncAsByte(_v566AA);
- s.syncAsByte(_v56AA0);
- s.syncAsByte(_v56AA1);
- s.syncAsByte(_v56AA6);
- s.syncAsByte(_v56AA7);
- s.syncAsByte(_v56AA8);
+ s.syncAsByte(_scannerFrequencies[i]);
+
+ s.syncAsByte(_stripModifier);
+ s.syncAsByte(_flubMazeArea);
+ s.syncAsByte(_flubMazeEntryDirection);
+ s.syncAsByte(_desertStepsRemaining);
+ s.syncAsByte(_desertCorrectDirection);
+ s.syncAsByte(_desertPreviousDirection);
+ s.syncAsByte(_mirandaJailState);
+ s.syncAsByte(_scientistConvIndex);
+ s.syncAsByte(_ductMazePanel1State);
+ s.syncAsByte(_ductMazePanel2State);
+ s.syncAsByte(_ductMazePanel3State);
for (i = 0; i < 14; ++i)
- s.syncAsByte(_v56605[i]);
+ s.syncAsByte(_spillLocation[i]);
for (i = 0; i < 1000; ++i)
- s.syncAsByte(_v566AB[i]);
- s.syncAsByte(_v56A99);
+ s.syncAsByte(_desertMovements[i]);
+ s.syncAsByte(_balloonAltitude);
for (i = 0; i < 12; ++i)
s.syncAsByte(_stripManager_lookupList[i]);
s.syncAsSint16LE(_insetUp);
- s.syncAsByte(_frameEdgeColour);
+ s.syncAsByte(_frameEdgeColor);
+
+ for (i = 0; i < 508; i += 4)
+ s.syncAsByte(_scene1550JunkLocations[i + 2]);
+
+ s.syncAsSint16LE(_balloonPosition.x);
+ s.syncAsSint16LE(_balloonPosition.y);
+
+ // Synchronize Flub maze vampire data
+ for (i = 0; i < 18; ++i) {
+ s.syncAsSint16LE(_vampireData[i]._isAlive);
+ s.syncAsSint16LE(_vampireData[i]._shotsRequired);
+ s.syncAsSint16LE(_vampireData[i]._position.x);
+ s.syncAsSint16LE(_vampireData[i]._position.y);
+ }
}
} // end of namespace Ringworld2
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
index d190b6a2a4..92c3d2e24b 100644
--- a/engines/tsage/globals.h
+++ b/engines/tsage/globals.h
@@ -110,7 +110,7 @@ public:
int _interfaceY;
ASoundExt _inventorySound;
- TsAGE2Globals() { _onSelectItem = NULL; }
+ TsAGE2Globals();
virtual void reset();
virtual void synchronize(Serializer &s);
};
@@ -194,33 +194,25 @@ public:
int _safeCombination;
int _gateStatus;
int _greenDay5TalkCtr;
- int _v4CEC4;
int _v4CEC8;
int _v4CECA;
int _v4CECC;
int8 _breakerBoxStatusArr[18];
int _hiddenDoorStatus;
int _nico910State;
- int _v4CEE4;
- int _v4CEE6;
- int _v4CEE8;
+ int _stuart910State;
+ int _nico910Talk;
+ int _stuart910Talk;
int _deziTopic;
int _deathReason;
int _driveFromScene;
int _driveToScene;
- int _v501F8;
- int _v501FA;
- int _v501FC;
- int _v5020C;
- int _v50696;
uint8 _subFlagBitArr1;
uint8 _subFlagBitArr2;
- int _v50CC2;
- int _v50CC4;
- int _v50CC6;
- int _v50CC8;
- int _v51C42;
- int _v51C44;
+ bool _scene410HarrisonTalkFl;
+ int _scene410Action1Count;
+ int _scene410TalkCount;
+ bool _scene410HarrisonMovedFl;
Bookmark _bookmark;
int _mapLocationId;
int _clip1Bullets, _clip2Bullets;
@@ -242,69 +234,69 @@ namespace Ringworld2 {
#define SPEECH_TEXT 1
#define SPEECH_VOICE 2
-#define k5A78C 15
-#define k5A78D 16
-#define k5A790 18
-#define k5A791 17
+class ScannerDialog;
+
+struct VampireData {
+ bool _isAlive;
+ int _shotsRequired;
+ Common::Point _position;
+};
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 _frameEdgeColor;
int _animationCtr;
- int _v565E1;
- int _v565E3;
- int _v565E5;
- int _v565E7;
- int _v565E9;
- int _v565EB;
- int _v565F5;
- int _v565F6;
- int _v565FA;
- int _v5657C;
- byte _v565AE;
- byte _v56605[14];
- int _v56613[76];
- byte _v566A4;
- byte _v566A5;
- int _v566A6;
- byte _v566A3;
- byte _v566A8;
- byte _v566A9;
- byte _v566AA;
- byte _v566AB[1000];
- int _v56A93;
- byte _v56A99;
+ int _electromagnetChangeAmount;
+ int _electromagnetZoom;
+ bool _tractorField;
+ bool _cableAttached;
+ int _foodCount;
+ int _rimLocation;
+ int _rimTransportLocation;
+ byte _stripModifier;
+ byte _spillLocation[14];
+ VampireData _vampireData[18];
+ byte _flubMazeArea;
+ byte _flubMazeEntryDirection;
+ int _maze3800SceneNumb;
+ byte _landerSuitNumber;
+ byte _desertStepsRemaining;
+ byte _desertCorrectDirection;
+ byte _desertPreviousDirection;
+ byte _desertMovements[1000];
+ int _desertWrongDirCtr;
+ byte _balloonAltitude;
int _scene1925CurrLevel; //_v56A9C
- int _v56A9E;
- byte _v56AA0;
- byte _v56AA1;
- int _v56AA2;
- int _v56AA4;
- byte _v56AA6;
- byte _v56AA7;
- byte _v56AA8;
- int _v56AAB;
+ int _walkwaySceneNumber;
+ byte _mirandaJailState;
+ byte _scientistConvIndex;
+ Common::Point _ventCellPos;
+ byte _ductMazePanel1State;
+ byte _ductMazePanel2State;
+ byte _ductMazePanel3State;
int _scene180Mode; // _v575f7
int _v57709;
int _v5780C;
int _v5780E;
int _v57810;
- int _v57C2C;
int _speechSubtitles;
- byte _v565EC[5];
- byte _v565F1[4];
+ Common::Point _s1550PlayerArea[3]; // only used for Quinn and Seeker
+ byte _scannerFrequencies[4];
byte _stripManager_lookupList[12];
+ byte _scene1550JunkLocations[508];
+ Common::Point _balloonPosition;
+
+ 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..fa3ed33302 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -47,7 +47,7 @@ GfxSurface *surfaceGetArea(GfxSurface &src, const Rect &bounds) {
Graphics::Surface destSurface = dest->lockSurface();
byte *srcP = (byte *)srcSurface.getBasePtr(bounds.left, bounds.top);
- byte *destP = (byte *)destSurface.getBasePtr(0, 0);
+ byte *destP = (byte *)destSurface.getPixels();
for (int y = bounds.top; y < bounds.bottom; ++y, srcP += srcSurface.pitch, destP += destSurface.pitch)
Common::copy(srcP, srcP + destSurface.pitch, destP);
@@ -68,15 +68,20 @@ GfxSurface surfaceFromRes(const byte *imgData) {
Rect r(0, 0, READ_LE_UINT16(imgData), READ_LE_UINT16(imgData + 2));
GfxSurface s;
s.create(r.width(), r.height());
- s._centroid.x = READ_LE_UINT16(imgData + 4);
- s._centroid.y = READ_LE_UINT16(imgData + 6);
s._transColor = *(imgData + 8);
- bool rleEncoded = (imgData[9] & 2) != 0;
+ byte flags = imgData[9];
+ s._flags = (g_vm->getGameID() != GType_Ringworld) ? flags : 0;
+
+ bool rleEncoded = (flags & 2) != 0;
+
+ // Figure out the centroid
+ s._centroid.x = READ_LE_UINT16(imgData + 4);
+ s._centroid.y = READ_LE_UINT16(imgData + 6);
const byte *srcP = imgData + 10;
Graphics::Surface destSurface = s.lockSurface();
- byte *destP = (byte *)destSurface.getBasePtr(0, 0);
+ byte *destP = (byte *)destSurface.getPixels();
if (!rleEncoded) {
Common::copy(srcP, srcP + (r.width() * r.height()), destP);
@@ -184,8 +189,9 @@ void Rect::contain(const Rect &r) {
* @percent Scaling percentage
*/
void Rect::resize(const GfxSurface &surface, int xp, int yp, int percent) {
- int xe = surface.getBounds().width() * percent / 100;
- int ye = surface.getBounds().height() * percent / 100;
+ const Rect &bounds = surface.getBounds();
+ int xe = bounds.width() * percent / 100;
+ int ye = bounds.height() * percent / 100;
this->set(0, 0, xe, ye);
if (!right) ++right;
@@ -193,8 +199,13 @@ void Rect::resize(const GfxSurface &surface, int xp, int yp, int percent) {
this->moveTo(xp, yp);
- int xd = surface._centroid.x * percent / 100;
- int yd = surface._centroid.y * percent / 100;
+ int xa = (surface._flags & FRAME_FLIP_CENTROID_X) == 0 ? surface._centroid.x :
+ bounds.width() - (surface._centroid.x + 1);
+ int ya = (surface._flags & FRAME_FLIP_CENTROID_Y) == 0 ? surface._centroid.y :
+ bounds.height() - (surface._centroid.y + 1);
+
+ int xd = xa * percent / 100;
+ int yd = ya * percent / 100;
this->translate(-xd, -yd);
}
@@ -224,6 +235,7 @@ GfxSurface::GfxSurface() : _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
_customSurface = NULL;
_transColor = -1;
_trackDirtyRects = false;
+ _flags = 0;
}
GfxSurface::GfxSurface(const GfxSurface &s) {
@@ -234,9 +246,14 @@ GfxSurface::GfxSurface(const GfxSurface &s) {
}
GfxSurface::~GfxSurface() {
+ clear();
+}
+
+void GfxSurface::clear() {
if (_customSurface) {
_customSurface->free();
delete _customSurface;
+ _customSurface = NULL;
}
}
@@ -289,8 +306,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);
}
}
@@ -308,7 +328,7 @@ void GfxSurface::create(int width, int height) {
}
_customSurface = new Graphics::Surface();
_customSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- Common::fill((byte *)_customSurface->pixels, (byte *)_customSurface->pixels + (width * height), 0);
+ Common::fill((byte *)_customSurface->getPixels(), (byte *)_customSurface->getBasePtr(0, height), 0);
_bounds = Rect(0, 0, width, height);
}
@@ -324,12 +344,7 @@ Graphics::Surface GfxSurface::lockSurface() {
// Setup the returned surface either as one pointing to the same pixels as the source, or
// as a subset of the source one based on the currently set bounds
Graphics::Surface result;
- result.w = _bounds.width();
- result.h = _bounds.height();
- result.pitch = src->pitch;
- result.format = src->format;
- result.pixels = src->getBasePtr(_bounds.left, _bounds.top);
-
+ result.init(_bounds.width(), _bounds.height(), src->pitch, src->getBasePtr(_bounds.left, _bounds.top), src->format);
return result;
}
@@ -355,7 +370,7 @@ void GfxSurface::synchronize(Serializer &s) {
if (_customSurface) {
s.syncAsSint16LE(_customSurface->w);
s.syncAsSint16LE(_customSurface->h);
- s.syncBytes((byte *)_customSurface->pixels, _customSurface->w * _customSurface->h);
+ s.syncBytes((byte *)_customSurface->getPixels(), _customSurface->w * _customSurface->h);
} else {
int zero = 0;
s.syncAsSint16LE(zero);
@@ -372,7 +387,7 @@ void GfxSurface::synchronize(Serializer &s) {
_customSurface = NULL;
} else {
create(w, h);
- s.syncBytes((byte *)_customSurface->pixels, w * h);
+ s.syncBytes((byte *)_customSurface->getPixels(), w * h);
}
}
}
@@ -404,13 +419,14 @@ GfxSurface &GfxSurface::operator=(const GfxSurface &s) {
_bounds = s._bounds;
_centroid = s._centroid;
_transColor = s._transColor;
+ _flags = s._flags;
if (_customSurface) {
// Surface owns the internal data, so replicate it so new surface owns it's own
_customSurface = new Graphics::Surface();
_customSurface->create(s._customSurface->w, s._customSurface->h, Graphics::PixelFormat::createFormatCLUT8());
- const byte *srcP = (const byte *)s._customSurface->getBasePtr(0, 0);
- byte *destP = (byte *)_customSurface->getBasePtr(0, 0);
+ const byte *srcP = (const byte *)s._customSurface->getPixels();
+ byte *destP = (byte *)_customSurface->getPixels();
Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP);
}
@@ -556,9 +572,11 @@ static GfxSurface ResizeSurface(GfxSurface &src, int xSize, int ySize, int trans
}
/**
- * Copys an area from one GfxSurface to another
+ * Copys an area from one GfxSurface to another.
+ *
*/
-void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion) {
+void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds,
+ Region *priorityRegion, const byte *shadowMap) {
GfxSurface srcImage;
if (srcBounds.isEmpty())
return;
@@ -573,7 +591,7 @@ void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Regi
Graphics::Surface destSurface = srcImage.lockSurface();
const byte *srcP = (const byte *)srcSurface.getBasePtr(srcBounds.left, srcBounds.top);
- byte *destP = (byte *)destSurface.pixels;
+ byte *destP = (byte *)destSurface.getPixels();
for (int yp = srcBounds.top; yp < srcBounds.bottom; ++yp, srcP += srcSurface.pitch, destP += destSurface.pitch) {
Common::copy(srcP, srcP + srcBounds.width(), destP);
}
@@ -588,20 +606,24 @@ void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Regi
Graphics::Surface srcSurface = srcImage.lockSurface();
Graphics::Surface destSurface = lockSurface();
+ // Get clipping area
+ Rect clipRect = !_clipRect.isEmpty() ? _clipRect :
+ Rect(0, 0, destSurface.w, destSurface.h);
+
// Adjust bounds to ensure destination will be on-screen
int srcX = 0, srcY = 0;
- if (destBounds.left < 0) {
- srcX = -destBounds.left;
- destBounds.left = 0;
+ if (destBounds.left < clipRect.left) {
+ srcX = clipRect.left - destBounds.left;
+ destBounds.left = clipRect.left;
}
- if (destBounds.top < 0) {
- srcY = -destBounds.top;
- destBounds.top = 0;
+ if (destBounds.top < clipRect.top) {
+ srcY = clipRect.top - destBounds.top;
+ destBounds.top = clipRect.top;
}
- if (destBounds.right > destSurface.w)
- destBounds.right = destSurface.w;
- if (destBounds.bottom > destSurface.h)
- destBounds.bottom = destSurface.h;
+ if (destBounds.right > clipRect.right)
+ destBounds.right = clipRect.right;
+ if (destBounds.bottom > clipRect.bottom)
+ destBounds.bottom = clipRect.bottom;
if (destBounds.isValidRect() && !((destBounds.right < 0) || (destBounds.bottom < 0)
|| (destBounds.left >= destSurface.w) || (destBounds.top >= destSurface.h))) {
@@ -624,8 +646,15 @@ void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Regi
if (!priorityRegion || !priorityRegion->contains(Common::Point(
xp + g_globals->_sceneManager._scene->_sceneBounds.left,
destBounds.top + y + g_globals->_sceneManager._scene->_sceneBounds.top))) {
- if (*tempSrc != src._transColor)
- *tempDest = *tempSrc;
+ if (*tempSrc != src._transColor) {
+ if (shadowMap) {
+ // Using a shadow map, so translate the dest pixel using the mapping array
+ *tempDest = shadowMap[*tempDest];
+ } else {
+ // Otherwise, it's a standard pixel copy
+ *tempDest = *tempSrc;
+ }
+ }
}
++tempSrc;
++tempDest;
@@ -703,6 +732,11 @@ GfxElement::GfxElement() {
_owner = NULL;
_keycode = 0;
_flags = 0;
+
+ _fontNumber = 0;
+ _color1 = 0;
+ _color2 = 0;
+ _color3 = 0;
}
void GfxElement::setDefaults() {
@@ -790,35 +824,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._frameEdgeColor);
+ surface.hLine(tempRect.left + 2, tempRect.bottom - 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColor);
+ surface.vLine(tempRect.left + 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
+ surface.vLine(tempRect.right - 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
+ *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
+
gfxManager.unlockSurface();
+ gfxManager.getSurface().addDirtyRect(tempRect);
} else {
- // Fill dialog content with specified background colour
+ // Fill dialog content with specified background color
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();
}
@@ -1188,8 +1245,9 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
}
void GfxDialog::setPalette() {
- if (g_vm->getGameID() == GType_BlueForce) {
- g_globals->_scenePalette.loadPalette(2);
+ if (g_vm->getGameID() != GType_Ringworld) {
+ if (g_vm->getGameID() == GType_BlueForce)
+ g_globals->_scenePalette.loadPalette(2);
g_globals->_scenePalette.setPalette(0, 1);
g_globals->_scenePalette.setPalette(g_globals->_gfxColors.background, 1);
g_globals->_scenePalette.setPalette(g_globals->_gfxColors.foreground, 1);
@@ -1322,6 +1380,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);
+}
+
/*--------------------------------------------------------------------------*/
@@ -1331,6 +1395,8 @@ GfxFont::GfxFont() {
_bpp = 0;
_fontData = NULL;
_fillFlag = false;
+
+ _gfxManager = nullptr;
}
GfxFont::~GfxFont() {
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index 826f2fef6f..47961dd02a 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -71,6 +71,8 @@ public:
LineSlice(int xStart, int xEnd) { xs = xStart; xe = xEnd; }
};
+enum FrameFlag { FRAME_FLIP_CENTROID_X = 4, FRAME_FLIP_CENTROID_Y = 8 };
+
class GfxSurface {
private:
Graphics::Surface *_customSurface;
@@ -88,6 +90,8 @@ private:
public:
Common::Point _centroid;
int _transColor;
+ Rect _clipRect;
+ byte _flags;
public:
GfxSurface();
GfxSurface(const GfxSurface &s);
@@ -100,10 +104,12 @@ 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; }
- void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion = NULL);
+ void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds,
+ Region *priorityRegion = NULL, const byte *shadowMap = NULL);
void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL) {
copyFrom(src, src.getBounds(), destBounds, priorityRegion);
}
@@ -302,6 +308,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_logic.cpp b/engines/tsage/ringworld/ringworld_logic.cpp
index 0584570ac2..1e9d14cdcf 100644
--- a/engines/tsage/ringworld/ringworld_logic.cpp
+++ b/engines/tsage/ringworld/ringworld_logic.cpp
@@ -270,6 +270,11 @@ bool DisplayObject::performAction(int action) {
SceneArea::SceneArea() {
_savedArea = NULL;
_pt.x = _pt.y = 0;
+
+ _resNum = 0;
+ _rlbNum = 0;
+ _subNum = 0;
+ _actionId = 0;
}
SceneArea::~SceneArea() {
diff --git a/engines/tsage/ringworld/ringworld_scenes1.cpp b/engines/tsage/ringworld/ringworld_scenes1.cpp
index 4d9d565705..5a42bc530d 100644
--- a/engines/tsage/ringworld/ringworld_scenes1.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes1.cpp
@@ -52,52 +52,52 @@ void Scene10::Action1::signal() {
scene->_stripManager.start(11, this, scene);
break;
case 3:
- scene->_object2.hide();
- scene->_object3.hide();
- scene->_object3.setAction(NULL);
- scene->_object4.animate(ANIM_MODE_5, this);
+ scene->_veeshkaHead.hide();
+ scene->_veeshkaRightArm.hide();
+ scene->_veeshkaRightArm.setAction(NULL);
+ scene->_centurion.animate(ANIM_MODE_5, this);
break;
case 4:
case 9:
- scene->_object1.animate(ANIM_MODE_5, this);
+ scene->_veeshkaBody.animate(ANIM_MODE_5, this);
break;
case 5:
- scene->_object2.setStrip(3);
- scene->_object2.setFrame(1);
- scene->_object2.setPosition(Common::Point(240, 51));
- scene->_object2.show();
+ scene->_veeshkaHead.setStrip(3);
+ scene->_veeshkaHead.setFrame(1);
+ scene->_veeshkaHead.setPosition(Common::Point(240, 51));
+ scene->_veeshkaHead.show();
- scene->_object3.setStrip(6);
- scene->_object3.setFrame(1);
- scene->_object3.setPosition(Common::Point(200, 76));
- scene->_object3._numFrames = 20;
- scene->_object3.show();
+ scene->_veeshkaRightArm.setStrip(6);
+ scene->_veeshkaRightArm.setFrame(1);
+ scene->_veeshkaRightArm.setPosition(Common::Point(200, 76));
+ scene->_veeshkaRightArm._numFrames = 20;
+ scene->_veeshkaRightArm.show();
scene->_stripManager.start(12, this, scene);
break;
case 6:
- scene->_object2.hide();
- scene->_object3.hide();
- scene->_object1.animate(ANIM_MODE_6, this);
+ scene->_veeshkaHead.hide();
+ scene->_veeshkaRightArm.hide();
+ scene->_veeshkaBody.animate(ANIM_MODE_6, this);
break;
case 7:
- scene->_object3.show();
- scene->_object3.setStrip2(5);
- scene->_object3._numFrames = 10;
- scene->_object3.setPosition(Common::Point(180, 87));
- scene->_object3.setAction(&scene->_action2);
+ scene->_veeshkaRightArm.show();
+ scene->_veeshkaRightArm.setStrip2(5);
+ scene->_veeshkaRightArm._numFrames = 10;
+ scene->_veeshkaRightArm.setPosition(Common::Point(180, 87));
+ scene->_veeshkaRightArm.setAction(&scene->_action2);
- scene->_object2.setStrip(4);
- scene->_object2.setFrame(1);
- scene->_object2.setPosition(Common::Point(204, 59));
- scene->_object2.show();
+ scene->_veeshkaHead.setStrip(4);
+ scene->_veeshkaHead.setFrame(1);
+ scene->_veeshkaHead.setPosition(Common::Point(204, 59));
+ scene->_veeshkaHead.show();
scene->_stripManager.start(13, this, scene);
break;
case 8:
- scene->_object2.hide();
- scene->_object3.hide();
- scene->_object4.animate(ANIM_MODE_6, this);
+ scene->_veeshkaHead.hide();
+ scene->_veeshkaRightArm.hide();
+ scene->_centurion.animate(ANIM_MODE_6, this);
break;
case 10:
g_globals->_soundHandler.fadeOut(this);
@@ -109,6 +109,7 @@ void Scene10::Action1::signal() {
}
}
+// Move Veeshka's fingers
void Scene10::Action2::signal() {
Scene10 *scene = (Scene10 *)g_globals->_sceneManager._scene;
@@ -117,8 +118,8 @@ void Scene10::Action2::signal() {
setDelay(g_globals->_randomSource.getRandomNumber(179));
break;
case 1:
- scene->_object3.setFrame(1);
- scene->_object3.animate(ANIM_MODE_5, this);
+ scene->_veeshkaRightArm.setFrame(1);
+ scene->_veeshkaRightArm.animate(ANIM_MODE_5, this);
_actionIndex = 0;
break;
}
@@ -145,43 +146,43 @@ void Scene10::postInit(SceneObjectList *OwnerList) {
_stripManager.setCallback(this);
- _object1.postInit();
- _object1.setVisage(10);
- _object1.setPosition(Common::Point(232, 90));
- _object1.fixPriority(1);
-
- _object2.postInit();
- _object2.setVisage(10);
- _object2.setStrip(4);
- _object2.setFrame(1);
- _object2.setPosition(Common::Point(204, 59));
- _object2.fixPriority(198);
-
- _object3.postInit();
- _object3.setVisage(10);
- _object3.setStrip2(5);
- _object3.setPosition(Common::Point(180, 87));
- _object3.fixPriority(196);
- _object3.setAction(&_action2);
-
- _object4.postInit();
- _object4.setVisage(10);
- _object4.setStrip(2);
- _object4.setPosition(Common::Point(0, 209));
- _object4.animate(ANIM_MODE_1, NULL);
-
- _object5.postInit();
- _object5.setVisage(11);
- _object5.setPosition(Common::Point(107, 146));
- _object5.animate(ANIM_MODE_2, NULL);
- _object5._numFrames = 5;
-
- _object6.postInit();
- _object6.setVisage(11);
- _object6.setStrip(2);
- _object6.setPosition(Common::Point(287, 149));
- _object6.animate(ANIM_MODE_2, NULL);
- _object6._numFrames = 5;
+ _veeshkaBody.postInit();
+ _veeshkaBody.setVisage(10);
+ _veeshkaBody.setPosition(Common::Point(232, 90));
+ _veeshkaBody.fixPriority(1);
+
+ _veeshkaHead.postInit();
+ _veeshkaHead.setVisage(10);
+ _veeshkaHead.setStrip(4);
+ _veeshkaHead.setFrame(1);
+ _veeshkaHead.setPosition(Common::Point(204, 59));
+ _veeshkaHead.fixPriority(198);
+
+ _veeshkaRightArm.postInit();
+ _veeshkaRightArm.setVisage(10);
+ _veeshkaRightArm.setStrip2(5);
+ _veeshkaRightArm.setPosition(Common::Point(180, 87));
+ _veeshkaRightArm.fixPriority(196);
+ _veeshkaRightArm.setAction(&_action2);
+
+ _centurion.postInit();
+ _centurion.setVisage(10);
+ _centurion.setStrip(2);
+ _centurion.setPosition(Common::Point(0, 209));
+ _centurion.animate(ANIM_MODE_1, NULL);
+
+ _leftSmoke.postInit();
+ _leftSmoke.setVisage(11);
+ _leftSmoke.setPosition(Common::Point(107, 146));
+ _leftSmoke.animate(ANIM_MODE_2, NULL);
+ _leftSmoke._numFrames = 5;
+
+ _rightSmoke.postInit();
+ _rightSmoke.setVisage(11);
+ _rightSmoke.setStrip(2);
+ _rightSmoke.setPosition(Common::Point(287, 149));
+ _rightSmoke.animate(ANIM_MODE_2, NULL);
+ _rightSmoke._numFrames = 5;
g_globals->_sceneManager._scene->_sceneBounds.contain(g_globals->_sceneManager._scene->_backgroundBounds);
g_globals->_sceneOffset.x = (g_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
@@ -193,14 +194,14 @@ void Scene10::postInit(SceneObjectList *OwnerList) {
void Scene10::stripCallback(int v) {
switch (v) {
case 1:
- _object2.animate(ANIM_MODE_7, -1, NULL);
+ _veeshkaHead.animate(ANIM_MODE_7, -1, NULL);
break;
case 2:
- _object2.animate(ANIM_MODE_NONE);
+ _veeshkaHead.animate(ANIM_MODE_NONE);
break;
case 3:
- _object2.animate(ANIM_MODE_7, -1, NULL);
- _object3.animate(ANIM_MODE_5, NULL);
+ _veeshkaHead.animate(ANIM_MODE_7, -1, NULL);
+ _veeshkaRightArm.animate(ANIM_MODE_5, NULL);
break;
default:
break;
@@ -227,13 +228,13 @@ void Scene15::Action1::signal() {
case 2: {
SceneItem::display(15, 1, SET_Y, 20, SET_FONT, 2, SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 7,
SET_WIDTH, 320, SET_KEEP_ONSCREEN, 1, LIST_END);
- scene->_object1.postInit();
- scene->_object1.setVisage(15);
- scene->_object1.setPosition(Common::Point(160, -10));
- scene->_object1.animate(ANIM_MODE_2, NULL);
+ scene->_ship.postInit();
+ scene->_ship.setVisage(15);
+ scene->_ship.setPosition(Common::Point(160, -10));
+ scene->_ship.animate(ANIM_MODE_2, NULL);
Common::Point pt(160, 100);
NpcMover *mover = new NpcMover();
- scene->_object1.addMover(mover, &pt, this);
+ scene->_ship.addMover(mover, &pt, this);
scene->_soundHandler.play(7);
break;
}
@@ -247,8 +248,8 @@ void Scene15::Action1::signal() {
void Scene15::Action1::dispatch() {
Scene15 *scene = (Scene15 *)g_globals->_sceneManager._scene;
- if (scene->_object1._position.y < 100)
- scene->_object1.changeZoom(100 - scene->_object1._position.y);
+ if (scene->_ship._position.y < 100)
+ scene->_ship.changeZoom(100 - scene->_ship._position.y);
Action::dispatch();
}
@@ -307,9 +308,9 @@ void Scene20::Action2::signal() {
Common::Point pt(455, 77);
g_globals->_player.addMover(mover, &pt, this);
ObjectMover2 *mover2 = new ObjectMover2();
- scene->_SceneObjectExt.addMover(mover2, 5, 10, &g_globals->_player);
+ scene->_assassinShip1.addMover(mover2, 5, 10, &g_globals->_player);
ObjectMover2 *mover3 = new ObjectMover2();
- scene->_sceneObject3.addMover(mover3, 10, 15, &g_globals->_player);
+ scene->_assassinShip2.addMover(mover3, 10, 15, &g_globals->_player);
break;
}
case 3: {
@@ -369,9 +370,9 @@ void Scene20::Action3::signal() {
Common::Point pt(615, 81);
g_globals->_player.addMover(npcMover, &pt, this);
ObjectMover2 *mover1 = new ObjectMover2();
- scene->_SceneObjectExt.addMover(mover1, 5, 10, &g_globals->_player);
+ scene->_assassinShip1.addMover(mover1, 5, 10, &g_globals->_player);
ObjectMover2 *mover2 = new ObjectMover2();
- scene->_sceneObject3.addMover(mover2, 20, 25, &g_globals->_player);
+ scene->_assassinShip2.addMover(mover2, 20, 25, &g_globals->_player);
break;
}
case 2: {
@@ -382,8 +383,8 @@ void Scene20::Action3::signal() {
}
case 3: {
g_globals->_player._moveDiff = Common::Point(10, 10);
- scene->_SceneObjectExt._moveDiff = Common::Point(10, 10);
- scene->_sceneObject3._moveDiff = Common::Point(10, 10);
+ scene->_assassinShip1._moveDiff = Common::Point(10, 10);
+ scene->_assassinShip2._moveDiff = Common::Point(10, 10);
npcMover = new NpcMover();
Common::Point pt(445, 132);
g_globals->_player.addMover(npcMover, &pt, this);
@@ -427,73 +428,73 @@ void Scene20::Action4::signal() {
Common::Point pt(486, 134);
g_globals->_player.addMover(npcMover, &pt, this);
ObjectMover2 *mover1 = new ObjectMover2();
- scene->_SceneObjectExt.addMover(mover1, 20, 35, &g_globals->_player);
+ scene->_assassinShip1.addMover(mover1, 20, 35, &g_globals->_player);
break;
}
case 2: {
g_globals->_player._moveDiff = Common::Point(12, 12);
- scene->_SceneObjectExt._moveDiff = Common::Point(12, 12);
+ scene->_assassinShip1._moveDiff = Common::Point(12, 12);
NpcMover *mover1 = new NpcMover();
Common::Point pt(486, 134);
- scene->_sceneObject3.addMover(mover1, &pt, this);
+ scene->_assassinShip2.addMover(mover1, &pt, this);
NpcMover *mover2 = new NpcMover();
pt = Common::Point(-15, 134);
g_globals->_player.addMover(mover2, &pt, NULL);
NpcMover *mover3 = new NpcMover();
pt = Common::Point(-15, 134);
- scene->_SceneObjectExt.addMover(mover3, &pt, NULL);
+ scene->_assassinShip1.addMover(mover3, &pt, NULL);
break;
}
case 3: {
- scene->_sceneObject3._moveDiff = Common::Point(20, 20);
+ scene->_assassinShip2._moveDiff = Common::Point(20, 20);
npcMover = new NpcMover();
Common::Point pt(320, 134);
- scene->_sceneObject3.addMover(npcMover, &pt, this);
+ scene->_assassinShip2.addMover(npcMover, &pt, this);
break;
}
case 4: {
scene->_sound.play(28);
- scene->_sceneObject4.postInit();
- scene->_sceneObject4.setVisage(21);
- scene->_sceneObject4.setStrip(3);
- scene->_sceneObject4.setPosition(Common::Point(scene->_sceneObject3._position.x - 36,
- scene->_sceneObject3._position.y - 1));
- scene->_sceneObject4._moveDiff.x = 48;
+ scene->_laserShot1.postInit();
+ scene->_laserShot1.setVisage(21);
+ scene->_laserShot1.setStrip(3);
+ Common::Point pt = Common::Point(scene->_assassinShip2._position.x - 36, scene->_assassinShip2._position.y - 1);
+ scene->_laserShot1.setPosition(pt);
+ scene->_laserShot1._moveDiff.x = 48;
ObjectMover3 *mover = new ObjectMover3();
- scene->_sceneObject4.addMover(mover, &scene->_SceneObjectExt, 4, this);
+ scene->_laserShot1.addMover(mover, &scene->_assassinShip1, 4, this);
break;
}
case 5: {
scene->_sound.play(42);
- scene->_sceneObject4.remove();
- scene->_SceneObjectExt.setVisage(21);
- scene->_SceneObjectExt.setStrip(1);
- scene->_SceneObjectExt.setFrame(1);
- scene->_SceneObjectExt.animate(ANIM_MODE_5, NULL);
+ scene->_laserShot1.remove();
+ scene->_assassinShip1.setVisage(21);
+ scene->_assassinShip1.setStrip(1);
+ scene->_assassinShip1.setFrame(1);
+ scene->_assassinShip1.animate(ANIM_MODE_5, NULL);
- scene->_SceneObjectExt._moveDiff.x = 4;
+ scene->_assassinShip1._moveDiff.x = 4;
NpcMover *mover1 = new NpcMover();
- Common::Point pt(scene->_SceneObjectExt._position.x - 12, scene->_SceneObjectExt._position.y + 5);
- scene->_SceneObjectExt.addMover(mover1, &pt, NULL);
+ Common::Point pt(scene->_assassinShip1._position.x - 12, scene->_assassinShip1._position.y + 5);
+ scene->_assassinShip1.addMover(mover1, &pt, NULL);
- scene->_sceneObject5.postInit();
- scene->_sceneObject5.setVisage(21);
- scene->_sceneObject5.setStrip(3);
- scene->_sceneObject5.setPosition(Common::Point(scene->_sceneObject3._position.x - 36,
- scene->_sceneObject3._position.y - 1));
- scene->_sceneObject5._moveDiff.x = 48;
+ scene->_laserShot2.postInit();
+ scene->_laserShot2.setVisage(21);
+ scene->_laserShot2.setStrip(3);
+ pt = Common::Point(scene->_assassinShip2._position.x - 36, scene->_assassinShip2._position.y - 1);
+ scene->_laserShot2.setPosition(pt);
+ scene->_laserShot2._moveDiff.x = 48;
ObjectMover3 *mover = new ObjectMover3();
- scene->_sceneObject5.addMover(mover, &g_globals->_player, 4, this);
+ scene->_laserShot2.addMover(mover, &g_globals->_player, 4, this);
break;
}
case 6: {
scene->_sound.play(42);
- scene->_SceneObjectExt.setStrip(2);
- scene->_SceneObjectExt.animate(ANIM_MODE_2, NULL);
+ scene->_assassinShip1.setStrip(2);
+ scene->_assassinShip1.animate(ANIM_MODE_2, NULL);
- scene->_sceneObject5.remove();
+ scene->_laserShot2.remove();
g_globals->_player.setVisage(21);
g_globals->_player.setStrip(1);
g_globals->_player.setFrame(1);
@@ -539,18 +540,18 @@ void Scene20::postInit(SceneObjectList *OwnerList) {
g_globals->_player._moveDiff = Common::Point(10, 10);
g_globals->_player.animate(ANIM_MODE_1, NULL);
- _SceneObjectExt.postInit();
- _SceneObjectExt.setVisage(20);
- _SceneObjectExt.setPosition(Common::Point(400, 69));
- _SceneObjectExt.animate(ANIM_MODE_1, NULL);
+ _assassinShip1.postInit();
+ _assassinShip1.setVisage(20);
+ _assassinShip1.setPosition(Common::Point(400, 69));
+ _assassinShip1.animate(ANIM_MODE_1, NULL);
- _sceneObject3.postInit();
- _sceneObject3.setVisage(20);
- _sceneObject3.setPosition(Common::Point(395, 69));
- _sceneObject3.animate(ANIM_MODE_1, NULL);
+ _assassinShip2.postInit();
+ _assassinShip2.setVisage(20);
+ _assassinShip2.setPosition(Common::Point(395, 69));
+ _assassinShip2.animate(ANIM_MODE_1, NULL);
- _SceneObjectExt._moveDiff = Common::Point(10, 10);
- _sceneObject3._moveDiff = Common::Point(10, 10);
+ _assassinShip1._moveDiff = Common::Point(10, 10);
+ _assassinShip2._moveDiff = Common::Point(10, 10);
g_globals->_soundHandler.play(20);
_sound.play(21);
_sound.holdAt(true);
@@ -567,16 +568,16 @@ void Scene20::postInit(SceneObjectList *OwnerList) {
g_globals->_player.fixPriority(50);
g_globals->_player.animate(ANIM_MODE_1, NULL);
- _SceneObjectExt.postInit();
- _SceneObjectExt.setVisage(20);
- _SceneObjectExt.setPosition(Common::Point(583, 79));
- _SceneObjectExt.animate(ANIM_MODE_1, NULL);
+ _assassinShip1.postInit();
+ _assassinShip1.setVisage(20);
+ _assassinShip1.setPosition(Common::Point(583, 79));
+ _assassinShip1.animate(ANIM_MODE_1, NULL);
- _sceneObject3.postInit();
- _sceneObject3.setVisage(20);
- _sceneObject3.setStrip2(2);
- _sceneObject3.setPosition(Common::Point(595, 79));
- _sceneObject3.animate(ANIM_MODE_1, NULL);
+ _assassinShip2.postInit();
+ _assassinShip2.setVisage(20);
+ _assassinShip2.setStrip2(2);
+ _assassinShip2.setPosition(Common::Point(595, 79));
+ _assassinShip2.animate(ANIM_MODE_1, NULL);
if ((g_globals->getFlag(120) && g_globals->getFlag(116)) ||
(g_globals->getFlag(117) && g_globals->getFlag(119))) {
@@ -584,10 +585,10 @@ void Scene20::postInit(SceneObjectList *OwnerList) {
setAction(&_action3);
} else if (g_globals->getFlag(104)) {
_sceneMode = 21;
- setAction(&_sequenceManager, this, 21, &g_globals->_player, &_SceneObjectExt, NULL);
+ setAction(&_sequenceManager, this, 21, &g_globals->_player, &_assassinShip1, NULL);
} else {
// Failed evasion
- _sceneObject3._moveDiff = Common::Point(8, 8);
+ _assassinShip2._moveDiff = Common::Point(8, 8);
setAction(&_action4);
}
_sceneBounds.center(g_globals->_player._position.x, g_globals->_player._position.y);
@@ -626,26 +627,37 @@ void Scene20::signal() {
*--------------------------------------------------------------------------*/
void Scene30::BeamObject::doAction(int action) {
- if (action == OBJECT_SCANNER)
+ switch (action) {
+ case OBJECT_SCANNER:
display2(30, 14);
- else if (action == CURSOR_LOOK)
+ break;
+ case CURSOR_LOOK:
display2(30, 2);
- else if (action == CURSOR_USE) {
+ break;
+ case CURSOR_USE: {
Scene30 *parent = (Scene30 *)g_globals->_sceneManager._scene;
parent->setAction(&parent->_beamAction);
- } else
+ }
+ break;
+ default:
SceneObject::doAction(action);
+ }
}
void Scene30::DoorObject::doAction(int action) {
- if (action == OBJECT_SCANNER)
+ switch (action) {
+ case OBJECT_SCANNER:
display2(30, 13);
- else if (action == CURSOR_LOOK)
+ break;
+ case CURSOR_LOOK:
display2(30, 1);
- else if (action == CURSOR_USE)
+ break;
+ case CURSOR_USE:
display2(30, 7);
- else
+ break;
+ default:
SceneObject::doAction(action);
+ }
}
void Scene30::BeamAction::signal() {
@@ -963,16 +975,16 @@ void Scene40::Action1::signal() {
scene->_doorway.hide();
scene->_dyingKzin.setPosition(Common::Point(296, 62));
g_globals->_player.animate(ANIM_MODE_5, NULL);
- scene->_object1.setVisage(43);
- scene->_object1.setStrip(3);
- scene->_object1.animate(ANIM_MODE_5, NULL);
- scene->_object2.hide();
- scene->_object3.hide();
+ scene->_seeker.setVisage(43);
+ scene->_seeker.setStrip(3);
+ scene->_seeker.animate(ANIM_MODE_5, NULL);
+ scene->_seekerTail.hide();
+ scene->_seekerHand.hide();
scene->_stripManager.start(45, this);
break;
case 4:
- scene->_object2.remove();
- scene->_object3.remove();
+ scene->_seekerTail.remove();
+ scene->_seekerHand.remove();
scene->_assassin.setVisage(42);
scene->_assassin.setStrip(2);
scene->_assassin.setFrame(1);
@@ -1049,10 +1061,10 @@ void Scene40::Action1::signal() {
break;
case 15:
g_globals->_player.disableControl();
- scene->_object1.setVisage(40);
- scene->_object1.setStrip(4);
- scene->_object1.setFrame(1);
- scene->_object1.animate(ANIM_MODE_5, NULL);
+ scene->_seeker.setVisage(40);
+ scene->_seeker.setStrip(4);
+ scene->_seeker.setFrame(1);
+ scene->_seeker.animate(ANIM_MODE_5, NULL);
g_globals->_player.setVisage(40);
g_globals->_player.setStrip(2);
g_globals->_player.setFrame(1);
@@ -1122,13 +1134,13 @@ void Scene40::Action2::signal() {
}
case 6: {
g_globals->_player.setStrip(7);
- scene->_object1.setVisage(2806);
- scene->_object1.animate(ANIM_MODE_1, NULL);
+ scene->_seeker.setVisage(2806);
+ scene->_seeker.animate(ANIM_MODE_1, NULL);
SceneObjectWrapper *wrapper = new SceneObjectWrapper();
- scene->_object1.setObjectWrapper(wrapper);
+ scene->_seeker.setObjectWrapper(wrapper);
Common::Point pt(200, 190);
NpcMover *mover = new NpcMover();
- scene->_object1.addMover(mover, &pt, this);
+ scene->_seeker.addMover(mover, &pt, this);
break;
}
case 7:
@@ -1137,12 +1149,12 @@ void Scene40::Action2::signal() {
case 8: {
Common::Point pt(170, 260);
NpcMover *mover = new NpcMover();
- scene->_object1.addMover(mover, &pt, this);
+ scene->_seeker.addMover(mover, &pt, this);
break;
}
case 9:
scene->_dyingKzin.setAction(&scene->_action7);
- scene->_object1.remove();
+ scene->_seeker.remove();
g_globals->_stripNum = 88;
g_globals->_events.setCursor(CURSOR_WALK);
g_globals->_player.enableControl();
@@ -1202,6 +1214,7 @@ void Scene40::Action4::signal() {
}
}
+// Animate the tail of Seeker, with random pauses
void Scene40::Action5::signal() {
Scene40 *scene = (Scene40 *)g_globals->_sceneManager._scene;
@@ -1210,7 +1223,7 @@ void Scene40::Action5::signal() {
setDelay(g_globals->_randomSource.getRandomNumber(119) + 120);
break;
case 1:
- scene->_object2.animate(ANIM_MODE_8, 1, this);
+ scene->_seekerTail.animate(ANIM_MODE_8, 1, this);
_actionIndex = 0;
}
}
@@ -1220,17 +1233,17 @@ void Scene40::Action6::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_object1.postInit();
- scene->_object1.setVisage(16);
- scene->_object1.setStrip2(6);
- scene->_object1._moveDiff = Common::Point(40, 40);
- scene->_object1.setPosition(Common::Point(313, 53));
- scene->_object1._moveRate = 60;
+ scene->_seeker.postInit();
+ scene->_seeker.setVisage(16);
+ scene->_seeker.setStrip2(6);
+ scene->_seeker._moveDiff = Common::Point(40, 40);
+ scene->_seeker.setPosition(Common::Point(313, 53));
+ scene->_seeker._moveRate = 60;
Common::Point pt(141, 194);
NpcMover *mover = new NpcMover();
- scene->_object1.addMover(mover, &pt, NULL);
- scene->_object1.animate(ANIM_MODE_5, NULL);
+ scene->_seeker.addMover(mover, &pt, NULL);
+ scene->_seeker.animate(ANIM_MODE_5, NULL);
scene->_doorway.postInit();
scene->_doorway.setVisage(46);
@@ -1260,21 +1273,21 @@ void Scene40::Action7::signal() {
setDelay(g_globals->_randomSource.getRandomNumber(499) + 500);
break;
case 1:
- scene->_object7.postInit();
- scene->_object7.setVisage(46);
+ scene->_leftEntrance.postInit();
+ scene->_leftEntrance.setVisage(46);
if (g_globals->_randomSource.getRandomNumber(32767) >= 16384) {
- scene->_object7.setStrip(3);
- scene->_object7.setPosition(Common::Point(15, 185));
+ scene->_leftEntrance.setStrip(3);
+ scene->_leftEntrance.setPosition(Common::Point(15, 185));
} else {
- scene->_object7.setPosition(Common::Point(305, 61));
- scene->_object7.setFrame(15);
+ scene->_leftEntrance.setPosition(Common::Point(305, 61));
+ scene->_leftEntrance.setFrame(15);
}
- scene->_object7.animate(ANIM_MODE_5, this);
+ scene->_leftEntrance.animate(ANIM_MODE_5, this);
scene->_soundHandler.play(25);
break;
case 2:
- scene->_object7.remove();
+ scene->_leftEntrance.remove();
_actionIndex = 0;
setDelay(60);
break;
@@ -1465,12 +1478,12 @@ void Scene40::Item6::doAction(int action) {
/*--------------------------------------------------------------------------*/
Scene40::Scene40() :
- _item1(2, OBJECT_SCANNER, 40, 24, OBJECT_STUNNER, 40, 25, CURSOR_LOOK, 40, 7, CURSOR_USE, 40, 16, LIST_END),
- _item3(5, OBJECT_SCANNER, 40, 28, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 2, CURSOR_USE, 40, 30, LIST_END),
- _item4(6, OBJECT_SCANNER, 40, 31, OBJECT_STUNNER, 40, 32, CURSOR_LOOK, 40, 5, CURSOR_USE, 40, 33, LIST_END),
- _item5(0, CURSOR_LOOK, 40, 11, LIST_END),
- _item7(4, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
- _item8(8, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_LOOK, 40, 3, CURSOR_USE, 40, 41, LIST_END) {
+ _ball(2, OBJECT_SCANNER, 40, 24, OBJECT_STUNNER, 40, 25, CURSOR_LOOK, 40, 7, CURSOR_USE, 40, 16, LIST_END),
+ _window(5, OBJECT_SCANNER, 40, 28, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 2, CURSOR_USE, 40, 30, LIST_END),
+ _entrance(6, OBJECT_SCANNER, 40, 31, OBJECT_STUNNER, 40, 32, CURSOR_LOOK, 40, 5, CURSOR_USE, 40, 33, LIST_END),
+ _background(0, CURSOR_LOOK, 40, 11, LIST_END),
+ _emerald(4, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
+ _tree(8, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_LOOK, 40, 3, CURSOR_USE, 40, 41, LIST_END) {
}
void Scene40::postInit(SceneObjectList *OwnerList) {
@@ -1489,7 +1502,7 @@ void Scene40::postInit(SceneObjectList *OwnerList) {
_speakerGameText._color1 = 9;
_speakerGameText.setTextPos(Common::Point(160, 30));
_speakerQText._npc = &g_globals->_player;
- _speakerSText._npc = &_object1;
+ _speakerSText._npc = &_seeker;
g_globals->_player.postInit();
g_globals->_player.setVisage(0);
@@ -1502,23 +1515,24 @@ void Scene40::postInit(SceneObjectList *OwnerList) {
g_globals->_soundHandler.play(24);
g_globals->_player.setVisage(43);
- _object1.postInit();
- _object1.setVisage(41);
- _object1.setPosition(Common::Point(105, 220));
- _object2.postInit();
- _object2.setVisage(41);
- _object2.setStrip(6);
- _object2.fixPriority(200);
- _object2.setPosition(Common::Point(94, 189));
- _object2.setAction(&_action5);
-
- _object3.postInit();
- _object3.setVisage(41);
- _object3.setStrip(5);
- _object3.fixPriority(205);
- _object3.setPosition(Common::Point(110, 186));
- _object3._numFrames = 2;
- _object3.animate(ANIM_MODE_8, NULL, NULL);
+ _seeker.postInit();
+ _seeker.setVisage(41);
+ _seeker.setPosition(Common::Point(105, 220));
+
+ _seekerTail.postInit();
+ _seekerTail.setVisage(41);
+ _seekerTail.setStrip(6);
+ _seekerTail.fixPriority(200);
+ _seekerTail.setPosition(Common::Point(94, 189));
+ _seekerTail.setAction(&_action5);
+
+ _seekerHand.postInit();
+ _seekerHand.setVisage(41);
+ _seekerHand.setStrip(5);
+ _seekerHand.fixPriority(205);
+ _seekerHand.setPosition(Common::Point(110, 186));
+ _seekerHand._numFrames = 2;
+ _seekerHand.animate(ANIM_MODE_8, NULL, NULL);
_assassin.postInit();
_assassin.setPosition(Common::Point(-40, 191));
@@ -1563,12 +1577,12 @@ void Scene40::postInit(SceneObjectList *OwnerList) {
setAction(&_action4);
}
- _item5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
- _item6._sceneRegionId = 3;
- _item2._sceneRegionId = 7;
+ _background.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _pedestal._sceneRegionId = 3;
+ _statue._sceneRegionId = 7;
- g_globals->_sceneItems.addItems(&_dyingKzin, &_item8, &_item1, &_item2, &_item3, &_item4,
- &_item6, &_item7, &_item5, NULL);
+ g_globals->_sceneItems.addItems(&_dyingKzin, &_tree, &_ball, &_statue, &_window, &_entrance,
+ &_pedestal, &_emerald, &_background, NULL);
}
void Scene40::signal() {
@@ -1691,7 +1705,7 @@ void Scene50::Object1::doAction(int action) {
}
}
-void Scene50::Object2::doAction(int action) {
+void Scene50::LeftFlyCycle::doAction(int action) {
Scene50 *scene = (Scene50 *)g_globals->_sceneManager._scene;
switch (action) {
@@ -1715,7 +1729,7 @@ void Scene50::Object2::doAction(int action) {
}
}
-void Scene50::Object3::doAction(int action) {
+void Scene50::CenterFlyCycle::doAction(int action) {
Scene50 *scene = (Scene50 *)g_globals->_sceneManager._scene;
switch (action) {
@@ -1743,7 +1757,7 @@ void Scene50::Object3::doAction(int action) {
}
}
-void Scene50::Object4::doAction(int action) {
+void Scene50::RightFlyCycle::doAction(int action) {
Scene50 *scene = (Scene50 *)g_globals->_sceneManager._scene;
switch (action) {
@@ -1772,12 +1786,13 @@ void Scene50::Object4::doAction(int action) {
/*--------------------------------------------------------------------------*/
Scene50::Scene50() :
- _item0(0, CURSOR_LOOK, 50, 3, LIST_END),
+ _background(0, CURSOR_LOOK, 50, 3, LIST_END),
_item1(0, OBJECT_SCANNER, 50, 15, CURSOR_USE, 50, 16, CURSOR_LOOK, 50, 3, LIST_END),
- _item2(0, CURSOR_LOOK, 50, 7, LIST_END),
- _item3(8, OBJECT_STUNNER, 50, 14, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 50, 3, LIST_END),
- _item4(9, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_USE, 40, 41, CURSOR_LOOK, 50, 5, LIST_END),
- _item5(10, OBJECT_SCANNER, 50, 17, OBJECT_STUNNER, 50, 18, CURSOR_LOOK, 50, 6, CURSOR_USE, 30, 8, LIST_END) {
+ _entrance(0, CURSOR_LOOK, 50, 7, LIST_END),
+ // The original was using dialog 50/3 for CURSOR_LOOK, which is too generic.
+ _bulwark(8, OBJECT_STUNNER, 50, 14, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 30, 0, LIST_END),
+ _tree(9, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_USE, 40, 41, CURSOR_LOOK, 50, 5, LIST_END),
+ _flagstones(10, OBJECT_SCANNER, 50, 17, OBJECT_STUNNER, 50, 18, CURSOR_LOOK, 50, 6, CURSOR_USE, 30, 8, LIST_END) {
_doorwayRect = Rect(80, 108, 160, 112);
}
@@ -1806,25 +1821,25 @@ void Scene50::postInit(SceneObjectList *OwnerList) {
g_globals->_player.setPosition(Common::Point(270, 143));
}
- _object2.postInit();
- _object2.setVisage(2331);
- _object2.setStrip(6);
- _object2.setPosition(Common::Point(136, 192));
- _object2.fixPriority(200);
+ _leftFlyCycle.postInit();
+ _leftFlyCycle.setVisage(2331);
+ _leftFlyCycle.setStrip(6);
+ _leftFlyCycle.setPosition(Common::Point(136, 192));
+ _leftFlyCycle.fixPriority(200);
- _object3.postInit();
- _object3.setVisage(2337);
- _object3.setStrip(6);
- _object3.setPosition(Common::Point(260, 180));
- _object3.fixPriority(200);
+ _centerFlyCycle.postInit();
+ _centerFlyCycle.setVisage(2337);
+ _centerFlyCycle.setStrip(6);
+ _centerFlyCycle.setPosition(Common::Point(260, 180));
+ _centerFlyCycle.fixPriority(200);
- _object4.postInit();
- _object4.setVisage(2331);
- _object4.setStrip(6);
- _object4.setPosition(Common::Point(295, 144));
- _object4.fixPriority(178);
+ _rightFlyCycle.postInit();
+ _rightFlyCycle.setVisage(2331);
+ _rightFlyCycle.setStrip(6);
+ _rightFlyCycle.setPosition(Common::Point(295, 144));
+ _rightFlyCycle.fixPriority(178);
- g_globals->_sceneItems.addItems(&_object2, &_object3, &_object4, NULL);
+ g_globals->_sceneItems.addItems(&_leftFlyCycle, &_centerFlyCycle, &_rightFlyCycle, NULL);
if (!g_globals->getFlag(101)) {
g_globals->_player.disableControl();
@@ -1840,8 +1855,8 @@ void Scene50::postInit(SceneObjectList *OwnerList) {
}
}
- _item0.setBounds(Rect(200, 0, 320, 200));
- g_globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item0, NULL);
+ _background.setBounds(Rect(0, 0, 320, 200));
+ g_globals->_sceneItems.addItems(&_bulwark, &_tree, &_flagstones, &_background, NULL);
}
void Scene50::signal() {
@@ -1928,8 +1943,8 @@ void Scene60::Action1::signal() {
scene->_controlButton.remove();
scene->_slaveButton.remove();
scene->_masterButton.remove();
- scene->_item1.remove();
- scene->_item2.remove();
+ scene->_diskDrive.remove();
+ scene->_dashboard.remove();
scene->_nextButton.postInit();
scene->_nextButton.setVisage(65);
@@ -2030,11 +2045,11 @@ void Scene60::Action2::signal() {
/*--------------------------------------------------------------------------*/
void Scene60::PrevObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 16);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
animate(ANIM_MODE_8, 1, NULL);
if (scene->_action1.getActionIndex() > 5) {
@@ -2048,11 +2063,11 @@ void Scene60::PrevObject::doAction(int action) {
}
void Scene60::NextObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 17);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
animate(ANIM_MODE_8, 1, NULL);
if (scene->_action1.getActionIndex() < 8) {
@@ -2065,11 +2080,11 @@ void Scene60::NextObject::doAction(int action) {
}
void Scene60::ExitObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 18);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
scene->_soundHandler3.play(36);
animate(ANIM_MODE_8, 1, NULL);
scene->_nextButton.remove();
@@ -2111,11 +2126,11 @@ void Scene60::ExitObject::doAction(int action) {
if (scene->_masterButton._state)
scene->_masterButton.setFrame(2);
- g_globals->_sceneItems.push_front(&scene->_item1);
+ g_globals->_sceneItems.push_front(&scene->_diskDrive);
g_globals->_sceneItems.push_front(&scene->_controlButton);
g_globals->_sceneItems.push_front(&scene->_slaveButton);
g_globals->_sceneItems.push_front(&scene->_masterButton);
- g_globals->_sceneItems.push_back(&scene->_item2);
+ g_globals->_sceneItems.push_back(&scene->_dashboard);
g_globals->gfxManager()._font.setFontNumber(2);
g_globals->_sceneText._fontNumber = 2;
@@ -2130,11 +2145,11 @@ void Scene60::ExitObject::doAction(int action) {
}
void Scene60::MessageObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 9);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
scene->_action1.setDelay(1);
g_globals->setFlag(83);
} else {
@@ -2143,11 +2158,11 @@ void Scene60::MessageObject::doAction(int action) {
}
void Scene60::ControlObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 11);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
if (_animateMode == ANIM_MODE_NONE)
SceneItem::display2(60, 14);
else if (!scene->_slaveButton._state) {
@@ -2164,11 +2179,11 @@ void Scene60::ControlObject::doAction(int action) {
}
void Scene60::SlaveObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 8);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
if (scene->_masterButton._state)
scene->_sceneMode = 19;
else if (_state) {
@@ -2194,11 +2209,11 @@ void Scene60::SlaveObject::doAction(int action) {
}
void Scene60::MasterObject::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 7);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
if (!scene->_controlButton._animateMode)
scene->_sceneMode = 14;
else if (scene->_slaveButton._state)
@@ -2226,11 +2241,11 @@ void Scene60::MasterObject::doAction(int action) {
}
void Scene60::FloppyDrive::doAction(int action) {
- Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
-
if (action == CURSOR_LOOK) {
SceneItem::display2(60, 13);
} else if (action == CURSOR_USE) {
+ Scene60 *scene = (Scene60 *)g_globals->_sceneManager._scene;
+
g_globals->setFlag(!g_globals->_stripNum ? 118 : 121);
scene->setAction(&scene->_action1);
} else {
@@ -2273,6 +2288,7 @@ void Scene60::Item1::doAction(int action) {
} else {
scene->setAction(&scene->_action2);
}
+ break;
default:
SceneHotspot::doAction(action);
break;
@@ -2299,11 +2315,11 @@ void Scene60::Item::doAction(int action) {
/*--------------------------------------------------------------------------*/
Scene60::Scene60() :
- _item2(0, 12, 12),
- _item3(8, 22, 23),
- _item4(9, 24, 25),
- _item5(10, 26, 27),
- _item6(11, 28, 29) {
+ _dashboard(0, 12, 12),
+ _intercomm(8, 22, 23),
+ _viewScreen(9, 24, 25),
+ _speedControl(10, 26, 27),
+ _speaker(11, 28, 29) {
}
void Scene60::postInit(SceneObjectList *OwnerList) {
@@ -2344,8 +2360,8 @@ void Scene60::postInit(SceneObjectList *OwnerList) {
setAction(&_sequenceManager, this, 61, NULL);
}
- _item1.setBounds(Rect(130, 55, 174, 70));
- _item2.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _diskDrive.setBounds(Rect(130, 55, 174, 70));
+ _dashboard.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
if (g_globals->_stripNum == 0) {
if (g_globals->getFlag(117)) {
@@ -2418,8 +2434,7 @@ void Scene60::postInit(SceneObjectList *OwnerList) {
}
}
- g_globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item6,
- &_item1, &_item2, NULL);
+ g_globals->_sceneItems.addItems(&_intercomm, &_viewScreen, &_speedControl, &_speaker, &_diskDrive, &_dashboard, NULL);
}
void Scene60::signal() {
@@ -2473,11 +2488,11 @@ void Scene90::Action1::signal() {
case 3: {
Common::Point pt(278, 191);
NpcMover *mover = new NpcMover();
- scene->_object2.addMover(mover, &pt, this);
+ scene->_guard.addMover(mover, &pt, this);
break;
}
case 4:
- scene->_object2.setStrip(3);
+ scene->_guard.setStrip(3);
setDelay(2);
break;
case 5:
@@ -2491,36 +2506,36 @@ void Scene90::Action1::signal() {
}
break;
case 6:
- scene->_object2.animate(ANIM_MODE_NONE);
+ scene->_guard.animate(ANIM_MODE_NONE);
g_globals->_player._uiEnabled = true;
break;
case 7:
- scene->_object2.animate(ANIM_MODE_NONE);
+ scene->_guard.animate(ANIM_MODE_NONE);
g_globals->_soundHandler.play(56);
- scene->_object3.animate(ANIM_MODE_5, this);
+ scene->_headGate.animate(ANIM_MODE_5, this);
break;
case 8: {
Common::Point pt(215, 127);
PlayerMover *mover = new PlayerMover();
- scene->_object5.addMover(mover, &pt, this);
+ scene->_quinnShip.addMover(mover, &pt, this);
break;
}
case 9: {
Common::Point pt1(215, 127);
PlayerMover *mover1 = new PlayerMover();
- scene->_object1.addMover(mover1, &pt1, this);
+ scene->_seekerShip.addMover(mover1, &pt1, this);
Common::Point pt2(86, 62);
PlayerMover *mover2 = new PlayerMover();
- scene->_object5.addMover(mover2, &pt2, this);
+ scene->_quinnShip.addMover(mover2, &pt2, this);
break;
}
case 10: {
PlayerMover2 *mover = new PlayerMover2();
- scene->_object1.addMover(mover, 10, 15, &scene->_object5);
+ scene->_seekerShip.addMover(mover, 10, 15, &scene->_quinnShip);
if (!g_globals->getFlag(104)) {
mover = new PlayerMover2();
- scene->_object4.addMover(mover, 10, 15, &scene->_object1);
+ scene->_emptyShip.addMover(mover, 10, 15, &scene->_seekerShip);
}
setDelay(60);
break;
@@ -2528,7 +2543,7 @@ void Scene90::Action1::signal() {
case 11:
g_globals->_soundHandler.play(57);
g_globals->_soundHandler.play(68);
- scene->_object3.animate(ANIM_MODE_6, NULL);
+ scene->_headGate.animate(ANIM_MODE_6, NULL);
SceneItem::display(90, g_globals->getFlag(104) ? 15 : 14,
SET_EXT_BGCOLOR, 13, SET_KEEP_ONSCREEN, -1, SET_X, 120, SET_Y, 20, LIST_END);
@@ -2543,7 +2558,7 @@ void Scene90::Action1::signal() {
/*--------------------------------------------------------------------------*/
-void Scene90::Object1::doAction(int action) {
+void Scene90::SeekerShip::doAction(int action) {
Scene90 *scene = (Scene90 *)g_globals->_sceneManager._scene;
switch (action) {
@@ -2561,23 +2576,23 @@ void Scene90::Object1::doAction(int action) {
}
}
-void Scene90::Object2::doAction(int action) {
+void Scene90::Guard::doAction(int action) {
Scene90 *scene = (Scene90 *)g_globals->_sceneManager._scene;
switch (action) {
case OBJECT_STUNNER:
case CURSOR_USE:
g_globals->_player.disableControl();
- scene->_object6.postInit();
- scene->_object6.setVisage(90);
- scene->_object6.setStrip(6);
- scene->_object6.setPosition(Common::Point(184, 210));
- scene->_object6.hide();
+ scene->_bubble.postInit();
+ scene->_bubble.setVisage(90);
+ scene->_bubble.setStrip(6);
+ scene->_bubble.setPosition(Common::Point(184, 210));
+ scene->_bubble.hide();
scene->_sceneMode = 91;
scene->_soundHandler1.play(59);
scene->_soundHandler1.holdAt(true);
- scene->setAction(&scene->_sequenceManager, scene, 91, this, &scene->_object6, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 91, this, &scene->_bubble, NULL);
break;
case CURSOR_LOOK:
SceneItem::display2(90, 8);
@@ -2595,21 +2610,21 @@ void Scene90::Object2::doAction(int action) {
/*--------------------------------------------------------------------------*/
Scene90::Scene90() :
- _item1(0, CURSOR_LOOK, 90, 9, LIST_END),
- _item2(0, CURSOR_LOOK, 90, 10, LIST_END),
- _item3(0, CURSOR_LOOK, 90, 11, LIST_END),
- _object3(OBJECT_STUNNER, 90, 13, CURSOR_LOOK, 90, 12, CURSOR_USE, 90, 16, LIST_END),
- _object4(CURSOR_LOOK, 90, 17, LIST_END),
- _object5(CURSOR_LOOK, 90, 18, CURSOR_USE, 90, 19, LIST_END) {
+ _guardShack(0, CURSOR_LOOK, 90, 9, LIST_END),
+ _shed(0, CURSOR_LOOK, 90, 10, LIST_END),
+ _background(0, CURSOR_LOOK, 90, 11, LIST_END),
+ _headGate(OBJECT_STUNNER, 90, 13, CURSOR_LOOK, 90, 12, CURSOR_USE, 90, 16, LIST_END),
+ _emptyShip(CURSOR_LOOK, 90, 17, LIST_END),
+ _quinnShip(CURSOR_LOOK, 90, 18, CURSOR_USE, 90, 19, LIST_END) {
}
void Scene90::stripCallback(int v) {
Scene90 *scene = (Scene90 *)g_globals->_sceneManager._scene;
if (v == 1)
- scene->_object2.animate(ANIM_MODE_7, 0, NULL);
+ scene->_guard.animate(ANIM_MODE_7, 0, NULL);
else if (v == 2)
- scene->_object2.animate(ANIM_MODE_NONE);
+ scene->_guard.animate(ANIM_MODE_NONE);
}
void Scene90::postInit(SceneObjectList *OwnerList) {
@@ -2623,53 +2638,53 @@ void Scene90::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_speakerQL);
_stripManager.addSpeaker(&_speakerSR);
- _speakerMText._npc = &_object2;
+ _speakerMText._npc = &_guard;
_speakerQText._textWidth = 160;
- _speakerQText._npc = &_object5;
- _speakerSText._npc = &_object1;
-
- _object5.postInit();
- _object5.setVisage(2333);
- _object5.setObjectWrapper(new SceneObjectWrapper());
- _object5._strip = 7;
- _object5._moveDiff = Common::Point(22, 22);
- _object5.setPosition(Common::Point(151, 177));
- _object5.changeZoom(-1);
- g_globals->_sceneItems.push_back(&_object5);
-
- _object1.postInit();
- _object1.setVisage(2337);
- _object1.setObjectWrapper(new SceneObjectWrapper());
- _object1._strip = 4;
- _object1._moveDiff = Common::Point(20, 20);
- _object1.setPosition(Common::Point(212, 183));
- _object1.changeZoom(-1);
- g_globals->_sceneItems.push_back(&_object1);
+ _speakerQText._npc = &_quinnShip;
+ _speakerSText._npc = &_seekerShip;
+
+ _quinnShip.postInit();
+ _quinnShip.setVisage(2333);
+ _quinnShip.setObjectWrapper(new SceneObjectWrapper());
+ _quinnShip._strip = 7;
+ _quinnShip._moveDiff = Common::Point(22, 22);
+ _quinnShip.setPosition(Common::Point(151, 177));
+ _quinnShip.changeZoom(-1);
+ g_globals->_sceneItems.push_back(&_quinnShip);
+
+ _seekerShip.postInit();
+ _seekerShip.setVisage(2337);
+ _seekerShip.setObjectWrapper(new SceneObjectWrapper());
+ _seekerShip._strip = 4;
+ _seekerShip._moveDiff = Common::Point(20, 20);
+ _seekerShip.setPosition(Common::Point(212, 183));
+ _seekerShip.changeZoom(-1);
+ g_globals->_sceneItems.push_back(&_seekerShip);
if (!g_globals->getFlag(104)) {
- _object4.postInit();
- _object4.setVisage(2331);
- _object4.setObjectWrapper(new SceneObjectWrapper());
- _object4._strip = 4;
- _object4._moveDiff = Common::Point(20, 20);
- _object4.setPosition(Common::Point(251, 207));
- _object4.changeZoom(-1);
- g_globals->_sceneItems.push_back(&_object4);
- }
-
- _object2.postInit();
- _object2.setVisage(90);
- _object2.animate(ANIM_MODE_1, NULL);
- _object2.setPosition(Common::Point(315, 185));
- _object2._strip = 2;
- g_globals->_sceneItems.push_back(&_object2);
-
- _object3.postInit();
- _object3.setVisage(90);
- _object3.animate(ANIM_MODE_1, NULL);
- _object3.setPosition(Common::Point(196, 181));
- _object3.fixPriority(175);
- g_globals->_sceneItems.push_back(&_object3);
+ _emptyShip.postInit();
+ _emptyShip.setVisage(2331);
+ _emptyShip.setObjectWrapper(new SceneObjectWrapper());
+ _emptyShip._strip = 4;
+ _emptyShip._moveDiff = Common::Point(20, 20);
+ _emptyShip.setPosition(Common::Point(251, 207));
+ _emptyShip.changeZoom(-1);
+ g_globals->_sceneItems.push_back(&_emptyShip);
+ }
+
+ _guard.postInit();
+ _guard.setVisage(90);
+ _guard.animate(ANIM_MODE_1, NULL);
+ _guard.setPosition(Common::Point(315, 185));
+ _guard._strip = 2;
+ g_globals->_sceneItems.push_back(&_guard);
+
+ _headGate.postInit();
+ _headGate.setVisage(90);
+ _headGate.animate(ANIM_MODE_1, NULL);
+ _headGate.setPosition(Common::Point(196, 181));
+ _headGate.fixPriority(175);
+ g_globals->_sceneItems.push_back(&_headGate);
g_globals->_player.disableControl();
g_globals->_soundHandler.play(55);
@@ -2678,11 +2693,11 @@ void Scene90::postInit(SceneObjectList *OwnerList) {
setAction(&_action1);
- _item3.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
- _item1.setBounds(Rect(271, 65, 271, 186));
- _item2.setBounds(Rect(0, 17, 124, 77));
+ _background.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _guardShack.setBounds(Rect(271, 65, 271, 186));
+ _shed.setBounds(Rect(0, 17, 124, 77));
- g_globals->_sceneItems.addItems(&_item1, &_item2, &_item3, NULL);
+ g_globals->_sceneItems.addItems(&_guardShack, &_shed, &_background, NULL);
}
void Scene90::signal() {
diff --git a/engines/tsage/ringworld/ringworld_scenes1.h b/engines/tsage/ringworld/ringworld_scenes1.h
index bb98c89a8c..d52d4fb6ec 100644
--- a/engines/tsage/ringworld/ringworld_scenes1.h
+++ b/engines/tsage/ringworld/ringworld_scenes1.h
@@ -54,8 +54,12 @@ public:
Speaker _speakerQText;
Action1 _action1;
Action2 _action2;
- SceneObject _object1, _object2, _object3;
- SceneObject _object4, _object5, _object6;
+ SceneObject _veeshkaBody;
+ SceneObject _veeshkaHead;
+ SceneObject _veeshkaRightArm;
+ SceneObject _centurion;
+ SceneObject _leftSmoke;
+ SceneObject _rightSmoke;
virtual void stripCallback(int v);
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -70,7 +74,7 @@ class Scene15 : public Scene {
};
public:
Action1 _action1;
- SceneObject _object1;
+ SceneObject _ship;
ASound _soundHandler;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -102,7 +106,10 @@ public:
Action2 _action2;
Action3 _action3;
Action4 _action4;
- SceneObject _sceneObject1, _SceneObjectExt, _sceneObject3, _sceneObject4, _sceneObject5;
+ SceneObject _assassinShip1;
+ SceneObject _assassinShip2;
+ SceneObject _laserShot1;
+ SceneObject _laserShot2;
ASound _sound;
public:
Scene20();
@@ -248,15 +255,21 @@ public:
Action6 _action6;
Action7 _action7;
Action8 _action8;
- SceneObject _object1, _object2, _object3;
+ SceneObject _seeker;
+ SceneObject _seekerTail;
+ SceneObject _seekerHand;
DyingKzin _dyingKzin;
Assassin _assassin;
- SceneObject _doorway, _object7, _object8;
- DisplayHotspot _item1;
- Item2 _item2;
- DisplayHotspot _item3, _item4, _item5;
- Item6 _item6;
- DisplayHotspot _item7, _item8;
+ SceneObject _doorway;
+ SceneObject _leftEntrance;
+ DisplayHotspot _ball;
+ Item2 _statue;
+ DisplayHotspot _window;
+ DisplayHotspot _entrance;
+ DisplayHotspot _background;
+ Item6 _pedestal;
+ DisplayHotspot _emerald;
+ DisplayHotspot _tree;
Scene40();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -284,15 +297,15 @@ class Scene50 : public Scene {
public:
virtual void doAction(int action);
};
- class Object2 : public SceneObject {
+ class LeftFlyCycle : public SceneObject {
public:
virtual void doAction(int action);
};
- class Object3 : public SceneObject {
+ class CenterFlyCycle : public SceneObject {
public:
virtual void doAction(int action);
};
- class Object4 : public SceneObject {
+ class RightFlyCycle : public SceneObject {
public:
virtual void doAction(int action);
};
@@ -302,15 +315,18 @@ public:
Action1 _action1;
Action2 _action2;
Action3 _action3;
- Object1 _object1;
- Object2 _object2;
- Object3 _object3;
- Object4 _object4;
+ LeftFlyCycle _leftFlyCycle;
+ CenterFlyCycle _centerFlyCycle;
+ RightFlyCycle _rightFlyCycle;
Rect _doorwayRect;
SpeakerSText _speakerSText;
SpeakerQText _speakerQText;
- DisplayHotspot _item0, _item1, _item2;
- DisplayHotspot _item3, _item4, _item5;
+ DisplayHotspot _background;
+ DisplayHotspot _item1;
+ DisplayHotspot _entrance;
+ DisplayHotspot _bulwark;
+ DisplayHotspot _tree;
+ DisplayHotspot _flagstones;
Scene50();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -392,8 +408,12 @@ public:
MasterObject _masterButton;
FloppyDrive _floppyDrive;
SceneObject _redLights;
- Item1 _item1;
- Item _item2, _item3, _item4, _item5, _item6;
+ Item1 _diskDrive;
+ Item _dashboard;
+ Item _intercomm;
+ Item _viewScreen;
+ Item _speedControl;
+ Item _speaker;
ASound _soundHandler1;
ASound _soundHandler2;
ASound _soundHandler3;
@@ -409,11 +429,11 @@ class Scene90 : public Scene {
public:
virtual void signal();
};
- class Object1 : public SceneObject {
+ class SeekerShip : public SceneObject {
public:
virtual void doAction(int action);
};
- class Object2 : public SceneObject {
+ class Guard : public SceneObject {
public:
virtual void doAction(int action);
};
@@ -425,11 +445,15 @@ public:
SpeakerSR _speakerSR;
SpeakerMText _speakerMText;
Action1 _action1;
- Object1 _object1;
- Object2 _object2;
- DisplayObject _object3, _object4, _object5;
- SceneObject _object6;
- DisplayHotspot _item1, _item2, _item3;
+ SeekerShip _seekerShip;
+ Guard _guard;
+ DisplayObject _headGate;
+ DisplayObject _emptyShip;
+ DisplayObject _quinnShip;
+ SceneObject _bubble;
+ DisplayHotspot _guardShack;
+ DisplayHotspot _shed;
+ DisplayHotspot _background;
ASound _soundHandler1, _soundHandler2;
Scene90();
diff --git a/engines/tsage/ringworld/ringworld_scenes10.cpp b/engines/tsage/ringworld/ringworld_scenes10.cpp
index f9a8e7996a..eac181e350 100644
--- a/engines/tsage/ringworld/ringworld_scenes10.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes10.cpp
@@ -1870,7 +1870,7 @@ void Scene9900::signal() {
setAction(&_sequenceManager, this, 9908, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
break;
case 162:
- warning("TBC: shutdown();");
+ // shutdown();
g_globals->_game->quitGame();
break;
case 9901:
diff --git a/engines/tsage/ringworld/ringworld_scenes5.cpp b/engines/tsage/ringworld/ringworld_scenes5.cpp
index 004ccbbb6d..1b6cd78223 100644
--- a/engines/tsage/ringworld/ringworld_scenes5.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes5.cpp
@@ -34,6 +34,9 @@ namespace Ringworld {
* Scene 4000 - Village
*
*--------------------------------------------------------------------------*/
+Scene4000::Hotspot8::Hotspot8() : SceneObject() {
+ _ctr = 0;
+}
void Scene4000::Action1::signal() {
// Quinn has the peg. Everybody enter the screen.
diff --git a/engines/tsage/ringworld/ringworld_scenes5.h b/engines/tsage/ringworld/ringworld_scenes5.h
index c93df2a1d8..2fe26d9712 100644
--- a/engines/tsage/ringworld/ringworld_scenes5.h
+++ b/engines/tsage/ringworld/ringworld_scenes5.h
@@ -99,6 +99,7 @@ class Scene4000 : public Scene {
private:
int _ctr;
public:
+ Hotspot8();
virtual void synchronize(Serializer &s) {
SceneObject::synchronize(s);
s.syncAsUint16LE(_ctr);
diff --git a/engines/tsage/ringworld/ringworld_scenes6.cpp b/engines/tsage/ringworld/ringworld_scenes6.cpp
index 30a91b57aa..65c1ed39c6 100644
--- a/engines/tsage/ringworld/ringworld_scenes6.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes6.cpp
@@ -2032,7 +2032,15 @@ void Scene5300::Hotspot8::doAction(int action) {
/*--------------------------------------------------------------------------*/
Scene5300::Scene5300() :
- _hotspot3(0, CURSOR_LOOK, 5300, 3, CURSOR_USE, 5300, 16, LIST_END) {
+ _hotspot3(0, CURSOR_LOOK, 5300, 3, CURSOR_USE, 5300, 16, LIST_END) {
+}
+
+void Scene5300::synchronize(Serializer &s) {
+ Scene::synchronize(s);
+ if (s.getVersion() < 11) {
+ int useless = 0;
+ s.syncAsSint16LE(useless);
+ }
}
void Scene5300::postInit(SceneObjectList *OwnerList) {
@@ -2119,7 +2127,6 @@ void Scene5300::postInit(SceneObjectList *OwnerList) {
setAction(&_sequenceManager, this, 5306, &g_globals->_player, &_hotspot3, NULL);
}
- _field1B0A = 1;
if (RING_INVENTORY._bone._sceneNumber == 5300) {
_hotspot5.postInit();
_hotspot5.setVisage(5301);
diff --git a/engines/tsage/ringworld/ringworld_scenes6.h b/engines/tsage/ringworld/ringworld_scenes6.h
index bf353de415..4c10e4a711 100644
--- a/engines/tsage/ringworld/ringworld_scenes6.h
+++ b/engines/tsage/ringworld/ringworld_scenes6.h
@@ -318,15 +318,11 @@ public:
Hotspot6 _hotspot6;
Hotspot7 _hotspot7;
Hotspot8 _hotspot8;
- int _field1B0A;
Scene5300();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
- virtual void synchronize(Serializer &s) {
- Scene::synchronize(s);
- s.syncAsSint16LE(_field1B0A);
- }
+ virtual void synchronize(Serializer &s);
};
} // End of namespace Ringworld
diff --git a/engines/tsage/ringworld/ringworld_scenes8.cpp b/engines/tsage/ringworld/ringworld_scenes8.cpp
index 9cb85a6930..f9156479e5 100644
--- a/engines/tsage/ringworld/ringworld_scenes8.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes8.cpp
@@ -30,6 +30,10 @@ namespace TsAGE {
namespace Ringworld {
+NamedHotspotMult::NamedHotspotMult() : SceneHotspot() {
+ _useLineNum = _lookLineNum = 0;
+}
+
void NamedHotspotMult::synchronize(Serializer &s) {
SceneHotspot::synchronize(s);
s.syncAsSint16LE(_useLineNum);
@@ -2533,6 +2537,10 @@ Scene7700::Scene7700() {
_object5._state = 0;
_object6._state = 0;
_prof._state = 0;
+
+ _seatCountLeft1 = 0;
+ _seatCountLeft2 = 0;
+ _seatCountRight = 0;
}
void Scene7700::synchronize(Serializer &s) {
diff --git a/engines/tsage/ringworld/ringworld_scenes8.h b/engines/tsage/ringworld/ringworld_scenes8.h
index b24f220f8c..fa441f87da 100644
--- a/engines/tsage/ringworld/ringworld_scenes8.h
+++ b/engines/tsage/ringworld/ringworld_scenes8.h
@@ -40,7 +40,7 @@ using namespace TsAGE;
class NamedHotspotMult : public SceneHotspot {
public:
int _useLineNum, _lookLineNum;
- NamedHotspotMult() : SceneHotspot() {}
+ NamedHotspotMult();
virtual Common::String getClassName() { return "NamedHotspotMult"; }
virtual void synchronize(Serializer &s);
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index 478fdcf5a5..a0675bc292 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -50,6 +50,7 @@ RightClickDialog::RightClickDialog() : GfxDialog() {
_btnList[5] = Common::Point(83, 47);
// Set the palette and change the cursor
+ _previousCursor = R2_GLOBALS._events.getCursor();
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
setPalette();
@@ -136,7 +137,7 @@ bool RightClickDialog::process(Event &event) {
return false;
}
-void RightClickDialog::execute() {
+int RightClickDialog::execute() {
// Draw the dialog
draw();
@@ -157,7 +158,8 @@ void RightClickDialog::execute() {
}
// Execute the specified action
- CursorType cursorNum = CURSOR_NONE;
+ CursorType cursorNum = _previousCursor;
+ int result = -1;
switch (_selectedAction) {
case 0:
// Look action
@@ -165,7 +167,7 @@ void RightClickDialog::execute() {
break;
case 1:
// Walk action
- cursorNum = CURSOR_WALK;
+ cursorNum = R2_GLOBALS._player._canWalk ? CURSOR_WALK : CURSOR_USE;
break;
case 2:
// Use action
@@ -177,17 +179,18 @@ void RightClickDialog::execute() {
break;
case 4:
// Change player
- CharacterDialog::show();
+ result = 0;
break;
case 5:
// Options dialog
+ result = 1;
break;
}
- if (cursorNum != CURSOR_NONE)
- R2_GLOBALS._events.setCursor(cursorNum);
-
+ R2_GLOBALS._events.setCursor(cursorNum);
_gfxManager.deactivate();
+
+ return result;
}
/*--------------------------------------------------------------------------*/
@@ -234,9 +237,9 @@ void CharacterDialog::show() {
SceneExt *scene = (SceneExt *)R2_GLOBALS._sceneManager._scene;
scene->saveCharacter(oldCharacter);
- // Play a transition sound as the character is changed
- if (R2_GLOBALS._player._characterScene[0] != 300) {
- switch (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex]) {
+ // Play the correctfrequency, if any, of the character being switched to's scanner device
+ if (R2_GLOBALS._player._characterScene[R2_NONE] != 300) {
+ switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] - 1) {
case 0:
R2_GLOBALS._sound4.stop();
break;
@@ -255,8 +258,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] - 1) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
@@ -272,8 +275,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[R2_QUINN] == 300) && (R2_GLOBALS._scannerFrequencies[1] != 1)) {
+ switch (R2_GLOBALS._scannerFrequencies[1] - 1) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
@@ -289,12 +292,12 @@ void CharacterDialog::show() {
default:
break;
}
- } else if (R2_GLOBALS._player._characterScene[2] != 300) {
+ } else if (R2_GLOBALS._player._characterScene[R2_SEEKER] != 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] - 1) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
@@ -344,7 +347,7 @@ CharacterDialog::CharacterDialog() {
/*--------------------------------------------------------------------------*/
void HelpDialog::show() {
- // Set the palette and change the cursor
+ // change the cursor
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
// Create the dialog and draw it
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.h b/engines/tsage/ringworld2/ringworld2_dialogs.h
index 02a1aed81c..0c19ae4371 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.h
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.h
@@ -50,13 +50,14 @@ private:
int _highlightedAction;
int _selectedAction;
+ CursorType _previousCursor;
public:
RightClickDialog();
~RightClickDialog();
virtual void draw();
virtual bool process(Event &event);
- void execute();
+ int execute();
};
class CharacterDialog: public GfxDialog {
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index 97042cb621..e1d6e79423 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"
@@ -36,8 +38,6 @@ namespace TsAGE {
namespace Ringworld2 {
Scene *Ringworld2Game::createScene(int sceneNumber) {
- warning("Switching to scene %d", sceneNumber);
-
switch (sceneNumber) {
/* Scene group #0 */
case 50:
@@ -86,8 +86,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,19 +101,24 @@ 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 */
//
case 1000:
- error("Missing scene %d from group 1", sceneNumber);
+ // Cutscene scene
+ return new Scene1000();
case 1010:
// Cutscene - trip in space
return new Scene1010();
case 1020:
+ // Cutscene - trip in space 2
return new Scene1020();
case 1100:
+ // Canyon
return new Scene1100();
case 1200:
+ // ARM Base - Air Ducts Maze
return new Scene1200();
case 1337:
case 1330:
@@ -124,11 +131,13 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Cutscene - Ship
return new Scene1525();
case 1530:
- // Cutscene - Elevator
+ // Cutscene - Crashing on Rimwall
return new Scene1530();
case 1550:
+ // Spaceport
return new Scene1550();
case 1575:
+ // Spaceport - unused ship scene
return new Scene1575();
case 1580:
// Inside wreck
@@ -137,83 +146,93 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Miranda being questioned
return new Scene1625();
case 1700:
+ // Rim
return new Scene1700();
case 1750:
+ // Rim Transport Vechile
return new Scene1750();
case 1800:
+ // Rim Lift Exterior
return new Scene1800();
case 1850:
+ // Rim Lift Interior
return new Scene1850();
case 1875:
+ // Rim Lift Computer
return new Scene1875();
case 1900:
+ // Spill Mountains Elevator Exit
return new Scene1900();
case 1925:
+ // Spill Mountains Elevator Shaft
return new Scene1925();
case 1945:
+ // Spill Mountains Shaft Bottom
return new Scene1945();
case 1950:
+ // Flup Tube Corridor Maze
return new Scene1950();
/* Scene group #2 */
- //
case 2000:
- // Ice Maze
+ // Spill Mountains
return new Scene2000();
case 2350:
- // Ice Maze: Balloon Launch Platform
+ // Spill Mountains: Balloon Launch Platform
return new Scene2350();
case 2400:
- // Ice Maze: Large empty room
+ // Spill Mountains: Unused large empty room
return new Scene2400();
case 2425:
- // Ice Maze:
+ // Spill Mountains: The Hall of Records
return new Scene2425();
case 2430:
- // Ice Maze: Bedroom
+ // Spill Mountains: Bedroom
return new Scene2430();
case 2435:
- // Ice Maze: Throne room
+ // Spill Mountains: Throne room
return new Scene2435();
case 2440:
- // Ice Maze: Another bedroom
+ // Spill Mountains: Another bedroom
return new Scene2440();
case 2445:
- // Ice Maze:
+ // Spill Mountains:
return new Scene2445();
case 2450:
- // Ice Maze: Another bedroom
+ // Spill Mountains: Another bedroom
return new Scene2450();
case 2455:
- // Ice Maze: Inside crevasse
+ // Spill Mountains: Inside crevasse
return new Scene2455();
case 2500:
- // Ice Maze: Large Cave
+ // Spill Mountains: Large Ledge
return new Scene2500();
case 2525:
- // Ice Maze: Furnace room
+ // Spill Mountains: Furnace room
return new Scene2525();
case 2530:
- // Ice Maze: Well
+ // Spill Mountains: Well
return new Scene2530();
case 2535:
- // Ice Maze: Tannery
+ // Spill Mountains: Tannery
return new Scene2535();
case 2600:
- // Ice Maze: Exit
+ // Spill Mountains: Exit
return new Scene2600();
case 2700:
- // Forest Maze
+ // Outer Forest
return new Scene2700();
case 2750:
- // Forest Maze
+ // Inner Forest
return new Scene2750();
case 2800:
- // Exiting Forest
+ // Guard post
return new Scene2800();
case 2900:
- error("Missing scene %d from group 2", sceneNumber);
+ // Balloon Cutscene
+ return new Scene2900();
+
/* Scene group #3 */
- //
+ // ARM Base Hanager
case 3100:
return new Scene3100();
case 3125:
@@ -247,34 +266,43 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Room with large stasis field negator
return new Scene3250();
case 3255:
+ // Guard Post
return new Scene3255();
case 3260:
- // Computer room
+ // ARM Base - Computer room
return new Scene3260();
case 3275:
- // Hall
+ // ARM Base - Hall
return new Scene3275();
case 3350:
// Cutscene - Ship landing
return new Scene3350();
case 3375:
+ // Circular Walkway
return new Scene3375();
case 3385:
+ // Corridor
return new Scene3385();
case 3395:
+ // Walkway
return new Scene3395();
case 3400:
+ // Confrontation
return new Scene3400();
case 3500:
+ // Flub tube maze
return new Scene3500();
case 3600:
+ // Cutscene - walking at gunpoint
return new Scene3600();
case 3700:
// Cutscene - Teleport outside
return new Scene3700();
case 3800:
+ // Desert
return new Scene3800();
case 3900:
+ // Forest Entrance
return new Scene3900();
default:
error("Unknown scene number - %d", sceneNumber);
@@ -294,8 +322,11 @@ bool Ringworld2Game::canLoadGameStateCurrently() {
* Returns true if it is currently okay to save the game
*/
bool Ringworld2Game::canSaveGameStateCurrently() {
- // Don't allow a game to be saved if a dialog is active
- return g_globals->_gfxManagers.size() == 1;
+ // Don't allow a game to be saved if a dialog is active, or if an animation
+ // is playing, or if an active scene prevents it
+ return g_globals->_gfxManagers.size() == 1 && R2_GLOBALS._animationCtr == 0 &&
+ (!R2_GLOBALS._sceneManager._scene ||
+ !((SceneExt *)R2_GLOBALS._sceneManager._scene)->_preventSaving);
}
/*--------------------------------------------------------------------------*/
@@ -305,12 +336,28 @@ SceneExt::SceneExt(): Scene() {
_stripManager._onEnd = SceneExt::endStrip;
for (int i = 0; i < 256; i++)
- _field312[i] = 0;
- _field372 = _field37A = 0;
+ _shadowPaletteMap[i] = 0;
+
_savedPlayerEnabled = false;
_savedUiEnabled = false;
_savedCanWalk = false;
- _focusObject = NULL;
+ _preventSaving = false;
+
+ // Reset screen clipping area
+ R2_GLOBALS._screenSurface._clipRect = Rect();
+
+ // WORKAROUND: In the original, playing animations don't reset the global _animationCtr
+ // counter as scene changes unless the playing animation explicitly finishes. For now,
+ // to make inter-scene debugging easier, I'm explicitly resetting the _animationCtr
+ // on scene start, since scene objects aren't drawn while it's non-zero
+ R2_GLOBALS._animationCtr = 0;
+}
+
+void SceneExt::synchronize(Serializer &s) {
+ Scene::synchronize(s);
+
+ s.syncBytes(&_shadowPaletteMap[0], 256);
+ _sceneAreas.synchronize(s);
}
void SceneExt::postInit(SceneObjectList *OwnerList) {
@@ -319,18 +366,18 @@ void SceneExt::postInit(SceneObjectList *OwnerList) {
// Exclude the bottom area of the screen to allow room for the UI
T2_GLOBALS._interfaceY = UI_INTERFACE_Y;
- // Initialise fields
+ // Initialize fields
_action = NULL;
_field12 = 0;
_sceneMode = 0;
+ static_cast<SceneHandlerExt *>(R2_GLOBALS._sceneHandler)->setupPaletteMaps();
+
int prevScene = R2_GLOBALS._sceneManager._previousScene;
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))) {
- static_cast<SceneHandlerExt *>(R2_GLOBALS._sceneHandler)->setupPaletteMaps();
+ || ((sceneNumber == 100) && (prevScene == 0 || prevScene == 180 || prevScene == 205))) {
R2_GLOBALS._uiElements._active = true;
R2_GLOBALS._uiElements.show();
} else {
@@ -341,6 +388,11 @@ void SceneExt::postInit(SceneObjectList *OwnerList) {
void SceneExt::remove() {
_sceneAreas.clear();
Scene::remove();
+ R2_GLOBALS._uiElements._active = true;
+
+ if (R2_GLOBALS._events.getCursor() >= EXITCURSOR_N &&
+ R2_GLOBALS._events.getCursor() <= SHADECURSOR_DOWN)
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
}
void SceneExt::process(Event &event) {
@@ -349,43 +401,9 @@ void SceneExt::process(Event &event) {
}
void SceneExt::dispatch() {
-/*
- _timerList.dispatch();
-
- if (_field37A) {
- if ((--_field37A == 0) && R2_GLOBALS._dayNumber) {
- if (R2_GLOBALS._uiElements._active && R2_GLOBALS._player._enabled) {
- R2_GLOBALS._uiElements.show();
- }
-
- _field37A = 0;
- }
- }
-*/
Scene::dispatch();
}
-void SceneExt::loadScene(int sceneNum) {
- Scene::loadScene(sceneNum);
-
- _v51C34.top = 0;
- _v51C34.bottom = 300;
-
- int prevScene = R2_GLOBALS._sceneManager._previousScene;
- 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))) {
- // TODO: sub_17875
- R2_GLOBALS._uiElements._active = true;
- R2_GLOBALS._uiElements.show();
- } else {
- // Update the user interface
- R2_GLOBALS._uiElements.updateInventory();
- }
-}
-
bool SceneExt::display(CursorType action, Event &event) {
switch (action) {
case CURSOR_CROSSHAIRS:
@@ -407,17 +425,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:
@@ -445,7 +465,6 @@ void SceneExt::fadeOut() {
void SceneExt::startStrip() {
SceneExt *scene = (SceneExt *)R2_GLOBALS._sceneManager._scene;
- scene->_field372 = 1;
scene->_savedPlayerEnabled = R2_GLOBALS._player._enabled;
if (scene->_savedPlayerEnabled) {
@@ -461,7 +480,6 @@ void SceneExt::startStrip() {
void SceneExt::endStrip() {
SceneExt *scene = (SceneExt *)R2_GLOBALS._sceneManager._scene;
- scene->_field372 = 0;
if (scene->_savedPlayerEnabled) {
R2_GLOBALS._player.enableControl();
@@ -509,10 +527,12 @@ void SceneExt::refreshBackground(int xAmount, int yAmount) {
assert(screenSize == (s.w * s.h));
// Copy the data
- byte *destP = (byte *)s.getBasePtr(0, 0);
+ byte *destP = (byte *)s.getPixels();
Common::copy(dataP, dataP + (s.w * s.h), destP);
_backSurface.unlockSurface();
+ R2_GLOBALS._screenSurface.addDirtyRect(_backSurface.getBounds());
+
// Free the resource data
DEALLOCATE(dataP);
}
@@ -553,14 +573,24 @@ void SceneExt::scalePalette(int RFactor, int GFactor, int BFactor) {
varC = tmp;
varD = j;
}
- this->_field312[i] = varD;
+ this->_shadowPaletteMap[i] = varD;
}
}
+void SceneExt::loadBlankScene() {
+ _backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2);
+ _backSurface.fillRect(_backSurface.getBounds(), 0);
+
+ R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0);
+}
+
/*--------------------------------------------------------------------------*/
void SceneHandlerExt::postInit(SceneObjectList *OwnerList) {
SceneHandler::postInit(OwnerList);
+
+ if (!R2_GLOBALS._playStream.setFile("SND4K.RES"))
+ warning("Could not find SND4K.RES voice file");
}
void SceneHandlerExt::process(Event &event) {
@@ -573,7 +603,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 +613,31 @@ void SceneHandlerExt::process(Event &event) {
SceneHandler::process(event);
}
+void SceneHandlerExt::postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) {
+ // Set up the shading maps used for showing the player in shadows
+ 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._frameEdgeColor = 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) {
@@ -617,7 +667,7 @@ void SceneHandlerExt::setupPaletteMaps() {
break;
}
- // Scan for the palette index with the closest matching colour
+ // Scan for the palette index with the closest matching color
int threshold = 769;
int foundIndex = -1;
for (int pIndex2 = 223; pIndex2 >= 0; --pIndex2) {
@@ -637,18 +687,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 +707,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;
}
@@ -733,113 +784,113 @@ bool DisplayObject::performAction(int action) {
Ringworld2InvObjectList::Ringworld2InvObjectList():
_none(1, 1),
- _inv1(1, 2),
- _inv2(1, 3),
+ _optoDisk(1, 2),
+ _reader(1, 3),
_negatorGun(1, 4),
_steppingDisks(1, 5),
- _inv5(1, 6),
- _inv6(1, 7),
- _inv7(1, 8),
- _inv8(1, 9),
- _inv9(1, 10),
- _inv10(1, 11),
- _inv11(1, 12),
- _inv12(1, 13),
- _inv13(1, 14),
- _inv14(1, 15),
- _inv15(1, 16),
- _inv16(1, 17),
- _inv17(2, 2),
- _inv18(2, 3),
- _inv19(2, 4),
- _inv20(2, 5),
- _inv21(2, 5),
- _inv22(2, 6),
- _inv23(2, 7),
- _inv24(2, 8),
- _inv25(2, 9),
- _inv26(2, 10),
- _inv27(2, 11),
- _inv28(2, 12),
- _inv29(2, 13),
- _inv30(2, 14),
- _inv31(2, 15),
- _inv32(2, 16),
- _inv33(3, 2),
- _inv34(3, 3),
- _inv35(3, 4),
- _inv36(3, 5),
- _inv37(3, 6),
- _inv38(3, 7),
- _inv39(1, 10),
- _inv40(3, 8),
- _inv41(3, 9),
- _inv42(3, 10),
- _inv43(3, 11),
- _inv44(3, 12),
- _inv45(3, 13),
- _inv46(3, 17),
- _inv47(3, 14),
- _inv48(3, 14),
- _inv49(3, 15),
- _inv50(3, 15),
- _inv51(3, 17),
- _inv52(4, 2) {
+ _attractorUnit(1, 6),
+ _sensorProbe(1, 7),
+ _sonicStunner(1, 8),
+ _cableHarness(1, 9),
+ _comScanner(1, 10),
+ _spentPowerCapsule(1, 11), // 10
+ _chargedPowerCapsule(1, 12),
+ _aerosol(1, 13),
+ _remoteControl(1, 14),
+ _opticalFibre(1, 15),
+ _clamp(1, 16),
+ _attractorHarness(1, 17),
+ _fuelCell(2, 2),
+ _gyroscope(2, 3),
+ _airbag(2, 4),
+ _rebreatherTank(2, 5), // 20
+ _reserveTank(2, 5),
+ _guidanceModule(2, 6),
+ _thrusterValve(2, 7),
+ _balloonBackpack(2, 8),
+ _radarMechanism(2, 9),
+ _joystick(2, 10),
+ _ignitor(2, 11),
+ _diagnosticsDisplay(2, 12),
+ _glassDome(2, 13),
+ _wickLamp(2, 14), // 30
+ _scrithKey(2, 15),
+ _tannerMask(2, 16),
+ _pureGrainAlcohol(3, 2),
+ _blueSapphire(3, 3),
+ _ancientScrolls(3, 4),
+ _flute(3, 5),
+ _gunpowder(3, 6),
+ _unused(3, 7),
+ _comScanner2(1, 10),
+ _superconductorWire(3, 8), // 40
+ _pillow(3, 9),
+ _foodTray(3, 10),
+ _laserHacksaw(3, 11),
+ _photonStunner(3, 12),
+ _battery(3, 13),
+ _soakedFaceMask(2, 17),
+ _lightBulb(3, 14),
+ _alcoholLamp1(2, 14),
+ _alcoholLamp2(3, 15),
+ _alocholLamp3(3, 15), // 50
+ _brokenDisplay(3, 17),
+ _toolbox(4, 2) {
// Add the items to the list
_itemList.push_back(&_none);
- _itemList.push_back(&_inv1);
- _itemList.push_back(&_inv2);
+ _itemList.push_back(&_optoDisk);
+ _itemList.push_back(&_reader);
_itemList.push_back(&_negatorGun);
_itemList.push_back(&_steppingDisks);
- _itemList.push_back(&_inv5);
- _itemList.push_back(&_inv6);
- _itemList.push_back(&_inv7);
- _itemList.push_back(&_inv8);
- _itemList.push_back(&_inv9);
- _itemList.push_back(&_inv10);
- _itemList.push_back(&_inv11);
- _itemList.push_back(&_inv12);
- _itemList.push_back(&_inv13);
- _itemList.push_back(&_inv14);
- _itemList.push_back(&_inv15);
- _itemList.push_back(&_inv16);
- _itemList.push_back(&_inv17);
- _itemList.push_back(&_inv18);
- _itemList.push_back(&_inv19);
- _itemList.push_back(&_inv20);
- _itemList.push_back(&_inv21);
- _itemList.push_back(&_inv22);
- _itemList.push_back(&_inv23);
- _itemList.push_back(&_inv24);
- _itemList.push_back(&_inv25);
- _itemList.push_back(&_inv26);
- _itemList.push_back(&_inv27);
- _itemList.push_back(&_inv28);
- _itemList.push_back(&_inv29);
- _itemList.push_back(&_inv30);
- _itemList.push_back(&_inv31);
- _itemList.push_back(&_inv32);
- _itemList.push_back(&_inv33);
- _itemList.push_back(&_inv34);
- _itemList.push_back(&_inv35);
- _itemList.push_back(&_inv36);
- _itemList.push_back(&_inv37);
- _itemList.push_back(&_inv38);
- _itemList.push_back(&_inv39);
- _itemList.push_back(&_inv40);
- _itemList.push_back(&_inv41);
- _itemList.push_back(&_inv42);
- _itemList.push_back(&_inv43);
- _itemList.push_back(&_inv44);
- _itemList.push_back(&_inv45);
- _itemList.push_back(&_inv46);
- _itemList.push_back(&_inv47);
- _itemList.push_back(&_inv48);
- _itemList.push_back(&_inv49);
- _itemList.push_back(&_inv50);
- _itemList.push_back(&_inv51);
- _itemList.push_back(&_inv52);
+ _itemList.push_back(&_attractorUnit);
+ _itemList.push_back(&_sensorProbe);
+ _itemList.push_back(&_sonicStunner);
+ _itemList.push_back(&_cableHarness);
+ _itemList.push_back(&_comScanner);
+ _itemList.push_back(&_spentPowerCapsule); // 10
+ _itemList.push_back(&_chargedPowerCapsule);
+ _itemList.push_back(&_aerosol);
+ _itemList.push_back(&_remoteControl);
+ _itemList.push_back(&_opticalFibre);
+ _itemList.push_back(&_clamp);
+ _itemList.push_back(&_attractorHarness);
+ _itemList.push_back(&_fuelCell);
+ _itemList.push_back(&_gyroscope);
+ _itemList.push_back(&_airbag);
+ _itemList.push_back(&_rebreatherTank); // 20
+ _itemList.push_back(&_reserveTank);
+ _itemList.push_back(&_guidanceModule);
+ _itemList.push_back(&_thrusterValve);
+ _itemList.push_back(&_balloonBackpack);
+ _itemList.push_back(&_radarMechanism);
+ _itemList.push_back(&_joystick);
+ _itemList.push_back(&_ignitor);
+ _itemList.push_back(&_diagnosticsDisplay);
+ _itemList.push_back(&_glassDome);
+ _itemList.push_back(&_wickLamp); // 30
+ _itemList.push_back(&_scrithKey);
+ _itemList.push_back(&_tannerMask);
+ _itemList.push_back(&_pureGrainAlcohol);
+ _itemList.push_back(&_blueSapphire);
+ _itemList.push_back(&_ancientScrolls);
+ _itemList.push_back(&_flute);
+ _itemList.push_back(&_gunpowder);
+ _itemList.push_back(&_unused);
+ _itemList.push_back(&_comScanner2);
+ _itemList.push_back(&_superconductorWire); // 40
+ _itemList.push_back(&_pillow);
+ _itemList.push_back(&_foodTray);
+ _itemList.push_back(&_laserHacksaw);
+ _itemList.push_back(&_photonStunner);
+ _itemList.push_back(&_battery);
+ _itemList.push_back(&_soakedFaceMask);
+ _itemList.push_back(&_lightBulb);
+ _itemList.push_back(&_alcoholLamp1);
+ _itemList.push_back(&_alcoholLamp2);
+ _itemList.push_back(&_alocholLamp3); // 50
+ _itemList.push_back(&_brokenDisplay);
+ _itemList.push_back(&_toolbox);
_selectedItem = NULL;
}
@@ -904,6 +955,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) {
@@ -918,7 +972,129 @@ void Ringworld2InvObjectList::setObjectScene(int objectNum, int sceneNumber) {
R2_GLOBALS._events.setCursor(CURSOR_USE);
// Update the user interface if necessary
- T2_GLOBALS._uiElements.updateInventory();
+ T2_GLOBALS._uiElements.updateInventory(
+ (sceneNumber == R2_GLOBALS._player._characterIndex) ? objectNum : 0);
+}
+
+/**
+ * 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, R2_SEEKER);
+ } 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);
}
/*--------------------------------------------------------------------------*/
@@ -939,19 +1115,31 @@ void Ringworld2Game::start() {
if (slot >= 0)
R2_GLOBALS._sceneHandler->_loadGameSlot = slot;
else {
- // Switch to the first game scene
+ // Switch to the first title screen
R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._uiElements._active = true;
- R2_GLOBALS._sceneManager.setNewScene(100);
+ R2_GLOBALS._sceneManager.setNewScene(180);
}
g_globals->_events.showCursor();
}
+void Ringworld2Game::restartGame() {
+ if (MessageDialog::show(Ringworld2::R2_RESTART_MSG, CANCEL_BTN_STRING, YES_MSG) == 1)
+ restart();
+}
+
void Ringworld2Game::restart() {
g_globals->_scenePalette.clearListeners();
g_globals->_soundHandler.stop();
+ // Reset the globals
+ g_globals->reset();
+
+ // Clear save/load slots
+ g_globals->_sceneHandler->_saveGameSlot = -1;
+ g_globals->_sceneHandler->_loadGameSlot = -1;
+
// Change to the first game scene
g_globals->_sceneManager.changeScene(100);
}
@@ -1008,25 +1196,25 @@ void Ringworld2Game::processEvent(Event &event) {
case Common::KEYCODE_F4:
// F4 - Restart
restartGame();
- g_globals->_events.setCursorFromFlag();
+ R2_GLOBALS._events.setCursorFromFlag();
break;
case Common::KEYCODE_F7:
// F7 - Restore
restoreGame();
- g_globals->_events.setCursorFromFlag();
+ R2_GLOBALS._events.setCursorFromFlag();
break;
case Common::KEYCODE_F8:
// F8 - Credits
- warning("TODO: Show Credits");
+ R2_GLOBALS._sceneManager.changeScene(205);
break;
case Common::KEYCODE_F10:
// F10 - Pause
GfxDialog::setPalette();
MessageDialog::show(GAME_PAUSED_MSG, OK_BTN_STRING);
- g_globals->_events.setCursorFromFlag();
+ R2_GLOBALS._events.setCursorFromFlag();
break;
default:
@@ -1037,8 +1225,13 @@ void Ringworld2Game::processEvent(Event &event) {
void Ringworld2Game::rightClick() {
RightClickDialog *dlg = new RightClickDialog();
- dlg->execute();
+ int option = dlg->execute();
delete dlg;
+
+ if (option == 0)
+ CharacterDialog::show();
+ else if (option == 1)
+ HelpDialog::show();
}
/*--------------------------------------------------------------------------*/
@@ -1083,6 +1276,14 @@ void SceneActor::postInit(SceneObjectList *OwnerList) {
SceneObject::postInit();
}
+void SceneActor::remove() {
+ R2_GLOBALS._sceneItems.remove(this);
+ _shadowMap = NULL;
+ _linkedActor = NULL;
+
+ SceneObject::remove();
+}
+
bool SceneActor::startAction(CursorType action, Event &event) {
bool handled = true;
@@ -1115,13 +1316,20 @@ bool SceneActor::startAction(CursorType action, Event &event) {
return handled;
}
+GfxSurface SceneActor::getFrame() {
+ GfxSurface frame = SceneObject::getFrame();
+
+ return frame;
+}
+
/*--------------------------------------------------------------------------*/
-SceneArea::SceneArea(): EventHandler() {
+SceneArea::SceneArea(): SceneItem() {
_enabled = true;
_insideArea = false;
_savedCursorNum = CURSOR_NONE;
_cursorState = 0;
+ _cursorNum = CURSOR_NONE;
}
void SceneArea::synchronize(Serializer &s) {
@@ -1130,8 +1338,8 @@ void SceneArea::synchronize(Serializer &s) {
_bounds.synchronize(s);
s.syncAsSint16LE(_enabled);
s.syncAsSint16LE(_insideArea);
- s.syncAsSint16LE(_cursorNum);
- s.syncAsSint16LE(_savedCursorNum);
+ s.syncAsSint32LE(_cursorNum);
+ s.syncAsSint32LE(_savedCursorNum);
s.syncAsSint16LE(_cursorState);
}
@@ -1140,10 +1348,13 @@ void SceneArea::remove() {
}
void SceneArea::process(Event &event) {
+ Common::Point mousePos = event.mousePos;
+ mousePos.x += R2_GLOBALS._sceneManager._scene->_sceneBounds.left;
+
if (!R2_GLOBALS._insetUp && _enabled && R2_GLOBALS._events.isCursorVisible()) {
CursorType cursor = R2_GLOBALS._events.getCursor();
- if (_bounds.contains(event.mousePos)) {
+ if (_bounds.contains(mousePos)) {
// Cursor moving in bounded area
if (cursor != _cursorNum) {
_savedCursorNum = cursor;
@@ -1151,7 +1362,7 @@ void SceneArea::process(Event &event) {
R2_GLOBALS._events.setCursor(_cursorNum);
}
_insideArea = true;
- } else if ((event.mousePos.y < 171) && _insideArea && (_cursorNum == cursor) &&
+ } else if ((mousePos.y < 171) && _insideArea && (_cursorNum == cursor) &&
(_savedCursorNum != CURSOR_NONE)) {
// Cursor moved outside bounded area
R2_GLOBALS._events.setCursor(_savedCursorNum);
@@ -1171,6 +1382,8 @@ void SceneArea::setDetails(const Rect &bounds, CursorType cursor) {
SceneExit::SceneExit(): SceneArea() {
_moving = false;
_destPos = Common::Point(-1, -1);
+
+ _sceneNumber = 0;
}
void SceneExit::synchronize(Serializer &s) {
@@ -1191,20 +1404,23 @@ void SceneExit::changeScene() {
}
void SceneExit::process(Event &event) {
+ Common::Point mousePos = event.mousePos;
+ mousePos.x += R2_GLOBALS._sceneManager._scene->_sceneBounds.left;
+
if (!R2_GLOBALS._insetUp) {
SceneArea::process(event);
if (_enabled) {
if (event.eventType == EVENT_BUTTON_DOWN) {
- if (!_bounds.contains(event.mousePos))
+ if (!_bounds.contains(mousePos))
_moving = false;
else if (!R2_GLOBALS._player._canWalk) {
_moving = false;
changeScene();
event.handled = true;
} else {
- Common::Point dest((_destPos.x == -1) ? event.mousePos.x : _destPos.x,
- (_destPos.y == -1) ? event.mousePos.y : _destPos.y);
+ Common::Point dest((_destPos.x == -1) ? mousePos.x : _destPos.x,
+ (_destPos.y == -1) ? mousePos.y : _destPos.y);
ADD_PLAYER_MOVER(dest.x, dest.y);
_moving = true;
@@ -1221,6 +1437,7 @@ void SceneExit::process(Event &event) {
/*--------------------------------------------------------------------------*/
void SceneAreaObject::remove() {
+ R2_GLOBALS._sceneItems.remove(this);
_object1.remove();
SceneArea::remove();
--R2_GLOBALS._insetUp;
@@ -1230,19 +1447,22 @@ void SceneAreaObject::process(Event &event) {
if (_insetCount == R2_GLOBALS._insetUp) {
CursorType cursor = R2_GLOBALS._events.getCursor();
- if (_bounds.contains(event.mousePos)) {
+ if (_object1._bounds.contains(event.mousePos)) {
// Cursor moving in bounded area
if (cursor == _cursorNum) {
R2_GLOBALS._events.setCursor(_savedCursorNum);
}
} else if (event.mousePos.y < 168) {
- if (_cursorNum != cursor)
+ if (_cursorNum != cursor) {
// Cursor moved outside bounded area
- R2_GLOBALS._events.setCursor(_savedCursorNum);
+ _savedCursorNum = R2_GLOBALS._events.getCursor();
+ R2_GLOBALS._events.setCursor(CURSOR_INVALID);
+ }
if (event.eventType == EVENT_BUTTON_DOWN) {
- R2_GLOBALS._events.setCursor(_savedCursorNum);
event.handled = true;
+ R2_GLOBALS._events.setCursor(_savedCursorNum);
+ remove();
}
}
}
@@ -1262,293 +1482,214 @@ void SceneAreaObject::setDetails(int visage, int strip, int frameNumber, const C
}
void SceneAreaObject::setDetails(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- ((SceneHotspot *)(this))->setDetails(resNum, lookLineNum, talkLineNum, useLineNum,
+ _object1.setDetails(resNum, lookLineNum, talkLineNum, useLineNum,
2, (SceneItem *)NULL);
}
/*****************************************************************************/
-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 = 0;
}
-void UnkObject1200::synchronize(Serializer &s) {
- SavedObject::synchronize(s);
+MazeUI::~MazeUI() {
+ DEALLOCATE(_mapData);
+}
- _rect1.synchronize(s);
- _rect2.synchronize(s);
+void MazeUI::synchronize(Serializer &s) {
+ SceneObject::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);
-void UnkObject1200::sub51AE9(int arg1) {
- warning("STUB: UnkObject1200::sub51AE9()");
+ int dummy = 0;
+ s.syncAsSint16LE(dummy);
}
-int UnkObject1200::sub51AF8(Common::Point pt) {
- if (!_rect1.contains(pt))
- return -1;
+void MazeUI::load(int resNum) {
+ clear();
+ _resNum = resNum;
- int tmp1 = (pt.x - _rect1.left + _field2E) / _field2A;
- int tmp2 = (pt.y - _rect1.top + _field30) / _field2C;
+ const byte *header = g_resourceManager->getResource(RT17, resNum, 0);
- if ((tmp1 >= 0) && (tmp2 >= 0) && (_field26 > tmp1) && (_field28 > tmp2))
- return _field16[(((_field26 * tmp2) + tmp1)* 2)];
+ _cellsResNum = resNum + 1000;
+ _mapCells.x = READ_LE_UINT16(header + 2);
+ _mapCells.y = READ_LE_UINT16(header + 4);
+ _frameCount = 10;
+ _resCount = _frameCount << 3;
- return -1;
+ Visage visage;
+ visage.setVisage(_cellsResNum, 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, plus one extra cell
+ // to allow for partial cell scrolling on-screen on the left/right sides
+ 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) {
@@ -1563,6 +1704,12 @@ void AnimationSlice::load(Common::File &f) {
AnimationSlices::AnimationSlices() {
_pixelData = NULL;
+
+ _dataSize = 0;
+ _dataSize2 = 0;
+ _slices->_sliceOffset = 0;
+ _slices->_drawMode = 0;
+ _slices->_secondaryIndex = 0;
}
AnimationSlices::~AnimationSlices() {
@@ -1624,10 +1771,21 @@ AnimationPlayer::AnimationPlayer(): EventHandler() {
_screenBounds = R2_GLOBALS._gfxManagerInstance._bounds;
_rect1 = R2_GLOBALS._gfxManagerInstance._bounds;
_paletteMode = ANIMPALMODE_REPLACE_PALETTE;
- _field3A = 1;
+ _canSkip = true;
_sliceHeight = 1;
- _field58 = 1;
_endAction = NULL;
+
+ _sliceCurrent = nullptr;
+ _sliceNext = nullptr;
+ _animLoaded = false;
+ _objectMode = ANIMOBJMODE_1;
+ _dataNeeded = 0;
+ _playbackTick = 0;
+ _playbackTickPrior = 0;
+ _position = 0;
+ _nextSlicesPosition = 0;
+ _frameDelay = 0;
+ _gameFrame = 0;
}
AnimationPlayer::~AnimationPlayer() {
@@ -1637,7 +1795,9 @@ AnimationPlayer::~AnimationPlayer() {
void AnimationPlayer::synchronize(Serializer &s) {
EventHandler::synchronize(s);
- warning("TODO AnimationPlayer::load");
+
+ // TODO: Implement saving for animation player state. Currently, I disable saving
+ // when an animation is active, so saving it's state would a "nice to have".
}
void AnimationPlayer::remove() {
@@ -1648,8 +1808,7 @@ void AnimationPlayer::remove() {
}
void AnimationPlayer::process(Event &event) {
- if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE) &&
- (_field3A)) {
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE) && _canSkip) {
// Move the current position to the end
_position = _subData._duration;
}
@@ -1695,11 +1854,13 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
_playbackTickPrior = -1;
_playbackTick = 0;
- // The final multiplication is used to deliberately slow down playback, since the original
- // was slowed down by the amount of time spent to decode and display the frames
- _frameDelay = (60 / _subData._frameRate) * 8;
+ _frameDelay = (60 / _subData._frameRate);
_gameFrame = R2_GLOBALS._events.getFrameNumber();
+ // WORKAROUND: Slow down the title sequences to better match the original
+ if (animId <= 4 || animId == 15)
+ _frameDelay *= 8;
+
if (_subData._totalSize) {
_dataNeeded = _subData._totalSize;
} else {
@@ -1755,7 +1916,7 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
default:
// ANIMPALMODE_CURR_PALETTE
- // Use the closest matching colours in the currently active palette to those specified in the animation
+ // Use the closest matching colors in the currently active palette to those specified in the animation
for (int idx = _subData._palStart; idx < (_subData._palStart + _subData._palSize); ++idx) {
byte r = _subData._palData[idx * 3];
byte g = _subData._palData[idx * 3 + 1];
@@ -1768,7 +1929,7 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
}
++R2_GLOBALS._animationCtr;
- _field38 = 1;
+ _animLoaded = true;
return true;
}
@@ -1865,7 +2026,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
// Unlock the screen surface
R2_GLOBALS._screenSurface.unlockSurface();
- if (_objectMode == 42) {
+ if (_objectMode == ANIMOBJMODE_42) {
_screenBounds.expandPanes();
// Copy the drawn frame to the back surface
@@ -1915,7 +2076,7 @@ bool AnimationPlayer::isCompleted() {
}
void AnimationPlayer::close() {
- if (_field38) {
+ if (_animLoaded) {
switch (_paletteMode) {
case 0:
R2_GLOBALS._scenePalette.replace(&_palette);
@@ -1934,7 +2095,7 @@ void AnimationPlayer::close() {
// Close the resource file
_resourceFile.close();
- if (_objectMode != 42) {
+ if (_objectMode != ANIMOBJMODE_42) {
// flip screen in original
}
@@ -1944,9 +2105,9 @@ void AnimationPlayer::close() {
_animData1 = NULL;
_animData2 = NULL;
- _field38 = 0;
+ _animLoaded = false;
if (g_globals != NULL)
- R2_GLOBALS._animationCtr = MAX(R2_GLOBALS._animationCtr, 0);
+ R2_GLOBALS._animationCtr = MAX(R2_GLOBALS._animationCtr - 1, 0);
}
void AnimationPlayer::rleDecode(const byte *pSrc, byte *pDest, int size) {
@@ -1992,15 +2153,358 @@ void AnimationPlayer::getSlices() {
/*--------------------------------------------------------------------------*/
AnimationPlayerExt::AnimationPlayerExt(): AnimationPlayer() {
- _v = 0;
- _field3A = 0;
+ _isActive = false;
+ _canSkip = false;
}
void AnimationPlayerExt::synchronize(Serializer &s) {
AnimationPlayer::synchronize(s);
- s.syncAsSint16LE(_v);
+ s.syncAsSint16LE(_isActive);
+}
+
+/*--------------------------------------------------------------------------*/
+
+ModalWindow::ModalWindow() {
+ _insetCount = 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(_insetCount);
+}
+
+void ModalWindow::process(Event &event) {
+ if (_insetCount != 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::setup2(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;
+ _insetCount = R2_GLOBALS._insetUp;
+}
+
+void ModalWindow::setup3(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._s1550PlayerArea[R2_QUINN].x + 145,
+ R2_GLOBALS._s1550PlayerArea[R2_QUINN].y + 59));
+ scanner._obj5.fixPriority(257);
+
+ scanner._obj6.postInit();
+ scanner._obj6.setup(4, 4, 2);
+ scanner._obj6.setPosition(Common::Point(R2_GLOBALS._s1550PlayerArea[R2_SEEKER].x + 145,
+ R2_GLOBALS._s1550PlayerArea[R2_SEEKER].y + 59));
+ scanner._obj6.fixPriority(257);
+ break;
+ case 1700:
+ case 1800:
+ if (R2_GLOBALS._rimLocation < 1201)
+ scanner._obj4.setup(4, 3, 3);
+ else if (R2_GLOBALS._rimLocation < 1201)
+ scanner._obj4.setup(4, 3, 4);
+ else
+ scanner._obj4.setup(4, 3, 5);
+ break;
+ case 3800:
+ case 3900:
+ if ((R2_GLOBALS._desertWrongDirCtr + 1) == 0 && R2_GLOBALS._desertCorrectDirection == 0) {
+ do {
+ R2_GLOBALS._desertCorrectDirection = R2_GLOBALS._randomSource.getRandomNumber(3) + 1;
+ } while (R2_GLOBALS._desertCorrectDirection == R2_GLOBALS._desertPreviousDirection);
+ }
+
+ scanner._obj4.setup(4, 7, R2_GLOBALS._desertCorrectDirection);
+ 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_WALK : 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::setup2(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::setup2(visage, stripFrameNum, frameNum, posX, posY);
+
+ setup3(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..c9695c921d 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.h
+++ b/engines/tsage/ringworld2/ringworld2_logic.h
@@ -42,9 +42,8 @@ public:
static Scene *createScene(int sceneNumber);
};
-class SceneArea: public EventHandler {
+class SceneArea: public SceneItem {
public:
- Rect _bounds;
bool _enabled;
bool _insideArea;
CursorType _cursorNum;
@@ -54,9 +53,12 @@ public:
SceneArea();
void setDetails(const Rect &bounds, CursorType cursor);
+ virtual Common::String getClassName() { return "SceneArea"; }
virtual void synchronize(Serializer &s);
virtual void remove();
virtual void process(Event &event);
+ virtual bool startAction(CursorType action, Event &event) { return false; }
+ virtual void doAction(int action) {}
};
class SceneExit: public SceneArea {
@@ -79,27 +81,23 @@ private:
static void startStrip();
static void endStrip();
public:
- byte _field312[256];
- int _field372;
+ byte _shadowPaletteMap[256];
bool _savedPlayerEnabled;
bool _savedUiEnabled;
bool _savedCanWalk;
- int _field37A;
+ bool _preventSaving;
- SceneObject *_focusObject;
Visage _cursorVisage;
- SynchronizedList<SceneArea *> _sceneAreas;
-
- Rect _v51C34;
+ SynchronizedList<EventHandler *> _sceneAreas;
public:
SceneExt();
virtual Common::String getClassName() { return "SceneExt"; }
+ virtual void synchronize(Serializer &s);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void process(Event &event);
virtual void dispatch();
- virtual void loadScene(int sceneNum);
virtual void refreshBackground(int xAmount, int yAmount);
virtual void saveCharacter(int characterIndex);
virtual void restore() {}
@@ -108,12 +106,14 @@ public:
void fadeOut();
void clearScreen();
void scalePalette(int RFactor, int GFactor, int BFactor);
+ void loadBlankScene();
};
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,60 +159,63 @@ public:
/*--------------------------------------------------------------------------*/
class Ringworld2InvObjectList : public InvObjectList {
+private:
+ static bool SelectItem(int objectNumber);
+ static void selectDefault(int obectNumber);
public:
InvObject _none;
- InvObject _inv1;
- InvObject _inv2;
+ InvObject _optoDisk;
+ InvObject _reader;
InvObject _negatorGun;
InvObject _steppingDisks;
- InvObject _inv5;
- InvObject _inv6;
- InvObject _inv7;
- InvObject _inv8;
- InvObject _inv9;
- InvObject _inv10;
- InvObject _inv11;
- InvObject _inv12;
- InvObject _inv13;
- InvObject _inv14;
- InvObject _inv15;
- InvObject _inv16;
- InvObject _inv17;
- InvObject _inv18;
- InvObject _inv19;
- InvObject _inv20;
- InvObject _inv21;
- InvObject _inv22;
- InvObject _inv23;
- InvObject _inv24;
- InvObject _inv25;
- InvObject _inv26;
- InvObject _inv27;
- InvObject _inv28;
- InvObject _inv29;
- InvObject _inv30;
- InvObject _inv31;
- InvObject _inv32;
- InvObject _inv33;
- InvObject _inv34;
- InvObject _inv35;
- InvObject _inv36;
- InvObject _inv37;
- InvObject _inv38;
- InvObject _inv39;
- InvObject _inv40;
- InvObject _inv41;
- InvObject _inv42;
- InvObject _inv43;
- InvObject _inv44;
- InvObject _inv45;
- InvObject _inv46;
- InvObject _inv47;
- InvObject _inv48;
- InvObject _inv49;
- InvObject _inv50;
- InvObject _inv51;
- InvObject _inv52;
+ InvObject _attractorUnit;
+ InvObject _sensorProbe;
+ InvObject _sonicStunner;
+ InvObject _cableHarness;
+ InvObject _comScanner;
+ InvObject _spentPowerCapsule; // 10
+ InvObject _chargedPowerCapsule;
+ InvObject _aerosol;
+ InvObject _remoteControl;
+ InvObject _opticalFibre;
+ InvObject _clamp;
+ InvObject _attractorHarness;
+ InvObject _fuelCell;
+ InvObject _gyroscope;
+ InvObject _airbag;
+ InvObject _rebreatherTank; // 20
+ InvObject _reserveTank;
+ InvObject _guidanceModule;
+ InvObject _thrusterValve;
+ InvObject _balloonBackpack;
+ InvObject _radarMechanism;
+ InvObject _joystick;
+ InvObject _ignitor;
+ InvObject _diagnosticsDisplay;
+ InvObject _glassDome;
+ InvObject _wickLamp; // 30
+ InvObject _scrithKey;
+ InvObject _tannerMask;
+ InvObject _pureGrainAlcohol;
+ InvObject _blueSapphire;
+ InvObject _ancientScrolls;
+ InvObject _flute;
+ InvObject _gunpowder;
+ InvObject _unused;
+ InvObject _comScanner2;
+ InvObject _superconductorWire; // 40
+ InvObject _pillow;
+ InvObject _foodTray;
+ InvObject _laserHacksaw;
+ InvObject _photonStunner;
+ InvObject _battery;
+ InvObject _soakedFaceMask;
+ InvObject _lightBulb;
+ InvObject _alcoholLamp1;
+ InvObject _alcoholLamp2;
+ InvObject _alocholLamp3; // 50
+ InvObject _brokenDisplay;
+ InvObject _toolbox;
Ringworld2InvObjectList();
void reset();
@@ -226,6 +229,7 @@ public:
class Ringworld2Game: public Game {
public:
virtual void start();
+ virtual void restartGame();
virtual void restart();
virtual void endGame(int resNum, int lineNum);
@@ -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,48 @@ 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;
+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 +338,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 {
@@ -378,6 +391,8 @@ public:
enum AnimationPaletteMode { ANIMPALMODE_REPLACE_PALETTE = 0, ANIMPALMODE_CURR_PALETTE = 1,
ANIMPALMODE_NONE = 2 };
+enum AnimationObjectMode { ANIMOBJMODE_1 = 1, ANIMOBJMODE_2 = 2, ANIMOBJMODE_42 = 42 };
+
class AnimationPlayer: public EventHandler {
private:
void rleDecode(const byte *pSrc, byte *pDest, int size);
@@ -391,10 +406,11 @@ public:
AnimationData *_sliceNext;
Common::File _resourceFile;
Rect _rect1, _screenBounds;
- int _field38;
- int _field3A, _paletteMode;
- int _objectMode;
- int _field58, _sliceHeight;
+ bool _animLoaded;
+ bool _canSkip;
+ AnimationPaletteMode _paletteMode;
+ AnimationObjectMode _objectMode;
+ int _sliceHeight;
byte _palIndexes[256];
ScenePalette _palette;
AnimationPlayerSubData _subData;
@@ -418,6 +434,7 @@ public:
virtual void changePane() {}
virtual void closing() {}
+
bool load(int animId, Action *endAction = NULL);
bool isCompleted();
void close();
@@ -425,13 +442,81 @@ public:
class AnimationPlayerExt: public AnimationPlayer {
public:
- int _v;
+ bool _isActive;
public:
AnimationPlayerExt();
virtual void synchronize(Serializer &s);
};
+class ModalWindow: public SceneArea {
+public:
+ SceneActor _object1;
+ int _insetCount;
+public:
+ ModalWindow();
+
+ virtual void remove();
+ virtual void synchronize(Serializer &s);
+ virtual Common::String getClassName() { return "ModalWindow"; }
+ virtual void process(Event &event);
+ virtual void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY);
+ virtual void setup3(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();
+ virtual void setup2(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..2592bde19a 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -31,6 +31,11 @@ namespace TsAGE {
namespace Ringworld2 {
+/*--------------------------------------------------------------------------
+ * Scene 50 - Waking up cutscene
+ *
+ *--------------------------------------------------------------------------*/
+
void Scene50::Action1::signal() {
switch (_actionIndex++) {
case 0:
@@ -48,8 +53,8 @@ void Scene50::Action1::signal() {
}
void Scene50::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit(OwnerList);
loadScene(110);
+ SceneExt::postInit(OwnerList);
R2_GLOBALS._uiElements._active = false;
R2_GLOBALS._scenePalette.loadPalette(0);
@@ -111,7 +116,7 @@ bool Scene100::Table::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
if (_strip == 2) {
scene->_sceneMode = 108;
- scene->_object3.postInit();
+ scene->_tableLocker.postInit();
scene->_stasisNegator.postInit();
if (R2_INVENTORY.getObjectScene(R2_NEGATOR_GUN) == 1) {
@@ -121,11 +126,13 @@ bool Scene100::Table::startAction(CursorType action, Event &event) {
scene->_stasisNegator.setDetails(100, 21, 22, 23, 2, (SceneItem *)NULL);
}
- scene->setAction(&scene->_sequenceManager2, scene, 108, this, &scene->_object3,
+ // Open table locker
+ scene->setAction(&scene->_sequenceManager2, scene, 108, this, &scene->_tableLocker,
&scene->_stasisNegator, &R2_GLOBALS._player, NULL);
} else {
scene->_sceneMode = 109;
- scene->setAction(&scene->_sequenceManager2, scene, 109, this, &scene->_object3,
+ // Close table locker
+ scene->setAction(&scene->_sequenceManager2, scene, 109, this, &scene->_tableLocker,
&scene->_stasisNegator, &R2_GLOBALS._player, NULL);
}
return true;
@@ -135,7 +142,7 @@ bool Scene100::Table::startAction(CursorType action, Event &event) {
if (_strip == 2) {
SceneItem::display2(100, 18);
scene->_sceneMode = 102;
- scene->_object3.postInit();
+ scene->_tableLocker.postInit();
scene->_stasisNegator.postInit();
if (R2_INVENTORY.getObjectScene(R2_NEGATOR_GUN) == 1) {
@@ -145,12 +152,12 @@ bool Scene100::Table::startAction(CursorType action, Event &event) {
scene->_stasisNegator.setDetails(100, 21, 22, 23, 2, (SceneItem *)NULL);
}
- scene->setAction(&scene->_sequenceManager2, scene, 102, this, &scene->_object3,
+ scene->setAction(&scene->_sequenceManager2, scene, 102, this, &scene->_tableLocker,
&scene->_stasisNegator, NULL);
} else {
SceneItem::display2(100, 19);
scene->_sceneMode = 103;
- scene->setAction(&scene->_sequenceManager2, scene, 103, this, &scene->_object3,
+ scene->setAction(&scene->_sequenceManager2, scene, 103, this, &scene->_tableLocker,
&scene->_stasisNegator, NULL);
}
return true;
@@ -160,22 +167,21 @@ bool Scene100::Table::startAction(CursorType action, Event &event) {
}
bool Scene100::StasisNegator::startAction(CursorType action, Event &event) {
- Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 107;
scene->setAction(&scene->_sequenceManager1, scene, 107, &R2_GLOBALS._player, &scene->_stasisNegator, NULL);
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
}
bool Scene100::DoorDisplay::startAction(CursorType action, Event &event) {
- Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
case CURSOR_LOOK:
SceneItem::display2(100, _state ? 24 : 25);
@@ -183,25 +189,29 @@ bool Scene100::DoorDisplay::startAction(CursorType action, Event &event) {
case CURSOR_TALK:
SceneItem::display2(100, _state ? 26 : 27);
return true;
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 110;
scene->setAction(&scene->_sequenceManager1, scene, 110, &R2_GLOBALS._player, NULL);
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
}
bool Scene100::SteppingDisks::startAction(CursorType action, Event &event) {
- Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 111;
scene->setAction(&scene->_sequenceManager1, scene, 111, &R2_GLOBALS._player, this, NULL);
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
@@ -210,14 +220,15 @@ bool Scene100::SteppingDisks::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
bool Scene100::Terminal::startAction(CursorType action, Event &event) {
- Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 105;
scene->setAction(&scene->_sequenceManager1, scene, 105, &R2_GLOBALS._player, this, NULL);
return true;
+ }
default:
return NamedHotspot::startAction(action, event);
}
@@ -226,9 +237,8 @@ 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);
@@ -291,10 +301,10 @@ void Scene100::postInit(SceneObjectList *OwnerList) {
switch (R2_GLOBALS._sceneManager._previousScene) {
case 50:
case 180:
- _object5.postInit();
- _object4.postInit();
+ _wardrobeColorAnim.postInit();
+ _wardrobeTopAnim.postInit();
_sceneMode = 104;
- setAction(&_sequenceManager1, this, 104, &R2_GLOBALS._player, &_wardrobe, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager1, this, 104, &R2_GLOBALS._player, &_wardrobe, &_wardrobeTopAnim, &_wardrobeColorAnim, NULL);
break;
case 125:
_sceneMode = 100;
@@ -327,14 +337,14 @@ void Scene100::signal() {
_table.setStrip(2);
_table.setFrame(3);
- _object3.remove();
+ _tableLocker.remove();
_stasisNegator.remove();
R2_GLOBALS._player.enableControl();
break;
case 104:
_sceneMode = 0;
- _object5.remove();
- _object4.remove();
+ _wardrobeColorAnim.remove();
+ _wardrobeTopAnim.remove();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player._numFrames = 10;
@@ -383,7 +393,7 @@ void Scene100::dispatch() {
SceneExt::dispatch();
if ((_sceneMode == 101) && (_door._frame == 2) && (_table._strip == 5)) {
- _table.setAction(&_sequenceManager2, NULL, 103, &_table, &_object3, &_stasisNegator, NULL);
+ _table.setAction(&_sequenceManager2, NULL, 103, &_table, &_tableLocker, &_stasisNegator, NULL);
}
}
@@ -392,27 +402,27 @@ void Scene100::dispatch() {
*
*--------------------------------------------------------------------------*/
-bool Scene125::Object5::startAction(CursorType action, Event &event) {
+bool Scene125::Food::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE)
return true;
- else
- return SceneActor::startAction(action, event);
+
+ return SceneActor::startAction(action, event);
}
/*--------------------------------------------------------------------------*/
Scene125::Icon::Icon(): SceneActor() {
_lookLineNum = 0;
- _field98 = 0;
+ _iconId = 0;
_pressed = false;
}
void Scene125::Icon::postInit(SceneObjectList *OwnerList) {
SceneObject::postInit();
- _object1.postInit();
- _object1.fixPriority(255);
- _object1.hide();
+ _glyph.postInit();
+ _glyph.fixPriority(255);
+ _glyph.hide();
_sceneText1._color1 = 92;
_sceneText1._color2 = 0;
@@ -426,7 +436,7 @@ void Scene125::Icon::postInit(SceneObjectList *OwnerList) {
void Scene125::Icon::synchronize(Serializer &s) {
SceneActor::synchronize(s);
s.syncAsSint16LE(_lookLineNum);
- s.syncAsSint16LE(_field98);
+ s.syncAsSint16LE(_iconId);
s.syncAsSint16LE(_pressed);
}
@@ -455,15 +465,15 @@ void Scene125::Icon::process(Event &event) {
scene->_sound1.play(14);
setFrame(2);
- switch (_object1._strip) {
+ switch (_glyph._strip) {
case 1:
- _object1.setStrip(2);
+ _glyph.setStrip(2);
break;
case 3:
- _object1.setStrip(4);
+ _glyph.setStrip(4);
break;
case 5:
- _object1.setStrip(6);
+ _glyph.setStrip(6);
break;
default:
break;
@@ -482,15 +492,15 @@ void Scene125::Icon::process(Event &event) {
if ((event.eventType == EVENT_BUTTON_UP) && _pressed) {
setFrame(1);
- switch (_object1._strip) {
+ switch (_glyph._strip) {
case 2:
- _object1.setStrip(1);
+ _glyph.setStrip(1);
break;
case 4:
- _object1.setStrip(3);
+ _glyph.setStrip(3);
break;
case 6:
- _object1.setStrip(5);
+ _glyph.setStrip(5);
break;
default:
break;
@@ -504,18 +514,18 @@ void Scene125::Icon::process(Event &event) {
}
void Scene125::Icon::setIcon(int id) {
- Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene;
-
- _lookLineNum = _field98 = id;
+ _lookLineNum = _iconId = id;
SceneActor::_lookLineNum = id;
_sceneText1.remove();
_sceneText2.remove();
if (_lookLineNum) {
+ Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene;
+
showIcon();
- _object1.setup(161, ((id - 1) / 10) * 2 + 1, ((id - 1) % 10) + 1);
- _object1.setPosition(_position);
+ _glyph.setup(161, ((id - 1) / 10) * 2 + 1, ((id - 1) % 10) + 1);
+ _glyph.setPosition(_position);
_sceneText1._fontNumber = scene->_iconFontNumber;
_sceneText1.setup(CONSOLE125_MESSAGES[id]);
@@ -558,38 +568,38 @@ void Scene125::Icon::setIcon(int id) {
void Scene125::Icon::showIcon() {
_sceneText1.show();
_sceneText2.show();
- _object1.show();
- _object2.show();
+ _glyph.show();
+ _horizLine.show();
show();
}
void Scene125::Icon::hideIcon() {
_sceneText1.hide();
_sceneText2.hide();
- _object1.hide();
- _object2.hide();
+ _glyph.hide();
+ _horizLine.hide();
hide();
}
/*--------------------------------------------------------------------------*/
-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]) {
+ if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[R2_QUINN]) {
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;
@@ -613,29 +623,29 @@ Scene125::Scene125(): SceneExt() {
}
void Scene125::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(160);
+ SceneExt::postInit();
_palette.loadPalette(0);
if (R2_GLOBALS._sceneManager._previousScene != 125)
// Save the prior scene to return to when the console is turned off
- R2_GLOBALS._player._oldCharacterScene[1] = R2_GLOBALS._sceneManager._previousScene;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = R2_GLOBALS._sceneManager._previousScene;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.hide();
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));
+ if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[R2_QUINN]) {
+ _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));
+ _foodDispenser.postInit();
+ _foodDispenser.setup(162, 1, 1);
+ _foodDispenser.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);
@@ -656,34 +666,34 @@ void Scene125::signal() {
_icon4.postInit();
_icon4._sceneRegionId = 5;
- _sceneMode = 2;
setAction(&_sequenceManager, this, 127, &_icon1, &_icon2, &_icon3, &_icon4, &R2_GLOBALS._player, NULL);
+ _sceneMode = 2;
break;
case 2:
_icon1.setup(160, 1, 1);
_icon1.setPosition(Common::Point(65, 17));
- _icon1._object2.postInit();
- _icon1._object2.setup(160, 7, 1);
- _icon1._object2.setPosition(Common::Point(106, 41));
+ _icon1._horizLine.postInit();
+ _icon1._horizLine.setup(160, 7, 1);
+ _icon1._horizLine.setPosition(Common::Point(106, 41));
_icon2.setup(160, 1, 1);
_icon2.setPosition(Common::Point(80, 32));
- _icon2._object2.postInit();
- _icon2._object2.setup(160, 7, 2);
- _icon2._object2.setPosition(Common::Point(106, 56));
+ _icon2._horizLine.postInit();
+ _icon2._horizLine.setup(160, 7, 2);
+ _icon2._horizLine.setPosition(Common::Point(106, 56));
_icon3.setup(160, 1, 1);
_icon3.setPosition(Common::Point(65, 47));
- _icon3._object2.postInit();
- _icon3._object2.setup(160, 7, 1);
- _icon3._object2.setPosition(Common::Point(106, 71));
+ _icon3._horizLine.postInit();
+ _icon3._horizLine.setup(160, 7, 1);
+ _icon3._horizLine.setPosition(Common::Point(106, 71));
_icon4.setup(160, 1, 1);
_icon4.setPosition(Common::Point(80, 62));
_icon4._sceneRegionId = 5;
- _icon4._object2.postInit();
- _icon4._object2.setup(160, 7, 2);
- _icon4._object2.setPosition(Common::Point(106, 86));
+ _icon4._horizLine.postInit();
+ _icon4._horizLine.setup(160, 7, 2);
+ _icon4._horizLine.setPosition(Common::Point(106, 86));
_icon5.postInit();
_icon5.setup(160, 1, 1);
@@ -698,24 +708,27 @@ void Scene125::signal() {
_icon6._sceneRegionId = 8;
consoleAction(5);
- R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
break;
case 10:
- switch (_consoleMode) {
+ switch (_consoleMode) {
case 12:
_sceneMode = 129;
- _object1.postInit();
- _object2.postInit();
- _object3.postInit();
+ _starchart1.postInit();
+ _starchart2.postInit();
+ _starchart3.postInit();
if (R2_GLOBALS.getFlag(13)) {
- _object4.postInit();
- setAction(&_sequenceManager, this, 130, &R2_GLOBALS._player, &_object1, &_object2,
- &_object3, &_object4, NULL);
+ // Show starchart with Ringworld present
+ _starchart4.postInit();
+ setAction(&_sequenceManager, this, 130, &R2_GLOBALS._player, &_starchart1, &_starchart2,
+ &_starchart3, &_starchart4, NULL);
} else {
- setAction(&_sequenceManager, this, 129, &R2_GLOBALS._player, &_object1, &_object2, &_object3, NULL);
+ // Show starchart without Ringworld
+ setAction(&_sequenceManager, this, 129, &R2_GLOBALS._player, &_starchart1, &_starchart2,
+ &_starchart3, NULL);
}
break;
case 13:
@@ -772,7 +785,7 @@ void Scene125::signal() {
case 12:
if (_soundCount > 0)
--_soundCount;
- if (!_soundCount || (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
+ if (!_soundCount || !(R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
_soundIndex = 0;
R2_GLOBALS._playStream.stop();
} else {
@@ -781,11 +794,12 @@ void Scene125::signal() {
}
break;
case 125:
- R2_INVENTORY.setObjectScene(R2_OPTO_DISK, R2_GLOBALS._player._oldCharacterScene[1]);
+ R2_INVENTORY.setObjectScene(R2_OPTO_DISK, R2_GLOBALS._player._oldCharacterScene[R2_QUINN]);
+ 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;
@@ -831,7 +845,7 @@ void Scene125::process(Event &event) {
void Scene125::dispatch() {
if (_soundCount)
- R2_GLOBALS._playStream.proc1();
+ R2_GLOBALS._playStream.dispatch();
Scene::dispatch();
}
@@ -882,7 +896,7 @@ void Scene125::consoleAction(int id) {
_icon2.setIcon(23);
break;
case 6:
- R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._oldCharacterScene[1]);
+ R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._oldCharacterScene[R2_QUINN]);
break;
case 7:
if (_consoleMode == 11)
@@ -915,7 +929,7 @@ void Scene125::consoleAction(int id) {
_icon4.setPosition(Common::Point(52, 107));
_icon4._sceneRegionId = 9;
_icon4.setIcon(25);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
_icon6.setIcon(26);
_sceneMode = 10;
@@ -945,7 +959,7 @@ void Scene125::consoleAction(int id) {
break;
case 13:
consoleAction(2);
- if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) != R2_GLOBALS._player._oldCharacterScene[1]) {
+ if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) != R2_GLOBALS._player._oldCharacterScene[R2_QUINN]) {
SceneItem::display2(126, 17);
} else {
R2_GLOBALS._player.disableControl();
@@ -958,7 +972,7 @@ void Scene125::consoleAction(int id) {
_icon4.setPosition(Common::Point(52, 107));
_icon4._sceneRegionId = 9;
_icon4.setIcon(25);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
_icon6.setIcon(26);
_sceneMode = 10;
@@ -970,14 +984,17 @@ void Scene125::consoleAction(int id) {
case 15:
consoleAction(3);
- if (R2_GLOBALS._v565F5 < 3) {
+ if (R2_GLOBALS._foodCount < 3) {
R2_GLOBALS._player.disableControl();
- _object5.postInit();
- _object5.setup(162, 2, 2);
- _object5.setPosition(Common::Point(216, UI_INTERFACE_Y));
+ _food.postInit();
+ _food.setup(162, 2, 2);
+ _food.setPosition(Common::Point(216, UI_INTERFACE_Y));
+
+ R2_GLOBALS._foodCount += 2;
- R2_GLOBALS._v565F5 += 2;
- } else if (R2_GLOBALS._v565F5 == 3) {
+ _sceneMode = 128;
+ this->setAction(&_sequenceManager, this, 128, &_foodDispenser, &_food, NULL);
+ } else if (R2_GLOBALS._foodCount == 3) {
SceneItem::display2(126, 13);
} else {
SceneItem::display2(126, 14);
@@ -986,13 +1003,16 @@ void Scene125::consoleAction(int id) {
case 16:
consoleAction(3);
- if (R2_GLOBALS._v565F5 < 4) {
+ if (R2_GLOBALS._foodCount < 4) {
R2_GLOBALS._player.disableControl();
- _object5.postInit();
- _object5.setup(162, 2, 3);
- _object5.setPosition(Common::Point(218, UI_INTERFACE_Y));
+ _food.postInit();
+ _food.setup(162, 2, 3);
+ _food.setPosition(Common::Point(218, UI_INTERFACE_Y));
- ++R2_GLOBALS._v565F5;
+ ++R2_GLOBALS._foodCount;
+
+ _sceneMode = 128;
+ this->setAction(&_sequenceManager, this, 128, &_foodDispenser, &_food, NULL);
} else {
SceneItem::display2(126, 15);
}
@@ -1000,13 +1020,16 @@ void Scene125::consoleAction(int id) {
case 17:
consoleAction(3);
- if (R2_GLOBALS._v565F5 < 4) {
+ if (R2_GLOBALS._foodCount < 4) {
R2_GLOBALS._player.disableControl();
- _object5.postInit();
- _object5.setup(162, 2, 1);
- _object5.setPosition(Common::Point(215, UI_INTERFACE_Y));
+ _food.postInit();
+ _food.setup(162, 2, 1);
+ _food.setPosition(Common::Point(215, UI_INTERFACE_Y));
+
+ ++R2_GLOBALS._foodCount;
- ++R2_GLOBALS._v565F5;
+ _sceneMode = 128;
+ this->setAction(&_sequenceManager, this, 128, &_foodDispenser, &_food, NULL);
} else {
SceneItem::display2(126, 16);
}
@@ -1033,7 +1056,7 @@ void Scene125::consoleAction(int id) {
break;
case 24:
_icon4.setIcon(25);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
if (_consoleMode == 10) {
setDetails(127, --_logIndex);
@@ -1045,7 +1068,7 @@ void Scene125::consoleAction(int id) {
break;
case 25:
_icon4.setIcon(25);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
if (_consoleMode == 10) {
setDetails(127, ++_logIndex);
@@ -1063,10 +1086,10 @@ void Scene125::consoleAction(int id) {
_icon4.hideIcon();
R2_GLOBALS._player.hide();
- _object1.hide();
- _object2.hide();
- _object3.hide();
- _object4.hide();
+ _starchart1.hide();
+ _starchart2.hide();
+ _starchart3.hide();
+ _starchart4.hide();
_sceneMode = 11;
_palette.loadPalette(160);
@@ -1089,7 +1112,7 @@ void Scene125::consoleAction(int id) {
_icon4.setPosition(Common::Point(52, 107));
_icon4._sceneRegionId = 9;
_icon4.setIcon(25);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
_icon6.setIcon(26);
_sceneMode = 10;
@@ -1149,7 +1172,7 @@ void Scene125::setDetails(int resNum, int lineNum) {
if ((_soundCount > 0) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
_sceneMode = 12;
- R2_GLOBALS._playStream.play(_soundIndexes[_soundIndex], this);
+ R2_GLOBALS._playStream.play(_soundIndexes[_soundIndex++], this);
}
} else {
// Passed the start or end of the message set, so return to the menu
@@ -1203,8 +1226,8 @@ Common::String Scene125::parseMessage(const Common::String &msg) {
*--------------------------------------------------------------------------*/
void Scene150::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(100);
+ SceneExt::postInit();
_door.postInit();
_door._state = 0;
@@ -1410,8 +1433,9 @@ Scene160::Scene160(): SceneExt() {
}
void Scene160::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(4001);
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
R2_GLOBALS._player._uiEnabled = false;
R2_GLOBALS._player.enableControl();
@@ -1432,6 +1456,8 @@ void Scene160::synchronize(Serializer &s) {
s.syncAsSint16LE(_frameNumber);
s.syncAsSint16LE(_yChange);
s.syncAsSint16LE(_lineNum);
+
+ _creditsList.synchronize(s);
}
void Scene160::remove() {
@@ -1470,14 +1496,14 @@ void Scene180::Action1::signal() {
case 0:
case 1:
case 2:
- scene->_object5.setStrip((_actionIndex == 1) ? 1 : 2);
- scene->_object5.setFrame(1);
- scene->_object5.animate(ANIM_MODE_5, this);
+ scene->_shipDisplay.setStrip((_actionIndex == 1) ? 1 : 2);
+ scene->_shipDisplay.setFrame(1);
+ scene->_shipDisplay.animate(ANIM_MODE_5, this);
break;
case 4:
- scene->_object5.setStrip(3);
- scene->_object5.setFrame(1);
- scene->_object5.animate(ANIM_MODE_5, this);
+ scene->_shipDisplay.setStrip(3);
+ scene->_shipDisplay.setFrame(1);
+ scene->_shipDisplay.animate(ANIM_MODE_5, this);
_actionIndex = 0;
break;
}
@@ -1485,12 +1511,10 @@ void Scene180::Action1::signal() {
/*--------------------------------------------------------------------------*/
-Scene180::Scene180(): SceneExt(), _webbsterSpeaker(27) {
- _field412 = 0;
+Scene180::Scene180(): SceneExt() {
+ _helpEnabled = false;
_frameInc = 0;
_frameNumber = R2_GLOBALS._events.getFrameNumber();
- _field480 = 1;
- _field482 = -1;
_fontNumber = R2_GLOBALS.gfxManager()._font._fontNumber;
GfxFont font;
@@ -1521,6 +1545,9 @@ void Scene180::remove() {
// _stripManager._field2EA = -1;
SceneExt::remove();
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._scenePalette.setEntry(255, 255, 255, 255);
+
R2_GLOBALS._events.setCursor(CURSOR_WALK);
// word_575F7 = 0;
R2_GLOBALS._playStream.stop();
@@ -1532,9 +1559,7 @@ void Scene180::synchronize(Serializer &s) {
SceneExt::synchronize(s);
s.syncAsSint16LE(_frameNumber);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field480);
- s.syncAsSint16LE(_field482);
+ s.syncAsSint16LE(_helpEnabled);
s.syncAsSint16LE(_frameInc);
s.syncAsSint16LE(_fontNumber);
s.syncAsSint16LE(_fontHeight);
@@ -1549,11 +1574,11 @@ void Scene180::signal() {
break;
case 1:
- _field412 = 1;
+ _helpEnabled = true;
R2_GLOBALS._sceneManager._hasPalette = true;
_animationPlayer._paletteMode = ANIMPALMODE_NONE;
- _animationPlayer._v = 1;
- _animationPlayer._objectMode = 1;
+ _animationPlayer._isActive = true;
+ _animationPlayer._objectMode = ANIMOBJMODE_1;
R2_GLOBALS._scene180Mode = 1;
_animationPlayer.load(1);
@@ -1587,7 +1612,8 @@ void Scene180::signal() {
case 30:
case 43:
case 47:
- _field412 = 0;
+ _helpEnabled = false;
+ R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
_palette.loadPalette(0);
_palette.loadPalette(9998);
R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 8, this);
@@ -1595,12 +1621,12 @@ void Scene180::signal() {
case 5:
_animationPlayer._paletteMode = ANIMPALMODE_NONE;
- _animationPlayer._v = 1;
- _animationPlayer._objectMode = 1;
+ _animationPlayer._isActive = true;
+ _animationPlayer._objectMode = ANIMOBJMODE_1;
R2_GLOBALS._scene180Mode = 2;
_animationPlayer.load(2);
- _field412 = 1;
+ _helpEnabled = true;
R2_GLOBALS._scenePalette.addFader(_animationPlayer._subData._palData, 256, 6, NULL);
R2_GLOBALS._sound1.play(2);
break;
@@ -1637,10 +1663,10 @@ void Scene180::signal() {
break;
case 11:
- _field412 = 1;
- _object4.postInit();
- _object5.postInit();
- setAction(&_sequenceManager, this, 4000, &_object4, &_object5, NULL);
+ _helpEnabled = true;
+ _door.postInit();
+ _shipDisplay.postInit();
+ setAction(&_sequenceManager, this, 4000, &_door, &_shipDisplay, NULL);
break;
case 12:
@@ -1656,52 +1682,52 @@ void Scene180::signal() {
break;
case 13:
- setAction(&_sequenceManager, this, 4001, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4001, &_door, &_shipDisplay, NULL);
break;
case 15:
- setAction(&_sequenceManager, this, 4002, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4002, &_door, &_shipDisplay, NULL);
break;
case 17:
- setAction(&_sequenceManager, this, 4003, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4003, &_door, &_shipDisplay, NULL);
break;
case 19:
- setAction(&_sequenceManager, this, 4004, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4004, &_door, &_shipDisplay, NULL);
break;
case 21:
- setAction(&_sequenceManager, this, 4005, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4005, &_door, &_shipDisplay, NULL);
break;
case 23:
- setAction(&_sequenceManager, this, 4006, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4006, &_door, &_shipDisplay, NULL);
break;
case 25:
- setAction(&_sequenceManager, this, 4007, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager, this, 4007, &_door, &_shipDisplay, NULL);
break;
case 27:
- _field412 = 0;
- _object4.remove();
- _object5.remove();
+ _helpEnabled = false;
+ _door.remove();
+ _shipDisplay.remove();
setSceneDelay(2);
break;
case 28:
- _field412 = 0;
+ _helpEnabled = false;
_palette.loadPalette(0);
_palette.loadPalette(9998);
R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 100, this);
break;
case 29:
- _field412 = 1;
+ _helpEnabled = true;
_animationPlayer._paletteMode = ANIMPALMODE_REPLACE_PALETTE;
- _animationPlayer._v = 1;
- _animationPlayer._objectMode = 42;
+ _animationPlayer._isActive = true;
+ _animationPlayer._objectMode = ANIMOBJMODE_42;
R2_GLOBALS._scene180Mode = 3;
_animationPlayer.load(3);
break;
@@ -1709,12 +1735,12 @@ void Scene180::signal() {
case 31:
R2_GLOBALS._sound2.play(7);
- _object4.postInit();
- _object4.setVisage(76);
- _object4.setStrip(1);
- _object4.setFrame(1);
- _object4.setPosition(Common::Point(288, 143));
- _object4.fixPriority(210);
+ _door.postInit();
+ _door.setVisage(76);
+ _door.setStrip(1);
+ _door.setFrame(1);
+ _door.setPosition(Common::Point(288, 143));
+ _door.fixPriority(210);
loadScene(75);
@@ -1727,70 +1753,71 @@ void Scene180::signal() {
break;
case 32:
- _field412 = 1;
+ _helpEnabled = true;
- _object2.postInit();
- _object2.setPosition(Common::Point(161, 97));
- _object2.hide();
+ _teal.postInit();
+ _teal.setPosition(Common::Point(161, 97));
+ _teal.hide();
- _object3.postInit();
- _object3.setPosition(Common::Point(60, 96));
- _object3.hide();
- R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 11, this);
+ _webbster.postInit();
+ _webbster.setPosition(Common::Point(60, 96));
+ _webbster.hide();
+ _stripManager.start(11, this);
break;
case 33:
- _object2.hide();
+ _teal.hide();
- _object3.setup(76, 4, 1);
- _object3.setFrame(_object3.getFrameCount());
+ _webbster.setup(76, 4, 1);
+ _webbster.setFrame(_webbster.getFrameCount());
- _object5.postInit();
- _object5.setup(75, 1, 1);
- _object5.setPosition(Common::Point(221, 125));
- _object5.fixPriority(210);
- _object5.setAction(&_action1);
- R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 12, this);
+ _shipDisplay.postInit();
+ _shipDisplay.setup(75, 1, 1);
+ _shipDisplay.setPosition(Common::Point(221, 125));
+ _shipDisplay.fixPriority(210);
+ _shipDisplay.setAction(&_action1);
+ _stripManager.start(12, this);
break;
case 34:
- _object2.hide();
- _object3.hide();
+ _teal.hide();
+ _webbster.remove();
- _object1.postInit();
- _object1.setup(76, 2, 1);
- _object1.setPosition(Common::Point(287, 135));
- _object1.fixPriority(200);
+ _dutyOfficer.postInit();
+ _dutyOfficer.setup(76, 2, 1);
+ _dutyOfficer.setPosition(Common::Point(287, 135));
+ _dutyOfficer.fixPriority(200);
_sound1.play(19);
- R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this);
+ _door.animate(ANIM_MODE_5, this);
break;
case 35:
- R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 13, this);
+ _stripManager.start(13, this);
break;
case 36:
- _object2.remove();
+ _teal.remove();
_sound1.play(19);
-
- R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 6, this);
+ _door.animate(ANIM_MODE_6, this);
break;
case 37:
- _field412 = 0;
- _object1.remove();
+ _helpEnabled = false;
+ _dutyOfficer.remove();
_palette.loadPalette(9998);
R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 8, this);
break;
case 38:
- _object4.remove();
- _object5.setAction(NULL);
- _object5.remove();
+ _door.remove();
+ _shipDisplay.setAction(NULL);
+ _shipDisplay.remove();
+ _backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
R2_GLOBALS._sound2.fadeOut2(NULL);
- R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sound1.fadeOut2(this);
break;
case 39:
@@ -1800,7 +1827,7 @@ void Scene180::signal() {
case 40:
_animationPlayer._paletteMode = ANIMPALMODE_NONE;
- _animationPlayer._objectMode = 1;
+ _animationPlayer._objectMode = ANIMOBJMODE_1;
R2_GLOBALS._scene180Mode = 4;
if (_animationPlayer.load(4)) {
_animationPlayer.dispatch();
@@ -1812,8 +1839,8 @@ void Scene180::signal() {
break;
case 41:
- _field412 = 1;
- _animationPlayer._v = 1;
+ _helpEnabled = true;
+ _animationPlayer._isActive = true;
break;
case 42:
@@ -1832,14 +1859,15 @@ void Scene180::signal() {
break;
case 45:
- R2_GLOBALS._scenePalette.addFader(_animationPlayer._subData._palData, 256, 28, this);
+ _helpEnabled = true;
+ _stripManager.start(28, this);
break;
case 48:
- _field412 = 1;
+ _helpEnabled = true;
_animationPlayer._paletteMode = ANIMPALMODE_NONE;
- _animationPlayer._v = 1;
- _animationPlayer._objectMode = 1;
+ _animationPlayer._isActive = true;
+ _animationPlayer._objectMode = ANIMOBJMODE_1;
R2_GLOBALS._scene180Mode = 15;
_animationPlayer.load(15, NULL);
@@ -1850,13 +1878,21 @@ void Scene180::signal() {
case 49:
R2_GLOBALS._scene180Mode = 15;
R2_GLOBALS._paneRefreshFlag[0] = 3;
+
+ _backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+
setSceneDelay(1);
break;
case 50:
R2_GLOBALS._scene180Mode = 0;
- _field412 = 0;
- R2_GLOBALS._sceneManager.changeScene(100);
+ _helpEnabled = false;
+
+ // WORKAROUND: The original changed to scene 100 here, Quinn's Bedroom,
+ // but instead we're changing to the previously unused scene 50, which shows
+ // a closeup of Quinn in the floatation bed first
+ R2_GLOBALS._sceneManager.changeScene(50);
break;
}
}
@@ -1868,11 +1904,10 @@ void Scene180::setSceneDelay(int v) {
void Scene180::process(Event &event) {
if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
- event.handled = 1;
- if (!_field412) {
- if (R2_GLOBALS._scenePalette._listeners.size() == 0) {
+ event.handled = true;
+ if (_helpEnabled) {
+ if (R2_GLOBALS._scenePalette._listeners.size() == 0)
HelpDialog::show();
- }
}
}
@@ -1895,9 +1930,9 @@ void Scene180::dispatch() {
}
}
- if (_animationPlayer._v) {
+ if (_animationPlayer._isActive) {
if (_animationPlayer.isCompleted()) {
- _animationPlayer._v = 0;
+ _animationPlayer._isActive = false;
_animationPlayer.close();
_animationPlayer.remove();
@@ -1923,7 +1958,7 @@ void Scene180::restore() {
R2_GLOBALS._gfxColors.foreground = 4;
R2_GLOBALS._gfxColors.background = 3;
R2_GLOBALS._fontColors.background = 3;
- R2_GLOBALS._frameEdgeColour = 3;
+ R2_GLOBALS._frameEdgeColor = 3;
break;
case 1:
@@ -1932,7 +1967,7 @@ void Scene180::restore() {
R2_GLOBALS._gfxColors.foreground = 25;
R2_GLOBALS._gfxColors.background = 43;
R2_GLOBALS._fontColors.background = 48;
- R2_GLOBALS._frameEdgeColour = 48;
+ R2_GLOBALS._frameEdgeColor = 48;
break;
case 2:
@@ -1942,7 +1977,7 @@ void Scene180::restore() {
R2_GLOBALS._gfxColors.background = 136;
R2_GLOBALS._fontColors.background = 48;
R2_GLOBALS._fontColors.foreground = 253;
- R2_GLOBALS._frameEdgeColour = 48;
+ R2_GLOBALS._frameEdgeColor = 48;
break;
case 3:
@@ -1951,7 +1986,7 @@ void Scene180::restore() {
R2_GLOBALS._gfxColors.foreground = 84;
R2_GLOBALS._gfxColors.background = 118;
R2_GLOBALS._fontColors.background = 47;
- R2_GLOBALS._frameEdgeColour = 48;
+ R2_GLOBALS._frameEdgeColor = 48;
break;
case 14:
@@ -1961,7 +1996,7 @@ void Scene180::restore() {
R2_GLOBALS._fontColors.foreground = 38;
R2_GLOBALS._gfxColors.foreground = 192;
R2_GLOBALS._gfxColors.background = 30;
- R2_GLOBALS._frameEdgeColour = 48;
+ R2_GLOBALS._frameEdgeColor = 48;
break;
default:
@@ -1981,9 +2016,9 @@ void Scene180::restore() {
*--------------------------------------------------------------------------*/
bool Scene200::NorthDoor::startAction(CursorType action, Event &event) {
- Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 202;
scene->setAction(&scene->_sequenceManager, scene, 202, &R2_GLOBALS._player, this, NULL);
@@ -1994,9 +2029,9 @@ bool Scene200::NorthDoor::startAction(CursorType action, Event &event) {
}
bool Scene200::EastDoor::startAction(CursorType action, Event &event) {
- Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 200;
scene->setAction(&scene->_sequenceManager, scene, 200, &R2_GLOBALS._player, this, NULL);
@@ -2007,9 +2042,9 @@ bool Scene200::EastDoor::startAction(CursorType action, Event &event) {
}
bool Scene200::WestDoor::startAction(CursorType action, Event &event) {
- Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 204;
scene->setAction(&scene->_sequenceManager, scene, 204, &R2_GLOBALS._player, this, NULL);
@@ -2025,7 +2060,7 @@ void Scene200::EastExit::changeScene() {
Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 206;
scene->setAction(&scene->_sequenceManager, scene, 206, &R2_GLOBALS._player, NULL);
}
@@ -2034,7 +2069,7 @@ void Scene200::WestExit::changeScene() {
Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 208;
scene->setAction(&scene->_sequenceManager, scene, 208, &R2_GLOBALS._player, NULL);
}
@@ -2042,8 +2077,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));
@@ -2311,19 +2346,6 @@ void Scene205::Action1::textLoop() {
/*--------------------------------------------------------------------------*/
-Scene205::Object::Object(): SceneObject() {
- _x100 = _y100 = 0;
-}
-
-void Scene205::Object::synchronize(Serializer &s) {
- EventHandler::synchronize(s);
-
- s.syncAsSint32LE(_x100);
- s.syncAsSint32LE(_y100);
-}
-
-/*--------------------------------------------------------------------------*/
-
Scene205::Scene205(): SceneExt() {
_yp = 0;
_textIndex = 1;
@@ -2332,11 +2354,21 @@ Scene205::Scene205(): SceneExt() {
GfxFont font;
font.setFontNumber(4);
_fontHeight = font.getHeight();
+
+ for (int i = 0; i < 3; i++) {
+ _starList1[i] = nullptr;
+ _starList2[i] = nullptr;
+ }
+
+ for (int i = 0; i < 4; i++)
+ _starList3[i] = nullptr;
}
void Scene205::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(4000);
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._player._uiEnabled = false;
R2_GLOBALS._sound1.play(337);
@@ -2351,11 +2383,11 @@ void Scene205::synchronize(Serializer &s) {
SceneExt::synchronize(s);
for (int idx = 0; idx < 3; ++idx)
- SYNC_POINTER(_objList1[idx]);
+ SYNC_POINTER(_starList1[idx]);
for (int idx = 0; idx < 3; ++idx)
- SYNC_POINTER(_objList2[idx]);
+ SYNC_POINTER(_starList2[idx]);
for (int idx = 0; idx < 4; ++idx)
- SYNC_POINTER(_objList3[idx]);
+ SYNC_POINTER(_starList3[idx]);
s.syncAsSint16LE(_textIndex);
s.syncAsSint16LE(_lineNum);
@@ -2377,9 +2409,9 @@ void Scene205::process(Event &event) {
}
void Scene205::dispatch() {
- processList(_objList3, 4, Common::Rect(0, 0, 319, 200), 1, 1, 160, 100);
- processList(_objList2, 3, Common::Rect(0, 0, 319, 200), 2, 2, 160, 100);
- processList(_objList1, 3, Common::Rect(0, 0, 319, 200), 4, 3, 160, 100);
+ processList(_starList3, 4, Common::Rect(0, 0, 319, 200), 1, 1, 160, 100);
+ processList(_starList2, 3, Common::Rect(0, 0, 319, 200), 2, 2, 160, 100);
+ processList(_starList1, 3, Common::Rect(0, 0, 319, 200), 4, 3, 160, 100);
Scene::dispatch();
}
@@ -2391,10 +2423,10 @@ void Scene205::setup() {
Common::Point(140, 149), Common::Point(91, 166), Common::Point(299, 46), Common::Point(314, 10)
};
- // Set up the first object list
+ // Set up the first star list
for (int idx = 0; idx < 3; ++idx) {
- Object *obj = new Object();
- _objList1[idx] = obj;
+ Star *obj = new Star();
+ _starList1[idx] = obj;
obj->postInit();
obj->_flags |= OBJFLAG_CLONED;
@@ -2407,10 +2439,10 @@ void Scene205::setup() {
obj->fixPriority(12);
}
- // Setup the second object list
+ // Setup the second star list
for (int idx = 0; idx < 3; ++idx) {
- Object *obj = new Object();
- _objList2[idx] = obj;
+ Star *obj = new Star();
+ _starList2[idx] = obj;
obj->postInit();
obj->_flags |= OBJFLAG_CLONED;
@@ -2423,10 +2455,10 @@ void Scene205::setup() {
obj->fixPriority(11);
}
- // Setup the third object list
+ // Setup the third star list
for (int idx = 0; idx < 4; ++idx) {
- Object *obj = new Object();
- _objList3[idx] = obj;
+ Star *obj = new Star();
+ _starList3[idx] = obj;
obj->postInit();
obj->_flags |= OBJFLAG_CLONED;
@@ -2443,10 +2475,10 @@ void Scene205::setup() {
/**
* Handles moving a group of stars in the scene background
*/
-void Scene205::processList(Object **ObjList, int count, const Common::Rect &bounds,
+void Scene205::processList(Star **ObjList, int count, const Common::Rect &bounds,
int xMultiply, int yMultiply, int xCenter, int yCenter) {
for (int idx = 0; idx < count; ++idx) {
- Object *obj = ObjList[idx];
+ Star *obj = ObjList[idx];
Common::Point pt(obj->_position.x - xCenter, obj->_position.y - yCenter);
if ((obj->_position.x <= 319) && (obj->_position.x >= 0) &&
@@ -2492,22 +2524,21 @@ void Scene205::handleText() {
*--------------------------------------------------------------------------*/
Scene250::Button::Button(): SceneActor() {
- _floorNumber = _v2 = 0;
+ _floorNumber = 0;
}
void Scene250::Button::synchronize(Serializer &s) {
SceneActor::synchronize(s);
s.syncAsSint16LE(_floorNumber);
- s.syncAsSint16LE(_v2);
}
bool Scene250::Button::startAction(CursorType action, Event &event) {
- Scene250 *scene = (Scene250 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
- if (scene->_field414) {
+ case CURSOR_USE: {
+ Scene250 *scene = (Scene250 *)R2_GLOBALS._sceneManager._scene;
+
+ if (scene->_destButtonY) {
SceneItem::display2(250, 15);
} else {
switch (_floorNumber) {
@@ -2529,6 +2560,7 @@ bool Scene250::Button::startAction(CursorType action, Event &event) {
}
}
return true;
+ }
case CURSOR_LOOK:
switch (_floorNumber) {
@@ -2558,7 +2590,6 @@ bool Scene250::Button::startAction(CursorType action, Event &event) {
void Scene250::Button::setFloor(int floorNumber) {
SceneActor::postInit();
_floorNumber = floorNumber;
- _v2 = 0;
if (_floorNumber <= 9) {
SceneObject::setup(250, 1, 4);
@@ -2583,22 +2614,25 @@ void Scene250::Button::setFloor(int floorNumber) {
/*--------------------------------------------------------------------------*/
Scene250::Scene250(): SceneExt() {
- _field412 = _field414 = _field416 = _field418 = _field41A = 0;
+ _currButtonY = _destButtonY = _elevatorSpeed = 0;
+ _skippingFl = _skippableFl = false;
}
void Scene250::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
- s.syncAsSint16LE(_field418);
- s.syncAsSint16LE(_field41A);
+ s.syncAsSint16LE(_currButtonY);
+ s.syncAsSint16LE(_destButtonY);
+ s.syncAsSint16LE(_elevatorSpeed);
+ s.syncAsSint16LE(_skippableFl);
+ s.syncAsSint16LE(_skippingFl);
}
void Scene250::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(250);
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setVisage(10);
@@ -2610,12 +2644,12 @@ void Scene250::postInit(SceneObjectList *OwnerList) {
_currentFloor.setup(250, 1, 5);
_currentFloor.setDetails(250, 13, -1, -1, 1, (SceneItem *)NULL);
- _button1.setFloor(11);
- _button1.setup(250, 1, 3);
- _button1.setPosition(Common::Point(400, 100));
- _button1.setDetails(250, 14, -1, -1, 1, (SceneItem *)NULL);
- _button1.fixPriority(190);
- _button1.hide();
+ _destinationFloor.setFloor(11);
+ _destinationFloor.setup(250, 1, 3);
+ _destinationFloor.setPosition(Common::Point(400, 100));
+ _destinationFloor.setDetails(250, 14, -1, -1, 1, (SceneItem *)NULL);
+ _destinationFloor.fixPriority(190);
+ _destinationFloor.hide();
_floor1.setFloor(1);
_floor2.setFloor(2);
@@ -2627,36 +2661,36 @@ void Scene250::postInit(SceneObjectList *OwnerList) {
_floor8.setFloor(8);
_floor9.setFloor(9);
- _item2.setDetails(Rect(0, 0, 73, SCREEN_HEIGHT), 250, 9, -1, 9, 1, NULL);
- _item4.setDetails(Rect(239, 16, 283, 164), 250, 6, -1, -1, 1, NULL);
+ _door.setDetails(Rect(0, 0, 73, SCREEN_HEIGHT), 250, 9, -1, 9, 1, NULL);
+ _directionIndicator.setDetails(Rect(239, 16, 283, 164), 250, 6, -1, -1, 1, NULL);
_background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 250, 0, 1, -1, 1, NULL);
R2_GLOBALS._events.setCursor(CURSOR_USE);
switch (R2_GLOBALS._sceneManager._previousScene) {
case 200:
- _field412 = 55;
+ _currButtonY = 55;
break;
case 300:
- _field412 = 43;
+ _currButtonY = 43;
break;
case 700:
- _field412 = 139;
+ _currButtonY = 139;
break;
case 850:
- _field412 = 91;
+ _currButtonY = 91;
break;
default:
R2_GLOBALS._sceneManager._previousScene = 200;
- _field412 = 55;
+ _currButtonY = 55;
break;
}
- _currentFloor.setPosition(Common::Point(111, _field412));
+ _currentFloor.setPosition(Common::Point(111, _currButtonY));
}
void Scene250::signal() {
- if (_field41A)
+ if (_skippingFl)
_sceneMode = 20;
switch (_sceneMode) {
@@ -2667,20 +2701,24 @@ void Scene250::signal() {
R2_GLOBALS._player.setPosition(Common::Point(261, 185));
ADD_MOVER(R2_GLOBALS._player, 261, 15);
- _field416 = 0;
+ _elevatorSpeed = 0;
_sceneMode = 2;
break;
case 2:
- _sceneMode = ((_field414 - 12) == _field412) ? 4 : 3;
+ if (_destButtonY - 12 == _currButtonY)
+ _sceneMode = 4;
+ else
+ _sceneMode = 3;
+
signal();
break;
case 3:
_currentFloor.setPosition(Common::Point(111, _currentFloor._position.y + 12));
- _field412 += 12;
+ _currButtonY += 12;
R2_GLOBALS._player.setPosition(Common::Point(261, 185));
ADD_MOVER(R2_GLOBALS._player, 261, 15);
- if ((_field414 - 12) == _field412)
+ if ((_destButtonY - 12) == _currButtonY)
_sceneMode = 4;
break;
case 4:
@@ -2702,22 +2740,24 @@ void Scene250::signal() {
R2_GLOBALS._player.setup(250, 1, 2);
R2_GLOBALS._player.setPosition(Common::Point(261, 15));
ADD_MOVER(R2_GLOBALS._player, 261, 185);
- _field416 = 0;
+ _elevatorSpeed = 0;
_sceneMode = 7;
break;
case 7:
- _field418 = 1;
- if ((_field414 + 12) == _field412)
+ _skippableFl = true;
+ if ((_destButtonY + 12) == _currButtonY)
+ _sceneMode = 9;
+ else
_sceneMode = 8;
signal();
break;
case 8:
_currentFloor.setPosition(Common::Point(111, _currentFloor._position.y - 12));
- _field412 -= 12;
+ _currButtonY -= 12;
R2_GLOBALS._player.setPosition(Common::Point(261, 15));
ADD_MOVER(R2_GLOBALS._player, 261, 185);
- if ((_field414 + 12) == _field412)
+ if ((_destButtonY + 12) == _currButtonY)
_sceneMode = 9;
break;
case 9:
@@ -2733,7 +2773,7 @@ void Scene250::signal() {
break;
case 20:
// Handle changing scene
- switch (_field414) {
+ switch (_destButtonY) {
case 55:
R2_GLOBALS._sceneManager.changeScene(200);
break;
@@ -2741,7 +2781,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);
@@ -2756,12 +2796,13 @@ void Scene250::signal() {
}
void Scene250::changeFloor(int floorNumber) {
- _field414 = (floorNumber - 1) * 12 + 43;
- _button1.setPosition(Common::Point(111, _field414));
- _button1.show();
+ _destButtonY = (floorNumber - 1) * 12 + 43;
+ _destinationFloor.setPosition(Common::Point(111, _destButtonY));
+ _destinationFloor.show();
- _sceneMode = (_field412 >= _field414) ? 6 : 1;
- if (_field414 == _field412)
+ _skippableFl = true;
+ _sceneMode = (_currButtonY >= _destButtonY) ? 6 : 1;
+ if (_destButtonY == _currButtonY)
_sceneMode = 20;
signal();
@@ -2769,8 +2810,8 @@ void Scene250::changeFloor(int floorNumber) {
void Scene250::process(Event &event) {
if (!event.handled) {
- if (((event.eventType == EVENT_KEYPRESS) || (event.btnState != 0)) && _field418) {
- _field41A = 1;
+ if (((event.eventType == EVENT_KEYPRESS) || (event.btnState == BTNSHIFT_RIGHT)) && _skippableFl) {
+ _skippingFl = true;
event.handled = true;
}
@@ -2781,14 +2822,14 @@ void Scene250::process(Event &event) {
void Scene250::dispatch() {
SceneExt::dispatch();
- if (((_sceneMode == 2) || (_sceneMode == 7)) && (_field416 < 100)) {
- ++_field416;
- R2_GLOBALS._player._moveDiff.y = _field416 / 5;
+ if (((_sceneMode == 2) || (_sceneMode == 7)) && (_elevatorSpeed < 100)) {
+ ++_elevatorSpeed;
+ R2_GLOBALS._player._moveDiff.y = _elevatorSpeed / 5;
}
if (((_sceneMode == 5) || (_sceneMode == 10)) && (R2_GLOBALS._player._moveDiff.y > 4)) {
- --_field416;
- R2_GLOBALS._player._moveDiff.y = _field416 / 7 + 3;
+ --_elevatorSpeed;
+ R2_GLOBALS._player._moveDiff.y = (_elevatorSpeed / 7) + 3;
}
}
@@ -2802,12 +2843,12 @@ void Scene300::Action1::signal() {
switch (_actionIndex) {
case 0:
- setAction(&scene->_sequenceManager2, this, 311, (R2_GLOBALS._player._characterIndex == 1) ?
+ setAction(&scene->_sequenceManager2, this, 311, (R2_GLOBALS._player._characterIndex == R2_QUINN) ?
(SceneObject *)&R2_GLOBALS._player : (SceneObject *)&scene->_quinn);
_actionIndex = 2;
break;
case 1:
- setAction(&scene->_sequenceManager2, this, 312, (R2_GLOBALS._player._characterIndex == 1) ?
+ setAction(&scene->_sequenceManager2, this, 312, (R2_GLOBALS._player._characterIndex == R2_QUINN) ?
(SceneObject *)&R2_GLOBALS._player : (SceneObject *)&scene->_quinn);
_actionIndex = 0;
break;
@@ -2868,14 +2909,14 @@ void Scene300::Action3::signal() {
void Scene300::Action4::signal() {
- Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
-
if (!R2_GLOBALS._playStream.isPlaying()) {
- scene->_object7.setStrip2(R2_GLOBALS._randomSource.getRandomNumber(2));
- scene->_object7.setFrame(1);
+ Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
- scene->_object9.setStrip2(3);
- scene->_object9.setFrame(1);
+ scene->_mirandaScreen.setStrip2(R2_GLOBALS._randomSource.getRandomNumber(2));
+ scene->_mirandaScreen.setFrame(1);
+
+ scene->_quinnScreen.setStrip2(3);
+ scene->_quinnScreen.setFrame(1);
}
setDelay(60 + R2_GLOBALS._randomSource.getRandomNumber(479));
@@ -2884,8 +2925,6 @@ void Scene300::Action4::signal() {
/*--------------------------------------------------------------------------*/
bool Scene300::QuinnWorkstation::startAction(CursorType action, Event &event) {
- Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
case CURSOR_USE:
if (R2_GLOBALS._player._characterIndex != 1)
@@ -2894,6 +2933,8 @@ bool Scene300::QuinnWorkstation::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.setAction(NULL);
R2_GLOBALS._sceneManager.changeScene(325);
} else {
+ Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 306;
scene->setAction(&scene->_sequenceManager1, scene, 306, &R2_GLOBALS._player, NULL);
@@ -2901,7 +2942,7 @@ bool Scene300::QuinnWorkstation::startAction(CursorType action, Event &event) {
return true;
case CURSOR_LOOK:
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
SceneItem::display2(300, 47);
return true;
}
@@ -2924,7 +2965,7 @@ bool Scene300::MirandaWorkstation::startAction(CursorType action, Event &event)
return true;
case CURSOR_LOOK:
- if (R2_GLOBALS._player._characterIndex == 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA) {
SceneItem::display2(300, 47);
return true;
}
@@ -2940,7 +2981,7 @@ bool Scene300::MirandaWorkstation::startAction(CursorType action, Event &event)
bool Scene300::SeekerWorkstation::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_LOOK:
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
SceneItem::display2(300, 47);
return true;
}
@@ -2986,14 +3027,14 @@ bool Scene300::Miranda::startAction(CursorType action, Event &event) {
} else if (!R2_GLOBALS.getFlag(55)) {
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
scene->_sceneMode = 10;
- scene->_stripManager.start3(scene->_stripId, scene, R2_GLOBALS._stripManager_lookupList);
+ scene->_stripManager.start3(201, scene, R2_GLOBALS._stripManager_lookupList);
} else {
scene->_sceneMode = 16;
if (!R2_GLOBALS.getFlag(57)) {
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
scene->_stripManager.start3(434, scene, R2_GLOBALS._stripManager_lookupList);
- } else if (R2_GLOBALS._player._characterScene[R2_MIRANDA] != 500) {
+ } else if (R2_GLOBALS._player._characterScene[R2_SEEKER] != 500) {
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
scene->_stripManager.start3(407, scene, R2_GLOBALS._stripManager_lookupList);
} else {
@@ -3048,7 +3089,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;
@@ -3090,10 +3131,10 @@ bool Scene300::Seeker::startAction(CursorType action, Event &event) {
} else {
R2_GLOBALS._player.disableControl();
scene->_stripId = 171;
- }
- scene->_sceneMode = 310;
- scene->setAction(&scene->_sequenceManager1, scene, 310, &R2_GLOBALS._player, NULL);
+ scene->_sceneMode = 310;
+ scene->setAction(&scene->_sequenceManager1, scene, 310, &R2_GLOBALS._player, NULL);
+ }
return true;
case R2_READER:
@@ -3114,10 +3155,10 @@ bool Scene300::Seeker::startAction(CursorType action, Event &event) {
}
bool Scene300::Quinn::startAction(CursorType action, Event &event) {
- Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_TALK:
+ case CURSOR_TALK: {
+ Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
scene->_sceneMode = 10;
@@ -3126,33 +3167,31 @@ bool Scene300::Quinn::startAction(CursorType action, Event &event) {
if (R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500)
scene->_stripId = 442;
else if (!R2_GLOBALS.getFlag(44))
- scene->_stripId = 177 + R2_GLOBALS._randomSource.getRandomNumber(2);
+ scene->_stripId = 125 + R2_GLOBALS._randomSource.getRandomNumber(2);
else if (!R2_GLOBALS.getFlag(55))
- scene->_stripId = 208;
+ scene->_stripId = 439;
else
- scene->_stripId = 441;
- } else if (R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500) {
- scene->_stripId = 442;
+ scene->_stripId = 210;
} else if (R2_GLOBALS.getFlag(44)) {
- scene->_stripId = R2_GLOBALS.getFlag(55) ? 441 : 208;
+ scene->_stripId = R2_GLOBALS.getFlag(55) ? 439 : 210;
} else {
- scene->_stripId = 125 + R2_GLOBALS._randomSource.getRandomNumber(2);
+ scene->_stripId = 177 + R2_GLOBALS._randomSource.getRandomNumber(2);
}
scene->_stripManager.start3(scene->_stripId, scene, R2_GLOBALS._stripManager_lookupList);
return true;
-
+ }
default:
return SceneActor::startAction(action, event);
}
}
bool Scene300::Doorway::startAction(CursorType action, Event &event) {
- Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
if ((R2_GLOBALS._player._characterIndex == R2_QUINN) &&
- (!R2_GLOBALS.getFlag(44) || R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500)) {
+ (!R2_GLOBALS.getFlag(44) || R2_GLOBALS._player._characterScene[R2_SEEKER] == 500)) {
+ Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 301;
scene->setAction(&scene->_sequenceManager1, scene, 301, &R2_GLOBALS._player, this, NULL);
@@ -3171,6 +3210,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 +3223,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 +3234,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);
@@ -3206,75 +3247,75 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
_rotation->_countdown = 1;
if (R2_GLOBALS.getFlag(51) && !R2_GLOBALS.getFlag(25)) {
- _object1.postInit();
- _object1.setup(301, 7, 2);
- _object1.setPosition(Common::Point(65, 24));
+ _atmosphereLeftWindow.postInit();
+ _atmosphereLeftWindow.setup(301, 7, 2);
+ _atmosphereLeftWindow.setPosition(Common::Point(65, 24));
- _object2.postInit();
- _object2.setup(301, 8, 2);
- _object2.setPosition(Common::Point(254, 24));
+ _atmosphereRightWindow.postInit();
+ _atmosphereRightWindow.setup(301, 8, 2);
+ _atmosphereRightWindow.setPosition(Common::Point(254, 24));
}
_doorway.postInit();
_doorway.setVisage(300);
_doorway.setPosition(Common::Point(159, 79));
- _object3.postInit();
- _object3.setup(300, 4, 1);
- _object3.setPosition(Common::Point(84, 48));
- _object3.animate(ANIM_MODE_2, NULL);
- _object3._numFrames = 5;
+ _leftVerticalBarsAnim.postInit();
+ _leftVerticalBarsAnim.setup(300, 4, 1);
+ _leftVerticalBarsAnim.setPosition(Common::Point(84, 48));
+ _leftVerticalBarsAnim.animate(ANIM_MODE_2, NULL);
+ _leftVerticalBarsAnim._numFrames = 5;
- _object4.postInit();
- _object4.setup(300, 5, 1);
- _object4.setPosition(Common::Point(236, 48));
- _object4.animate(ANIM_MODE_2, NULL);
+ _rightVerticalBarsAnim.postInit();
+ _rightVerticalBarsAnim.setup(300, 5, 1);
+ _rightVerticalBarsAnim.setPosition(Common::Point(236, 48));
+ _rightVerticalBarsAnim.animate(ANIM_MODE_2, NULL);
_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();
- _object6.setup(300, 7, 1);
- _object6.setPosition(Common::Point(214, 37));
- _object6.animate(ANIM_MODE_2, NULL);
- _object6._numFrames = 3;
-
- _object7.postInit();
- _object7.setup(301, 1, 1);
- _object7.setPosition(Common::Point(39, 97));
- _object7.fixPriority(124);
- _object7.animate(ANIM_MODE_2, NULL);
- _object7._numFrames = 5;
- _object7.setAction(&_action4);
-
- _object8.postInit();
- _object8.setup(300, 8, 1);
- _object8.setPosition(Common::Point(105, 37));
- _object8.animate(ANIM_MODE_2, NULL);
- _object8._numFrames = 5;
-
- _object9.postInit();
- _object9.setup(301, 6, 1);
- _object9.setPosition(Common::Point(274, 116));
- _object9.fixPriority(143);
- _object9.animate(ANIM_MODE_2, NULL);
- _object9._numFrames = 5;
+ _rightTextDisplay.postInit();
+ _rightTextDisplay.setup(300, 7, 1);
+ _rightTextDisplay.setPosition(Common::Point(214, 37));
+ _rightTextDisplay.animate(ANIM_MODE_2, NULL);
+ _rightTextDisplay._numFrames = 3;
+
+ _mirandaScreen.postInit();
+ _mirandaScreen.setup(301, 1, 1);
+ _mirandaScreen.setPosition(Common::Point(39, 97));
+ _mirandaScreen.fixPriority(124);
+ _mirandaScreen.animate(ANIM_MODE_2, NULL);
+ _mirandaScreen._numFrames = 5;
+ _mirandaScreen.setAction(&_action4);
+
+ _leftTextDisplay.postInit();
+ _leftTextDisplay.setup(300, 8, 1);
+ _leftTextDisplay.setPosition(Common::Point(105, 37));
+ _leftTextDisplay.animate(ANIM_MODE_2, NULL);
+ _leftTextDisplay._numFrames = 5;
+
+ _quinnScreen.postInit();
+ _quinnScreen.setup(301, 6, 1);
+ _quinnScreen.setPosition(Common::Point(274, 116));
+ _quinnScreen.fixPriority(143);
+ _quinnScreen.animate(ANIM_MODE_2, NULL);
+ _quinnScreen._numFrames = 5;
_quinnWorkstation1.setDetails(Rect(243, 148, 315, 167), 300, 30, 31, 32, 1, NULL);
_mirandaWorkstation1.setDetails(Rect(4, 128, 69, 167), 300, 33, 31, 35, 1, NULL);
switch (R2_GLOBALS._player._characterIndex) {
- case 1:
+ case R2_QUINN:
_miranda.postInit();
_miranda.setup(302, 2, 1);
_miranda.setPosition(Common::Point(47, 128));
_miranda.setAction(&_action3);
_miranda.setDetails(300, 39, 40, 41, 1, (SceneItem *)NULL);
- if ((R2_GLOBALS._player._characterScene[2] == 300) || (R2_GLOBALS._player._characterScene[2] == 325)) {
+ if ((R2_GLOBALS._player._characterScene[R2_SEEKER] == 300) || (R2_GLOBALS._player._characterScene[R2_SEEKER] == 325)) {
_seeker.postInit();
_seeker.setVisage(302);
_seeker.setPosition(Common::Point(158, 108));
@@ -3289,14 +3330,14 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.disableControl();
break;
- case 2:
+ case R2_SEEKER:
_miranda.postInit();
_miranda.setup(302, 2, 1);
_miranda.setPosition(Common::Point(47, 128));
_miranda.setAction(&_action3);
_miranda.setDetails(300, 39, 40, 41, 1, (SceneItem *)NULL);
- if ((R2_GLOBALS._player._characterScene[1] == 300) || (R2_GLOBALS._player._characterScene[1] == 325)) {
+ if ((R2_GLOBALS._player._characterScene[R2_QUINN] == 300) || (R2_GLOBALS._player._characterScene[R2_QUINN] == 325)) {
_quinn.postInit();
_quinn.setup(302, 3, 1);
_quinn.setPosition(Common::Point(271, 150));
@@ -3309,10 +3350,11 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setPosition(Common::Point(158, 108));
R2_GLOBALS._player.fixPriority(130);
R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
break;
- case 3:
- if ((R2_GLOBALS._player._characterScene[2] == 300) || (R2_GLOBALS._player._characterScene[2] == 325)) {
+ case R2_MIRANDA:
+ if ((R2_GLOBALS._player._characterScene[R2_SEEKER] == 300) || (R2_GLOBALS._player._characterScene[R2_SEEKER] == 325)) {
_seeker.postInit();
_seeker.setVisage(302);
_seeker.setPosition(Common::Point(158, 108));
@@ -3321,7 +3363,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
_seeker.setDetails(300, 42, 43, 44, 1, (SceneItem *)NULL);
}
- if ((R2_GLOBALS._player._characterScene[1] == 300) || (R2_GLOBALS._player._characterScene[1] == 325)) {
+ if ((R2_GLOBALS._player._characterScene[R2_QUINN] == 300) || (R2_GLOBALS._player._characterScene[R2_QUINN] == 325)) {
_quinn.postInit();
_quinn.setup(302, 3, 1);
_quinn.setPosition(Common::Point(271, 150));
@@ -3333,6 +3375,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setup(302, 2, 1);
R2_GLOBALS._player.setPosition(Common::Point(47, 128));
R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
break;
default:
@@ -3365,7 +3408,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
break;
case 325:
if (!R2_GLOBALS.getFlag(44) || R2_GLOBALS.getFlag(25))
- setAction(&_sequenceManager1, this, 309, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager1, this, 307, &R2_GLOBALS._player, NULL);
else {
R2_GLOBALS.setFlag(60);
R2_GLOBALS._player.setup(302, 3, 1);
@@ -3402,9 +3445,11 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
if (R2_GLOBALS.getFlag(51)) {
+ // Things don't seem right
_sceneMode = 13;
_stripManager.start3(300, this, R2_GLOBALS._stripManager_lookupList);
} else {
+ // Back in Ringworld space
_sceneMode = 11;
_stripManager.start3(200, this, R2_GLOBALS._stripManager_lookupList);
}
@@ -3445,9 +3490,9 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
case 3:
if (R2_GLOBALS._sceneManager._previousScene == 1500) {
- R2_GLOBALS._player._oldCharacterScene[3] = 3150;
- R2_GLOBALS._player._characterScene[3] = 3150;
- R2_GLOBALS._player._effect = 0;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3150;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3150;
+ R2_GLOBALS._player._effect = EFFECT_NONE;
R2_GLOBALS._player.setAction(NULL);
R2_GLOBALS._player.disableControl();
@@ -3484,27 +3529,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:
- if (R2_GLOBALS._stripManager_lookupList[1] == 6)
+ case 5:
+ if (R2_GLOBALS._stripManager_lookupList[0] == 6)
R2_GLOBALS.setFlag(40);
break;
- case 5:
+ case 6:
R2_GLOBALS._sceneManager.changeScene(1000);
break;
default:
@@ -3565,7 +3610,7 @@ void Scene300::signal() {
break;
case 16:
- if (_stripManager._field2E8 == 1) {
+ if (_stripManager._exitMode == 1) {
R2_GLOBALS._player.setAction(NULL);
R2_GLOBALS._sceneManager.changeScene(1000);
} else {
@@ -3624,13 +3669,15 @@ 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;
case 313:
_sceneMode = 14;
- R2_GLOBALS._player._effect = 0;
+ R2_GLOBALS._player._effect = EFFECT_NONE;
_seeker.setAction(&_sequenceManager3, this, 314, &_seeker, &_doorway, NULL);
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
_stripManager.start(301, this);
@@ -3639,7 +3686,7 @@ void Scene300::signal() {
case 314:
R2_GLOBALS._player.disableControl();
_sceneMode = 315;
- R2_GLOBALS._player._effect = 1;
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
setAction(&_sequenceManager1, this, 315, &R2_GLOBALS._player, &_doorway, NULL);
break;
@@ -3648,9 +3695,9 @@ void Scene300::signal() {
break;
case 316:
- R2_GLOBALS._player._characterScene[2] = 500;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 500;
_seeker.remove();
- R2_GLOBALS._player.enableControl(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 317:
@@ -3671,6 +3718,8 @@ void Scene300::signal() {
}
void Scene300::signal309() {
+ // Sets up what conversation items will be available when to talking to the
+ // others on the Bridge, and will be set dependent on game flags
if (R2_GLOBALS.getFlag(2))
R2_GLOBALS._stripManager_lookupList[0] = (R2_INVENTORY.getObjectScene(R2_READER) == 1) ? 3 : 2;
@@ -3720,16 +3769,16 @@ const double ADJUST_FACTOR = 0.06419999999999999;
Scene325::Icon::Icon(): SceneActor() {
_lookLineNum = 0;
- _field98 = 0;
+ _iconId = 0;
_pressed = false;
}
void Scene325::Icon::postInit(SceneObjectList *OwnerList) {
SceneObject::postInit();
- _object1.postInit();
- _object1.fixPriority(21);
- _object1.hide();
+ _glyph.postInit();
+ _glyph.fixPriority(21);
+ _glyph.hide();
_sceneText1._color1 = 92;
_sceneText1._color2 = 0;
@@ -3743,7 +3792,7 @@ void Scene325::Icon::postInit(SceneObjectList *OwnerList) {
void Scene325::Icon::synchronize(Serializer &s) {
SceneActor::synchronize(s);
s.syncAsSint16LE(_lookLineNum);
- s.syncAsSint16LE(_field98);
+ s.syncAsSint16LE(_iconId);
s.syncAsSint16LE(_pressed);
}
@@ -3768,18 +3817,18 @@ void Scene325::Icon::process(Event &event) {
scene->_sound1.play(14);
setFrame(2);
- switch (_object1._strip) {
+ switch (_glyph._strip) {
case 1:
- _object1.setStrip(2);
+ _glyph.setStrip(2);
break;
case 3:
- _object1.setStrip(4);
+ _glyph.setStrip(4);
break;
case 5:
- _object1.setStrip(6);
+ _glyph.setStrip(6);
break;
case 7:
- _object1.setStrip(8);
+ _glyph.setStrip(8);
break;
default:
break;
@@ -3798,15 +3847,15 @@ void Scene325::Icon::process(Event &event) {
if ((event.eventType == EVENT_BUTTON_UP) && _pressed) {
setFrame(1);
- switch (_object1._strip) {
+ switch (_glyph._strip) {
case 2:
- _object1.setStrip(1);
+ _glyph.setStrip(1);
break;
case 4:
- _object1.setStrip(3);
+ _glyph.setStrip(3);
break;
case 6:
- _object1.setStrip(5);
+ _glyph.setStrip(5);
break;
default:
break;
@@ -3820,18 +3869,18 @@ void Scene325::Icon::process(Event &event) {
}
void Scene325::Icon::setIcon(int id) {
- Scene325 *scene = (Scene325 *)R2_GLOBALS._sceneManager._scene;
-
- _lookLineNum = _field98 = id;
+ _lookLineNum = _iconId = id;
SceneActor::_lookLineNum = id;
_sceneText1.remove();
_sceneText2.remove();
if (_lookLineNum) {
+ Scene325 *scene = (Scene325 *)R2_GLOBALS._sceneManager._scene;
+
showIcon();
- _object1.setup(325, ((id - 1) / 10) * 2 + 1, ((id - 1) % 10) + 1);
- _object1.setPosition(_position);
+ _glyph.setup(325, ((id - 1) / 10) * 2 + 1, ((id - 1) % 10) + 1);
+ _glyph.setPosition(_position);
_sceneText1._fontNumber = scene->_iconFontNumber;
_sceneText1.setup(CONSOLE325_MESSAGES[id]);
@@ -3872,26 +3921,26 @@ void Scene325::Icon::setIcon(int id) {
void Scene325::Icon::showIcon() {
_sceneText1.show();
_sceneText2.show();
- _object1.show();
- _object2.show();
+ _glyph.show();
+ _horizLine.show();
show();
}
void Scene325::Icon::hideIcon() {
_sceneText1.hide();
_sceneText2.hide();
- _object1.hide();
- _object2.hide();
+ _glyph.hide();
+ _horizLine.hide();
hide();
}
/*--------------------------------------------------------------------------*/
Scene325::Scene325(): SceneExt() {
- _field412 = 7;
+ _consoleAction = 7;
_iconFontNumber = 50;
- _field416 = _field418 = 0;
- _field41A = _field41C = _field41E = _field420 = 0;
+ _databasePage = _priorConsoleAction = 0;
+ _moveCounter = _yChange = _yDirection = _scannerLocation = 0;
_soundCount = _soundIndex = 0;
for (int idx = 0; idx < 10; ++idx)
@@ -3899,8 +3948,8 @@ Scene325::Scene325(): SceneExt() {
}
void Scene325::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(325);
+ SceneExt::postInit();
R2_GLOBALS.clearFlag(50);
_stripManager.addSpeaker(&_quinnSpeaker);
@@ -3910,7 +3959,7 @@ void Scene325::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _item2.setDetails(1, 325, 3, 4, 5);
+ _terminal.setDetails(1, 325, 3, 4, 5);
_background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 325, 0, 1, 2, 1, (SceneItem *)NULL);
_sceneMode = 1;
signal();
@@ -3919,14 +3968,14 @@ void Scene325::postInit(SceneObjectList *OwnerList) {
void Scene325::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_consoleAction);
s.syncAsSint16LE(_iconFontNumber);
- s.syncAsSint16LE(_field416);
- s.syncAsSint16LE(_field418);
- s.syncAsSint16LE(_field41A);
- s.syncAsSint16LE(_field41C);
- s.syncAsSint16LE(_field41E);
- s.syncAsSint16LE(_field420);
+ s.syncAsSint16LE(_databasePage);
+ s.syncAsSint16LE(_priorConsoleAction);
+ s.syncAsSint16LE(_moveCounter);
+ s.syncAsSint16LE(_yChange);
+ s.syncAsSint16LE(_yDirection);
+ s.syncAsSint16LE(_scannerLocation);
s.syncAsSint16LE(_soundCount);
s.syncAsSint16LE(_soundIndex);
@@ -3958,28 +4007,28 @@ void Scene325::signal() {
case 1:
_icon1.setup(160, 1, 1);
_icon1.setPosition(Common::Point(65, 17));
- _icon1._object2.postInit();
- _icon1._object2.setup(160, 7, 1);
- _icon1._object2.setPosition(Common::Point(106, 41));
+ _icon1._horizLine.postInit();
+ _icon1._horizLine.setup(160, 7, 1);
+ _icon1._horizLine.setPosition(Common::Point(106, 41));
_icon2.setup(160, 1, 1);
_icon2.setPosition(Common::Point(80, 32));
- _icon2._object2.postInit();
- _icon2._object2.setup(160, 7, 2);
- _icon2._object2.setPosition(Common::Point(106, 56));
+ _icon2._horizLine.postInit();
+ _icon2._horizLine.setup(160, 7, 2);
+ _icon2._horizLine.setPosition(Common::Point(106, 56));
_icon3.setup(160, 1, 1);
_icon3.setPosition(Common::Point(65, 47));
- _icon3._object2.postInit();
- _icon3._object2.setup(160, 7, 1);
- _icon3._object2.setPosition(Common::Point(106, 71));
+ _icon3._horizLine.postInit();
+ _icon3._horizLine.setup(160, 7, 1);
+ _icon3._horizLine.setPosition(Common::Point(106, 71));
_icon4.setup(160, 1, 1);
_icon4.setPosition(Common::Point(80, 62));
_icon4._sceneRegionId = 5;
- _icon4._object2.postInit();
- _icon4._object2.setup(160, 7, 2);
- _icon4._object2.setPosition(Common::Point(106, 86));
+ _icon4._horizLine.postInit();
+ _icon4._horizLine.setup(160, 7, 2);
+ _icon4._horizLine.setPosition(Common::Point(106, 86));
_icon5.postInit();
_icon5.setup(160, 1, 1);
@@ -3998,160 +4047,165 @@ void Scene325::signal() {
R2_GLOBALS._player._canWalk = false;
break;
case 9:
- switch (_field412) {
+ // Fade to black for console sub-section: database, or starchart
+ switch (_consoleAction) {
case 3:
+ // Starchart
_sceneMode = 129;
- _object1.postInit();
- _object2.postInit();
- _object3.postInit();
+ _starGrid1.postInit();
+ _starGrid2.postInit();
+ _starGrid3.postInit();
if (R2_GLOBALS.getFlag(13)) {
- _object4.postInit();
- setAction(&_sequenceManager1, this, 130, &R2_GLOBALS._player, &_object1,
- &_object2, &_object3, &_object4, NULL);
+ // Show starchart with Ringworld present
+ _starGrid4.postInit();
+ setAction(&_sequenceManager1, this, 130, &R2_GLOBALS._player, &_starGrid1,
+ &_starGrid2, &_starGrid3, &_starGrid4, NULL);
} else {
- setAction(&_sequenceManager1, this, 129, &R2_GLOBALS._player, &_object1,
- &_object2, &_object3, NULL);
+ // Show starchart without Ringworld
+ setAction(&_sequenceManager1, this, 129, &R2_GLOBALS._player, &_starGrid1,
+ &_starGrid2, &_starGrid3, NULL);
}
break;
case 17:
case 18:
case 19:
case 20: {
- int v = 10 - ((21 - _field412) * 2);
+ int v = 10 - ((21 - _consoleAction) * 2);
if (R2_GLOBALS.getFlag(50))
--v;
- if (_field418 == 5)
+ if (_priorConsoleAction == 5)
v += 8;
if (R2_GLOBALS.getFlag(51) && (v == 2))
R2_GLOBALS.setFlag(57);
if (R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51)) {
if (v != 13) {
- setMessage(328, 0);
+ setMessage(328, v);
} else {
- _field420 = 864;
-
- _object12.postInit();
- _object2.setup(326, 4, 1);
- _object12.setPosition(Common::Point(149, 128));
- _object12.fixPriority(20);
-
- _object13.postInit();
- _object13.setup(326, 4, 2);
- _object13.setPosition(Common::Point(149, (int)(_field420 * ADJUST_FACTOR)));
- _object13.fixPriority(21);
-
- _object10.postInit();
- _object10.setup(326, 1, 1);
- _object10.setPosition(Common::Point(210, 20));
- _object10.fixPriority(10);
-
- _object1.postInit();
- _object1.setup(326, 1, 1);
- _object1.setPosition(Common::Point(210, 32));
- _object10.fixPriority(10);
-
- _object2.postInit();
- _object2.setup(326, 1, 1);
- _object2.setPosition(Common::Point(210, 44));
- _object2.fixPriority(10);
-
- _object3.postInit();
- _object3.setup(326, 1, 1);
- _object3.setPosition(Common::Point(210, 56));
- _object3.fixPriority(10);
-
- _object4.postInit();
- _object4.setup(326, 1, 1);
- _object4.setPosition(Common::Point(210, 68));
- _object4.fixPriority(10);
-
- _object5.postInit();
- _object5.setup(326, 1, 1);
- _object5.setPosition(Common::Point(210, 80));
- _object5.fixPriority(10);
-
- _object6.postInit();
- _object6.setup(326, 1, 1);
- _object6.setPosition(Common::Point(210, 92));
- _object6.fixPriority(10);
-
- _object7.postInit();
- _object7.setup(326, 1, 1);
- _object7.setPosition(Common::Point(210, 104));
- _object7.fixPriority(10);
-
- _object8.postInit();
- _object8.setup(326, 1, 1);
- _object8.setPosition(Common::Point(210, 116));
- _object8.fixPriority(10);
-
- _object9.postInit();
- _object9.setup(326, 1, 1);
- _object9.setPosition(Common::Point(210, 128));
- _object9.fixPriority(10);
-
- _object11.postInit();
- _object11.setup(326, 1, 1);
- _object11.setPosition(Common::Point(210, 150));
- _object11.fixPriority(10);
+ _scannerLocation = 864;
+
+ _starGrid12.postInit();
+ _starGrid12.setup(326, 4, 1);
+ _starGrid12.setPosition(Common::Point(149, 128));
+ _starGrid12.fixPriority(20);
+
+ _starGrid13.postInit();
+ _starGrid13.setup(326, 4, 2);
+ _starGrid13.setPosition(Common::Point(149, 22 + (int)(_scannerLocation * ADJUST_FACTOR)));
+ _starGrid13.fixPriority(21);
+
+ _starGrid10.postInit();
+ _starGrid10.setup(326, 1, 1);
+ _starGrid10.setPosition(Common::Point(210, 20));
+ _starGrid10.fixPriority(10);
+
+ _starGrid1.postInit();
+ _starGrid1.setup(326, 1, 1);
+ _starGrid1.setPosition(Common::Point(210, 32));
+ _starGrid1.fixPriority(10);
+
+ _starGrid2.postInit();
+ _starGrid2.setup(326, 1, 1);
+ _starGrid2.setPosition(Common::Point(210, 44));
+ _starGrid2.fixPriority(10);
+
+ _starGrid3.postInit();
+ _starGrid3.setup(326, 1, 1);
+ _starGrid3.setPosition(Common::Point(210, 56));
+ _starGrid3.fixPriority(10);
+
+ _starGrid4.postInit();
+ _starGrid4.setup(326, 1, 1);
+ _starGrid4.setPosition(Common::Point(210, 68));
+ _starGrid4.fixPriority(10);
+
+ _starGrid5.postInit();
+ _starGrid5.setup(326, 1, 1);
+ _starGrid5.setPosition(Common::Point(210, 80));
+ _starGrid5.fixPriority(10);
+
+ _starGrid6.postInit();
+ _starGrid6.setup(326, 1, 1);
+ _starGrid6.setPosition(Common::Point(210, 92));
+ _starGrid6.fixPriority(10);
+
+ _starGrid7.postInit();
+ _starGrid7.setup(326, 1, 1);
+ _starGrid7.setPosition(Common::Point(210, 104));
+ _starGrid7.fixPriority(10);
+
+ _starGrid8.postInit();
+ _starGrid8.setup(326, 1, 1);
+ _starGrid8.setPosition(Common::Point(210, 116));
+ _starGrid8.fixPriority(10);
+
+ _starGrid9.postInit();
+ _starGrid9.setup(326, 1, 1);
+ _starGrid9.setPosition(Common::Point(210, 128));
+ _starGrid9.fixPriority(10);
+
+ _starGrid11.postInit();
+ _starGrid11.setup(326, 1, 1);
+ _starGrid11.setPosition(Common::Point(210, 150));
+ _starGrid11.fixPriority(10);
}
} else if (R2_GLOBALS.getFlag(51)) {
setMessage(329, (v == 12) ? 10 : v);
} else {
- setMessage(327, (v < 15) ? 1 : v);
+ setMessage(327, (v >= 15) ? 1 : v);
}
break;
}
case 21:
_sceneMode = 129;
- _object1.postInit();
- _object1.setup(327, 1, 1);
- _object1.setPosition(Common::Point(170, 80));
- _object1.fixPriority(10);
- _object1.animate(ANIM_MODE_5, NULL);
+ _starGrid1.postInit();
+ _starGrid1.setup(327, 1, 1);
+ _starGrid1.setPosition(Common::Point(170, 80));
+ _starGrid1.fixPriority(10);
+ _starGrid1.animate(ANIM_MODE_5, NULL);
break;
case 22:
_sceneMode = 129;
- _object1.postInit();
- _object1.setup(327, 2, 1);
- _object1.setPosition(Common::Point(160, 80));
- _object1.fixPriority(10);
- _object1.animate(ANIM_MODE_5, NULL);
+ _starGrid1.postInit();
+ _starGrid1.setup(327, 2, 1);
+ _starGrid1.setPosition(Common::Point(160, 80));
+ _starGrid1.fixPriority(10);
+ _starGrid1.animate(ANIM_MODE_5, NULL);
break;
case 24:
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- _field416 = 37;
- setMessage(128, _field416);
+ _databasePage = 37;
+ setMessage(128, _databasePage);
break;
case 25:
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- _field416 = 68;
- setMessage(128, _field416);
+ _databasePage = 68;
+ setMessage(128, _databasePage);
break;
case 26:
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- _field416 = 105;
- setMessage(128, _field416);
+ _databasePage = 105;
+ setMessage(128, _databasePage);
break;
default:
- R2_GLOBALS._player.enableControl();
- R2_GLOBALS._player._canWalk = false;
- _field416 = 105;
- setMessage(128, _field416);
+ _databasePage = 0;
+ setMessage(128, _databasePage);
break;
}
+
+ R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player._canWalk = false;
break;
case 10:
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- if ((_field412 >= 17) && (_field412 <= 20)) {
+ if ((_consoleAction >= 17) && (_consoleAction <= 20)) {
_icon5.setIcon(8);
consoleAction(4);
} else {
@@ -4202,7 +4256,7 @@ void Scene325::consoleAction(int id) {
if (id == 7)
_icon5.setIcon(9);
- else if ((_field412 != 3) && ((_field412 < 17) || (_field412 > 26)))
+ else if ((_consoleAction != 3) && ((_consoleAction < 17) || (_consoleAction > 26)))
_icon5.setIcon(8);
switch (id - 1) {
@@ -4211,10 +4265,12 @@ void Scene325::consoleAction(int id) {
_icon2.setIcon(11);
break;
case 1:
+ // Database screen
_icon1.setIcon(23);
_icon2.setIcon(24);
_icon3.setIcon(25);
_icon4.setIcon(26);
+ break;
case 2:
case 16:
case 17:
@@ -4227,8 +4283,88 @@ void Scene325::consoleAction(int id) {
_icon1.hideIcon();
_icon2.hideIcon();
_icon3.hideIcon();
- // TODO: Finish
+
+ if (id == 2 || (id == 19 && _priorConsoleAction == 5 && R2_GLOBALS.getFlag(50) &&
+ R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51))) {
+ _icon5.setIcon(13);
+ _icon4.setPosition(Common::Point(52, 107));
+ _icon4._sceneRegionId = 9;
+ _icon4.setIcon(14);
+ _icon4._horizLine.hide();
+
+ } else {
+ _icon4.hideIcon();
+ _icon5.hideIcon();
+ }
+
+ _icon6.setIcon(12);
+ _sceneMode = 10;
+ _palette.loadPalette(161);
+ R2_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
+ break;
+
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ // Database sub-sections: A-G, N-O, P-S, T-Z
+ R2_GLOBALS._player.disableControl();
+ consoleAction(2);
+ _consoleAction = id;
+ _icon1.hideIcon();
+ _icon2.hideIcon();
+ _icon3.hideIcon();
+ _icon4.hideIcon();
+
+ _icon5.setIcon(13);
+ _icon4.setPosition(Common::Point(52, 107));
+ _icon4._sceneRegionId = 9;
+ _icon4.setIcon(14);
+ _icon4._horizLine.hide();
+
+ _icon6.setIcon(12);
+ _sceneMode = 10;
+ _palette.loadPalette(161);
+ R2_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
+ break;
+
+ case 11:
+ if (R2_GLOBALS.getFlag(57) && (R2_GLOBALS._player._characterIndex == R2_QUINN) && !R2_GLOBALS.getFlag(25)) {
+ R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ _sceneMode = 13;
+ _stripManager.start(403, this);
+ } else {
+ R2_GLOBALS._player.disableControl();
+ id = 8;
+ _text1.remove();
+
+ _icon4.setPosition(Common::Point(80, 62));
+ _icon4._sceneRegionId = 5;
+ _icon4.hideIcon();
+
+ R2_GLOBALS._player.hide();
+ _starGrid1.remove();
+ _starGrid2.remove();
+ _starGrid3.remove();
+ _starGrid4.remove();
+ _starGrid5.remove();
+ _starGrid6.remove();
+ _starGrid7.remove();
+ _starGrid8.remove();
+ _starGrid9.remove();
+ _starGrid10.remove();
+ _starGrid11.remove();
+ _starGrid12.remove();
+ _starGrid13.remove();
+
+ _palette.loadPalette(160);
+ _sceneMode = 11;
+
+ R2_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
+ }
break;
+
case 3:
_icon1.setIcon(5);
_icon2.setIcon(6);
@@ -4236,96 +4372,73 @@ void Scene325::consoleAction(int id) {
break;
case 4:
case 5:
- _field418 = id;
+ _priorConsoleAction = id;
_icon1.setIcon(17);
_icon2.setIcon(18);
_icon3.setIcon(19);
+ _icon4.setIcon(20);
break;
case 7:
- consoleAction(((_field412 == 5) || (_field412 == 6) || (_field412 == 15)) ? 4 : 7);
+ consoleAction(((_consoleAction == 5) || (_consoleAction == 6) || (_consoleAction == 15)) ? 4 : 7);
break;
case 8:
R2_GLOBALS._sceneManager.changeScene(300);
+ break;
case 9:
case 10:
+ // Set language: Interworld or Hero's Tongue
_iconFontNumber = (id - 1) == 9 ? 50 : 52;
_text1.remove();
_icon6.setIcon(7);
- break;
- case 11:
- if (R2_GLOBALS.getFlag(57) && (R2_GLOBALS._player._characterIndex == 1) && !R2_GLOBALS.getFlag(25)) {
- R2_GLOBALS._player.disableControl();
- R2_GLOBALS._events.setCursor(CURSOR_ARROW);
- _sceneMode = 13;
- _stripManager.start(403, this);
- } else {
- R2_GLOBALS._player.disableControl();
- _text1.remove();
-
- _icon4.setPosition(Common::Point(80, 62));
- _icon4._sceneRegionId = 5;
- _icon4.hideIcon();
-
- _object12.remove();
- _object13.remove();
- _object10.remove();
- _object1.remove();
- _object2.remove();
- _object3.remove();
- _object4.remove();
- _object5.remove();
- _object6.remove();
- _object7.remove();
- _object8.remove();
- _object9.remove();
- _object11.remove();
-
- _palette.loadPalette(160);
- _sceneMode = 11;
-
- BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
- }
+ consoleAction(1);
break;
case 12:
+ // Page up button
_icon4.setIcon(14);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
- switch (_field412) {
+ switch (_consoleAction) {
case 17:
case 18:
case 19:
case 20:
- if (_field420) {
+ if (_scannerLocation) {
R2_GLOBALS._player.disableControl();
- _field41A = 1296;
- _field41E = 1;
+ _moveCounter = 1296;
+ _yDirection = 1;
}
break;
default:
- setMessage(128, --_field416);
+ setMessage(128, --_databasePage);
break;
}
return;
case 13:
+ // Page down button
_icon4.setIcon(14);
- _icon4._object2.hide();
+ _icon4._horizLine.hide();
- switch (_field412) {
+ switch (_consoleAction) {
case 17:
case 18:
case 19:
case 20:
- if (_field420 < 1620) {
+ if (_scannerLocation < 1620) {
R2_GLOBALS._player.disableControl();
- _field41A = 1296;
- _field41E = -1;
+ _moveCounter = 1296;
+ _yDirection = -1;
}
break;
+ default:
+ setMessage(128, ++_databasePage);
+ break;
}
return;
case 14:
if (R2_GLOBALS.getFlag(55)) {
- SceneItem::display2(329, 17);
+ consoleAction(4);
+ // Empty message crashing the game. It should be a warning message forbidding to switch to active scan
+ // SceneItem::display2(329, 17);
} else {
R2_GLOBALS.setFlag(50);
consoleAction(4);
@@ -4337,33 +4450,9 @@ void Scene325::consoleAction(int id) {
consoleAction(4);
id = 4;
break;
- case 22:
- case 23:
- case 24:
- case 25:
- R2_GLOBALS._player.disableControl();
- consoleAction(2);
- _field412 = id;
-
- _icon1.hideIcon();
- _icon2.hideIcon();
- _icon3.hideIcon();
- _icon4.hideIcon();
-
- _icon5.setIcon(13);
- _icon4.setPosition(Common::Point(52, 107));
- _icon4._sceneRegionId = 9;
- _icon4.setIcon(14);
- _icon4._object2.hide();
-
- _icon6.setIcon(12);
- _sceneMode = 10;
- _palette.loadPalette(161);
-
- BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
- break;
case 6:
default:
+ // Initial starting screen
_icon1.setIcon(1);
_icon2.setIcon(2);
_icon3.setIcon(3);
@@ -4373,7 +4462,7 @@ void Scene325::consoleAction(int id) {
}
if (id != 8)
- _field412 = id;
+ _consoleAction = id;
}
void Scene325::process(Event &event) {
@@ -4390,107 +4479,107 @@ void Scene325::process(Event &event) {
}
void Scene325::dispatch() {
- if (_field41A) {
- switch (_field41A) {
+ if (_moveCounter) {
+ switch (_moveCounter) {
case 13:
- _field41C = 1;
+ _yChange = 1;
break;
case 1296:
R2_GLOBALS._sound3.play(87);
- _field41C = 1;
+ _yChange = 1;
break;
case 33:
case 1283:
- _field41C = 2;
+ _yChange = 2;
break;
case 63:
case 1263:
- _field41C = 3;
+ _yChange = 3;
break;
case 103:
case 1233:
- _field41C = 4;
+ _yChange = 4;
break;
case 153:
case 1193:
- _field41C = 5;
+ _yChange = 5;
break;
case 213:
case 1143:
- _field41C = 6;
+ _yChange = 6;
break;
case 283:
case 1083:
- _field41C = 7;
+ _yChange = 7;
break;
case 1013:
- _field41C = 8;
+ _yChange = 8;
break;
default:
break;
}
- _field41A -= _field41C;
- int yp = _field41E * _field41C + _object10._position.y;
+ _moveCounter -= _yChange;
+ int yp = _yDirection * _yChange + _starGrid10._position.y;
bool flag = false;
if (yp >= 30) {
yp -= 12;
- --_field420;
+ --_scannerLocation;
flag = true;
}
if (yp <= 10) {
yp += 12;
- ++_field420;
+ ++_scannerLocation;
flag = true;
}
- _object3.setPosition(Common::Point(149, (int)(_field420 * ADJUST_FACTOR) + 22));
+ _starGrid13.setPosition(Common::Point(149, 22 + (int)(_scannerLocation * ADJUST_FACTOR)));
for (int idx = 0; idx < 4; ++idx)
_objList[idx].remove();
if (flag) {
- int v = _field420 - 758;
- _object10.setFrame((v++ <= 0) ? 1 : v);
- _object1.setFrame((v++ <= 0) ? 1 : v);
- _object2.setFrame((v++ <= 0) ? 1 : v);
- _object3.setFrame((v++ <= 0) ? 1 : v);
- _object4.setFrame((v++ <= 0) ? 1 : v);
- _object5.setFrame((v++ <= 0) ? 1 : v);
- _object6.setFrame((v++ <= 0) ? 1 : v);
- _object7.setFrame((v++ <= 0) ? 1 : v);
- _object8.setFrame((v++ <= 0) ? 1 : v);
- _object9.setFrame((v++ <= 0) ? 1 : v);
- _object11.setFrame((v++ <= 0) ? 1 : v);
- }
-
- _object10.setPosition(Common::Point(210, yp));
+ int v = _scannerLocation - 758;
+ _starGrid10.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid1.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid2.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid3.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid4.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid5.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid6.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid7.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid8.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid9.setFrame((v++ <= 0) ? 1 : v);
+ _starGrid11.setFrame((v++ <= 0) ? 1 : v);
+ }
+
+ _starGrid10.setPosition(Common::Point(210, yp));
yp += 12;
- _object1.setPosition(Common::Point(210, yp));
+ _starGrid1.setPosition(Common::Point(210, yp));
yp += 12;
- _object2.setPosition(Common::Point(210, yp));
+ _starGrid2.setPosition(Common::Point(210, yp));
yp += 12;
- _object3.setPosition(Common::Point(210, yp));
+ _starGrid3.setPosition(Common::Point(210, yp));
yp += 12;
- _object4.setPosition(Common::Point(210, yp));
+ _starGrid4.setPosition(Common::Point(210, yp));
yp += 12;
- _object5.setPosition(Common::Point(210, yp));
+ _starGrid5.setPosition(Common::Point(210, yp));
yp += 12;
- _object6.setPosition(Common::Point(210, yp));
+ _starGrid6.setPosition(Common::Point(210, yp));
yp += 12;
- _object7.setPosition(Common::Point(210, yp));
+ _starGrid7.setPosition(Common::Point(210, yp));
yp += 12;
- _object8.setPosition(Common::Point(210, yp));
+ _starGrid8.setPosition(Common::Point(210, yp));
yp += 12;
- _object9.setPosition(Common::Point(210, yp));
+ _starGrid9.setPosition(Common::Point(210, yp));
yp += 12;
- _object11.setPosition(Common::Point(210, yp));
+ _starGrid11.setPosition(Common::Point(210, yp));
- if (!_field41A) {
+ if (!_moveCounter) {
R2_GLOBALS._sound3.stop();
- _field41C = 0;
+ _yChange = 0;
- if (_field420 == 756) {
+ if (_scannerLocation == 756) {
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_USE);
_sceneMode = 12;
@@ -4506,9 +4595,11 @@ void Scene325::dispatch() {
}
void Scene325::setMessage(int resNum, int lineNum) {
- Common::String msg = g_resourceManager->getMessage(resNum, lineNum);
+ removeText();
+ Common::String msg = g_resourceManager->getMessage(resNum, lineNum, true);
if (!msg.empty()) {
+ // Found valid database entry to display
Common::String msgText = parseMessage(msg);
_text1._fontNumber = _iconFontNumber;
@@ -4526,7 +4617,9 @@ void Scene325::setMessage(int resNum, int lineNum) {
R2_GLOBALS._playStream.play(_soundQueue[_soundIndex++], this);
}
} else {
- _field412 = 13;
+ // No message for given database index, so we must have passed beyond
+ // the start or end of the database
+ _consoleAction = 13;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.hide();
@@ -4536,7 +4629,7 @@ void Scene325::setMessage(int resNum, int lineNum) {
_palette.loadPalette(160);
_sceneMode = 11;
- BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
+ R2_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this);
}
}
@@ -4558,15 +4651,16 @@ Common::String Scene325::parseMessage(const Common::String &msg) {
return Common::String(msgP);
}
+
/*--------------------------------------------------------------------------
* Scene 400 - Science Lab
*
*--------------------------------------------------------------------------*/
bool Scene400::Terminal::startAction(CursorType action, Event &event) {
- Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 402;
scene->setAction(&scene->_sequenceManager1, scene, 402, &R2_GLOBALS._player, this, NULL);
@@ -4580,9 +4674,9 @@ bool Scene400::Terminal::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
bool Scene400::Door::startAction(CursorType action, Event &event) {
- Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 401;
scene->setAction(&scene->_sequenceManager1, scene, 401, &R2_GLOBALS._player, this, NULL);
@@ -4594,9 +4688,9 @@ bool Scene400::Door::startAction(CursorType action, Event &event) {
}
bool Scene400::Reader::startAction(CursorType action, Event &event) {
- Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 405;
scene->setAction(&scene->_sequenceManager1, scene, 405, &R2_GLOBALS._player, this, NULL);
@@ -4608,9 +4702,9 @@ bool Scene400::Reader::startAction(CursorType action, Event &event) {
}
bool Scene400::SensorProbe::startAction(CursorType action, Event &event) {
- Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 404;
scene->setAction(&scene->_sequenceManager1, scene, 404, &R2_GLOBALS._player, this, NULL);
@@ -4622,9 +4716,9 @@ bool Scene400::SensorProbe::startAction(CursorType action, Event &event) {
}
bool Scene400::AttractorUnit::startAction(CursorType action, Event &event) {
- Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
-
if (action == CURSOR_USE) {
+ Scene400 *scene = (Scene400 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 406;
scene->setAction(&scene->_sequenceManager1, scene, 406, &R2_GLOBALS._player, this, NULL);
@@ -4638,8 +4732,9 @@ bool Scene400::AttractorUnit::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
void Scene400::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(400);
+ SceneExt::postInit();
+
_sound1.play(20);
_door.postInit();
@@ -4797,10 +4892,15 @@ void Scene400::dispatch() {
*
*--------------------------------------------------------------------------*/
-bool Scene500::ControlPanel::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+Scene500::PanelDialog::Button::Button() {
+ _buttonId = 0;
+ _buttonDown = false;
+}
+bool Scene500::ControlPanel::startAction(CursorType action, Event &event) {
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(26)) {
@@ -4819,17 +4919,18 @@ bool Scene500::ControlPanel::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
-bool Scene500::Object2::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene500::Seeker::startAction(CursorType action, Event &event) {
if (action == CURSOR_TALK) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
scene->_stripNumber = R2_GLOBALS.getFlag(26) ? 1101 : 1103;
} else {
scene->_stripNumber = R2_GLOBALS.getFlag(26) ? 1102 : 1105;
}
+ scene->_sceneMode = 524;
scene->setAction(&scene->_sequenceManager1, scene, 524, &R2_GLOBALS._player, NULL);
return true;
} else {
@@ -4837,7 +4938,7 @@ bool Scene500::Object2::startAction(CursorType action, Event &event) {
}
}
-bool Scene500::Object3::startAction(CursorType action, Event &event) {
+bool Scene500::Suit::startAction(CursorType action, Event &event) {
Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -4848,20 +4949,20 @@ bool Scene500::Object3::startAction(CursorType action, Event &event) {
case CURSOR_USE:
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if ((_strip != 3) && (_strip != 7))
- SceneItem::display2(500, _strip);
+ SceneItem::display2(500, _strip + 25);
else if (R2_GLOBALS.getFlag(26)) {
R2_GLOBALS._player.disableControl();
scene->_stripNumber = 1103;
scene->_sceneMode = 524;
- scene->setAction(&scene->_sequenceManager1, scene, 524, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 512, &R2_GLOBALS._player, NULL);
} else if (!R2_GLOBALS.getFlag(28))
SceneItem::display2(500, 41);
- else if (!R2_GLOBALS.getFlag(40))
+ else if (!R2_GLOBALS.getFlag(25))
SceneItem::display2(500, 40);
else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 512;
- scene->setAction(&scene->_sequenceManager1, scene, 524, &R2_GLOBALS._player, &scene->_object3, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 512, &R2_GLOBALS._player, &scene->_suit, NULL);
R2_GLOBALS.setFlag(26);
}
} else {
@@ -4877,7 +4978,7 @@ bool Scene500::Object3::startAction(CursorType action, Event &event) {
else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 515;
- scene->setAction(&scene->_sequenceManager1, scene, 515, &R2_GLOBALS._player, &scene->_object3, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 515, &R2_GLOBALS._player, &scene->_suit, NULL);
R2_GLOBALS.setFlag(28);
}
return true;
@@ -4887,19 +4988,14 @@ bool Scene500::Object3::startAction(CursorType action, Event &event) {
return true;
default:
- if (action < R2_LAST_INVENT) {
- SceneItem::display2(500, action);
- return true;
- } else {
- return SceneActor::startAction(action, event);
- }
+ return SceneActor::startAction(action, event);
}
}
bool Scene500::Doorway::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(26)) {
@@ -4908,7 +5004,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;
@@ -4918,8 +5014,6 @@ bool Scene500::Doorway::startAction(CursorType action, Event &event) {
}
bool Scene500::OxygenTanks::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
case CURSOR_LOOK:
SceneItem::display2(500, R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) ? 50 : 49);
@@ -4931,6 +5025,8 @@ bool Scene500::OxygenTanks::startAction(CursorType action, Event &event) {
return true;
} else if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) != 1) &&
(R2_GLOBALS._player._characterIndex != R2_SEEKER) && !R2_GLOBALS.getFlag(28)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (_position.y == 120) {
@@ -4954,23 +5050,56 @@ bool Scene500::OxygenTanks::startAction(CursorType action, Event &event) {
}
bool Scene500::AirLock::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
if ((action == CURSOR_USE) && R2_GLOBALS.getFlag(26)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = (R2_GLOBALS._player._characterIndex == R2_QUINN) ? 521 : 522;
scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player,
- &scene->_object2, &scene->_airLock, NULL);
+ &scene->_seeker, &scene->_airLock, NULL);
return true;
} else {
return SceneActor::startAction(action, event);
}
}
-bool Scene500::Aerosol::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+void Scene500::TransparentDoor::draw() {
+ // Determine the area of the screen to be updated
+ Rect destRect = _bounds;
+ destRect.translate(-g_globals->_sceneManager._scene->_sceneBounds.left,
+ -g_globals->_sceneManager._scene->_sceneBounds.top);
+
+ // Get the frame to be drawn
+ GfxSurface frame = getFrame();
+
+ Graphics::Surface s = frame.lockSurface();
+ Graphics::Surface screen = g_globals->gfxManager().getSurface().lockSurface();
+
+ for (int yp = 0; yp < s.h; ++yp) {
+ byte *frameSrcP = (byte *)s.getBasePtr(0, yp);
+ byte *screenP = (byte *)screen.getBasePtr(destRect.left, destRect.top + yp);
+
+ for (int xp = 0; xp < s.w; ++xp, ++frameSrcP, ++screenP) {
+ if (*frameSrcP != frame._transColor && *frameSrcP < 6) {
+ *frameSrcP = R2_GLOBALS._fadePaletteMap[*frameSrcP][*screenP];
+ }
+ }
+ }
+
+ // Finished updating the frame
+ frame.unlockSurface();
+ g_globals->gfxManager().getSurface().unlockSurface();
+
+ // Draw the processed frame
+ Region *priorityRegion = g_globals->_sceneManager._scene->_priorities.find(_priority);
+ g_globals->gfxManager().copyFrom(frame, destRect, priorityRegion);
+}
+
+bool Scene500::Aerosol::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 503;
scene->setAction(&scene->_sequenceManager1, scene, 503, &R2_GLOBALS._player, this, NULL);
@@ -4981,12 +5110,12 @@ bool Scene500::Aerosol::startAction(CursorType action, Event &event) {
}
bool Scene500::SonicStunner::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
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);
@@ -4994,9 +5123,9 @@ bool Scene500::SonicStunner::startAction(CursorType action, Event &event) {
}
bool Scene500::Locker1::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(11))
@@ -5012,9 +5141,9 @@ bool Scene500::Locker1::startAction(CursorType action, Event &event) {
}
bool Scene500::Locker2::startAction(CursorType action, Event &event) {
- Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
-
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(12))
@@ -5029,7 +5158,36 @@ bool Scene500::Locker2::startAction(CursorType action, Event &event) {
}
}
-bool Scene500::Object::startAction(CursorType action, Event &event) {
+/*--------------------------------------------------------------------------*/
+
+void Scene500::PanelDialog::setDetails(int visage, int strip, int frameNumber,
+ const Common::Point &pt) {
+ SceneAreaObject::setDetails(visage, strip, frameNumber, pt);
+ SceneAreaObject::setDetails(500, 43, 32, 45);
+
+ _button1.setupButton(1);
+ _button2.setupButton(2);
+ _button3.setupButton(3);
+}
+
+void Scene500::PanelDialog::remove() {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+ scene->_sceneAreas.remove(&_button1);
+ scene->_sceneAreas.remove(&_button2);
+ scene->_sceneAreas.remove(&_button3);
+
+ _button1.remove();
+ _button2.remove();
+ _button3.remove();
+
+ SceneAreaObject::remove();
+
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 511;
+ scene->setAction(&scene->_sequenceManager1, scene, 511, &R2_GLOBALS._player, NULL);
+}
+
+bool Scene500::PanelDialog::Button::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE) {
return false;
} else {
@@ -5037,13 +5195,127 @@ bool Scene500::Object::startAction(CursorType action, Event &event) {
}
}
+void Scene500::PanelDialog::Button::setupButton(int buttonId) {
+ _buttonId = buttonId;
+ _buttonDown = false;
+ SceneActor::postInit();
+ setup(500, 7, 1);
+ fixPriority(251);
+
+ switch (_buttonId) {
+ case 1:
+ setPosition(Common::Point(139, 78));
+ break;
+ case 2:
+ setPosition(Common::Point(139, 96));
+ break;
+ case 3:
+ setPosition(Common::Point(139, 114));
+ break;
+ default:
+ break;
+ }
+
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+ scene->_sceneAreas.push_front(this);
+}
+
+void Scene500::PanelDialog::Button::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_buttonId);
+ s.syncAsSint16LE(_buttonDown);
+}
+
+void Scene500::PanelDialog::Button::process(Event &event) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) &&
+ (R2_GLOBALS._events.getCursor() == CURSOR_USE) &&
+ _bounds.contains(event.mousePos) && !_buttonDown) {
+ _buttonDown = true;
+ event.handled = true;
+ setFrame(2);
+ }
+
+ if ((event.eventType == EVENT_BUTTON_UP) && _buttonDown) {
+ setFrame(1);
+ _buttonDown = false;
+ event.handled = true;
+
+ doButtonPress();
+ }
+}
+
+void Scene500::PanelDialog::Button::doButtonPress() {
+ if (R2_GLOBALS.getFlag(28)) {
+ SceneItem::display2(500, 48);
+ } else {
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = _buttonId;
+
+ switch (_buttonId) {
+ case 1:
+ // Rotate Left
+ if (--R2_GLOBALS._landerSuitNumber == 0)
+ R2_GLOBALS._landerSuitNumber = R2_MIRANDA;
+
+ if (R2_GLOBALS.getFlag(35)) {
+ scene->_sceneMode = 5;
+ scene->setAction(&scene->_sequenceManager1, scene, 509, &scene->_suits,
+ &scene->_suit, &scene->_transparentDoor, NULL);
+ } else {
+ scene->_sound1.play(127);
+ scene->_suits.animate(ANIM_MODE_6, scene);
+ }
+ break;
+
+ case 2:
+ // Rotate Right
+ if (++R2_GLOBALS._landerSuitNumber == 4)
+ R2_GLOBALS._landerSuitNumber = R2_QUINN;
+
+ if (R2_GLOBALS.getFlag(35)) {
+ scene->_sceneMode = 6;
+ scene->setAction(&scene->_sequenceManager1, scene, 509, &scene->_suits,
+ &scene->_suit, &scene->_transparentDoor, NULL);
+ } else {
+ scene->_sound1.play(127);
+ scene->_suits.animate(ANIM_MODE_6, scene);
+ }
+ break;
+
+ case 3:
+ if (R2_GLOBALS.getFlag(35)) {
+ scene->_sceneMode = 509;
+ scene->setAction(&scene->_sequenceManager1, scene, 509, &scene->_suits,
+ &scene->_suit, &scene->_transparentDoor, NULL);
+ } else {
+ scene->_suit.postInit();
+ scene->_suit.hide();
+ scene->_suit._effect = EFFECT_SHADED;
+ scene->_suit.setDetails(500, -1, -1, -1, 2, (SceneItem *)NULL);
+ scene->_suit.setup(502, R2_GLOBALS._landerSuitNumber + 2, 1);
+
+ scene->setAction(&scene->_sequenceManager1, scene, 508,
+ &R2_GLOBALS._player, &scene->_suits, &scene->_suit,
+ &scene->_transparentDoor, NULL);
+ R2_GLOBALS.setFlag(35);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
/*--------------------------------------------------------------------------*/
void Scene500::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(500);
+ SceneExt::postInit();
- Common::fill(&_buffer[0], &_buffer[2710], 0);
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(50);
_stripManager.addSpeaker(&_seekerSpeaker);
@@ -5053,29 +5325,29 @@ void Scene500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._characterScene[R2_SEEKER] = 500;
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- R2_GLOBALS._walkRegions.disableRegion(1);
-
- _object2.postInit();
- _object2._effect = 1;
- _object2.setup(1505, 1, 1);
- _object2._moveDiff.x = 5;
- _object2.setPosition(Common::Point(42, 151));
- _object2.setDetails(500, 34, 35, 36, 1, (SceneItem *)NULL);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+
+ _seeker.postInit();
+ _seeker._effect = EFFECT_SHADED;
+ _seeker.setup(1505, 1, 1);
+ _seeker._moveDiff.x = 5;
+ _seeker.setPosition(Common::Point(42, 151));
+ _seeker.setDetails(500, 34, 35, 36, 1, (SceneItem *)NULL);
} else if (R2_GLOBALS._player._characterScene[R2_QUINN] == 500) {
- _object2.postInit();
- _object2._effect = 1;
- _object2.setup(R2_GLOBALS.getFlag(26) ? 1500 : 10, 1, 1);
- _object2.setPosition(Common::Point(42, 151));
+ _seeker.postInit();
+ _seeker._effect = EFFECT_SHADED;
+ _seeker.setup(R2_GLOBALS.getFlag(26) ? 1500 : 10, 1, 1);
+ _seeker.setPosition(Common::Point(42, 151));
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(3);
- _object2.setDetails(500, 37, 38, -1, 1, (SceneItem *)NULL);
+ _seeker.setDetails(500, 37, 38, -1, 1, (SceneItem *)NULL);
}
}
- 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));
@@ -5137,30 +5409,30 @@ void Scene500::postInit(SceneObjectList *OwnerList) {
_sonicStunner.setDetails(500, 21, 22, 23, 1, (SceneItem *)NULL);
}
- _object1.postInit();
- _object1._effect = 1;
- _object1.setup(502, 1, 1);
- _object1.setPosition(Common::Point(258, 99));
- _object1.fixPriority(50);
+ _suits.postInit();
+ _suits._effect = EFFECT_SHADED;
+ _suits.setup(502, 1, 1);
+ _suits.setPosition(Common::Point(258, 99));
+ _suits.fixPriority(50);
- _object8.postInit();
- _object8.setPosition(Common::Point(250, 111));
+ _transparentDoor.postInit();
+ _transparentDoor.setPosition(Common::Point(250, 111));
if (!R2_GLOBALS.getFlag(35)) {
- _object8.setup(501, 3, 1);
+ _transparentDoor.setup(501, 3, 1);
} else {
- _object8.setup(500, 8, 7);
+ _transparentDoor.setup(500, 8, 7);
- _object3.postInit();
- _object3._effect = 1;
- _object3.setPosition(Common::Point(247, 52));
- _object3.setDetails(500, -1, -1, -1, 2, (SceneItem *)NULL);
+ _suit.postInit();
+ _suit._effect = EFFECT_SHADED;
+ _suit.setPosition(Common::Point(247, 52));
+ _suit.setDetails(500, -1, -1, -1, 2, (SceneItem *)NULL);
if (!R2_GLOBALS.getFlag(26)) {
if (R2_GLOBALS.getFlag(28))
- _object3.setup(502, 7, 2);
+ _suit.setup(502, 7, 2);
else
- _object3.setup(502, R2_GLOBALS._v566A3 + 2, 7);
+ _suit.setup(502, R2_GLOBALS._landerSuitNumber + 2, 7);
}
}
@@ -5171,7 +5443,7 @@ void Scene500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff.x = 5;
_controlPanel.setDetails(Rect(175, 62, 191, 80), 500, 31, 32, 33, 1, (SceneItem *)NULL);
- _item2.setDetails(Rect(13, 58, 70, 118), 500, 12, -1, -1, 1, (SceneItem *)NULL);
+ _airlockCorridor.setDetails(Rect(13, 58, 70, 118), 500, 12, -1, -1, 1, (SceneItem *)NULL);
_background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 500, 0, -1, -1, 1, (SceneItem *)NULL);
if ((R2_GLOBALS._player._characterIndex == R2_QUINN) && (R2_GLOBALS._sceneManager._previousScene == 700)) {
@@ -5203,34 +5475,34 @@ void Scene500::signal() {
case 5:
_sceneMode = 12;
_sound1.play(127);
- _object1.animate(ANIM_MODE_6, this);
+ _suits.animate(ANIM_MODE_6, this);
R2_GLOBALS.clearFlag(35);
- _object3.remove();
+ _suit.remove();
R2_GLOBALS._player.enableControl();
break;
case 6:
_sceneMode = 11;
_sound1.play(127);
- _object1.animate(ANIM_MODE_5, this);
+ _suits.animate(ANIM_MODE_5, this);
R2_GLOBALS.clearFlag(35);
- _object3.remove();
+ _suit.remove();
R2_GLOBALS._player.enableControl();
break;
case 7:
_sound1.play(126);
- _object8.animate(ANIM_MODE_6, this);
+ _transparentDoor.animate(ANIM_MODE_6, this);
R2_GLOBALS.clearFlag(35);
- _object3.remove();
+ _suit.remove();
R2_GLOBALS._player.enableControl();
break;
case 500:
R2_GLOBALS._sceneManager.changeScene(700);
break;
case 501:
- if (R2_GLOBALS._player._characterScene[R2_QUINN] == 500) {
+ if (R2_GLOBALS._player._characterScene[R2_SEEKER] == 500) {
_stripNumber = 1100;
_sceneMode = 523;
setAction(&_sequenceManager1, this, 523, &R2_GLOBALS._player, NULL);
@@ -5261,7 +5533,7 @@ void Scene500::signal() {
break;
case 506:
case 518:
- R2_GLOBALS.setFlag(11);
+ R2_GLOBALS.setFlag(12);
R2_GLOBALS._player.enableControl();
break;
case 507:
@@ -5271,12 +5543,12 @@ void Scene500::signal() {
break;
case 509:
R2_GLOBALS.clearFlag(35);
- _object3.remove();
+ _suit.remove();
R2_GLOBALS._player.enableControl();
break;
case 510:
R2_GLOBALS._player.enableControl();
- _area1.setDetails(500, 6, 1, Common::Point(160, 120));
+ _panelDialog.setDetails(500, 6, 1, Common::Point(160, 120));
R2_GLOBALS._player.enableControl();
break;
case 513:
@@ -5316,6 +5588,7 @@ void Scene500::signal() {
* Scene 525 - Cutscene - Walking in hall
*
*--------------------------------------------------------------------------*/
+
void Scene525::postInit(SceneObjectList *OwnerList) {
loadScene(525);
R2_GLOBALS._uiElements._active = false;
@@ -5324,7 +5597,7 @@ void Scene525::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(105);
_actor1.postInit();
- _actor1._effect = 1;
+ _actor1._effect = EFFECT_SHADED;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
@@ -5338,42 +5611,32 @@ 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;
}
-bool Scene600::Item4::startAction(CursorType action, Event &event) {
+bool Scene600::EngineCompartment::startAction(CursorType action, Event &event) {
if ((action != R2_NEGATOR_GUN) || (!R2_GLOBALS.getFlag(1)))
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;
}
@@ -5384,36 +5647,59 @@ bool Scene600::Item4::startAction(CursorType action, Event &event) {
Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
- scene->_object1.setup2(603, 3, 1, 239, 54, 10, 0);
- scene->_actor3.postInit();
- scene->_actor2.postInit();
+ scene->_stasisArea.setup(603, 3, 1, 239, 54, 10);
+ scene->_stasisField.postInit();
+ scene->_computer.postInit();
scene->_sceneMode = 612;
- setAction(&scene->_sequenceManager1, this, 612, &scene->_actor3, &scene->_actor2, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 612, &scene->_stasisField, &scene->_computer, &R2_GLOBALS._player, NULL);
+
+ // WORKAROUND: For ScummVM, we use a SceneActor rather than BackgroundSceneObject
+ // for the stasis field since it doesn't work properly. We override the priority for
+ // the stasis field here so that the stasis field dissolve will show up
+ scene->_stasisField.fixPriority(12);
+
return true;
}
-void Scene600::Actor4::signal() {
- Common::Point pt(36, 177 + R2_GLOBALS._randomSource.getRandomNumber(5));
+void Scene600::Smoke::signal() {
+ 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))
+bool Scene600::Smoke::startAction(CursorType action, Event &event) {
+ 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::Smoke::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.getPixels();
+
+ while (srcP < ((byte *)surface.getBasePtr(0, surface.h))) {
+ *srcP = pixelMap[*srcP];
+ srcP++;
+ }
+
+ frame.unlockSurface();
+ }
+
+ return frame;
}
-bool Scene600::Actor5::startAction(CursorType action, Event &event) {
- if ((action < CURSOR_WALK) && (action >= R2CURSORS_START))
+bool Scene600::Doorway::startAction(CursorType action, Event &event) {
+ // Only action cursors
+ if (action < CURSOR_WALK)
return false;
if (action != CURSOR_USE)
@@ -5423,10 +5709,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->_laserBeam, NULL);
return true;
}
@@ -5436,36 +5722,37 @@ 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;
}
if ((R2_GLOBALS.getFlag(9)) && (R2_INVENTORY.getObjectScene(R2_COM_SCANNER) == 600))
- SceneItem::display(600, 31, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(600, 31, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
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 laser is destroyed
if (R2_GLOBALS.getFlag(6)) {
if (R2_GLOBALS.getFlag(8)) {
- SceneItem::display(600, 29, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(600, 29, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
} else {
R2_GLOBALS._player.disableControl();
- scene->_actor8.postInit();
- scene->_actor8.setDetails(600, 20, -1, -1, 4, &scene->_actor6);
+ scene->_scanner.postInit();
+ scene->_scanner.setDetails(600, 20, -1, -1, 4, &scene->_laser);
scene->_sceneMode = 607;
- scene->setAction(&scene->_sequenceManager1, scene, 607, &R2_GLOBALS._player, &scene->_actor8, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 607, &R2_GLOBALS._player, &scene->_scanner, NULL);
return true;
}
} else {
@@ -5474,32 +5761,33 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
break;
case R2_AEROSOL:
if (R2_GLOBALS.getFlag(5)) {
- SceneItem::display(600, 28, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(600, 28, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
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);
- scene->_actor4._effect = 3;
- 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->_smoke.postInit();
+ scene->_smoke.setup(601, 3, 1);
+ scene->_smoke._effect = EFFECT_3;
+ scene->_smoke._moveDiff = Common::Point(1, 1);
+ scene->_smoke._moveRate = 2;
+ scene->_smoke._numFrames = 3;
+ scene->_smoke.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->_smoke, &scene->_doorway, NULL);
return true;
}
break;
case R2_CLAMP:
+ // If cloud is active
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,45 +5797,62 @@ 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 {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 610;
- scene->setAction(&scene->_sequenceManager1, scene, 610, &scene->_actor1, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 610, &scene->_laserBeam, &R2_GLOBALS._player, NULL);
return true;
}
} else
return SceneActor::startAction(action, event);
}
-bool Scene600::Actor7::startAction(CursorType action, Event &event) {
- Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
-
- if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) {
+bool Scene600::Aerosol::startAction(CursorType action, Event &event) {
+ // Only action cursors
+ if (action < CURSOR_WALK)
return false;
- } else if (action == CURSOR_USE) {
+
+ if (action == CURSOR_USE) {
+ Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
+
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);
}
}
-bool Scene600::Actor8::startAction(CursorType action, Event &event) {
+/*--------------------------------------------------------------------------*/
+
+Scene600::Scene600() {
+ _roomState = 0;
+ Common::fill(&_pixelMap[0], &_pixelMap[256], 0);
+}
+
+void Scene600::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_roomState);
+ for (int i = 0; i < 256; i++)
+ s.syncAsByte(_pixelMap[i]);
+}
+
+bool Scene600::Scanner::startAction(CursorType action, Event &event) {
Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
- if ((action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(9) == 600)) {
+ if ((action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(R2_COM_SCANNER) == 600)) {
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))){
+ scene->setAction(&scene->_sequenceManager1, scene, 615, &R2_GLOBALS._player, &scene->_scanner, NULL);
+ } else if ((action == R2_SONIC_STUNNER) && (R2_INVENTORY.getObjectScene(R2_COM_SCANNER) == 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);
+ scene->setAction(&scene->_sequenceManager1, scene, 608, &R2_GLOBALS._player, &scene->_smoke, NULL);
} else {
return SceneActor::startAction(action, event);
}
@@ -5559,26 +5864,34 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
loadScene(600);
SceneExt::postInit();
R2_GLOBALS.setFlag(39);
- R2_GLOBALS._walkRegions.enableRegion(3);
- _field412 = 0;
-
- warning("FIXME: loop to initialize _fieldAD2[]");
-
- _actor5.postInit();
- _actor5.setVisage(600);
- _actor5.setPosition(Common::Point(29, 147));
- _actor5.fixPriority(10);
- _actor5.setDetails(300, 3, -1, -1, 1, (SceneItem *) NULL);
-
- _actor6.postInit();
- _actor6.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) {
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ _roomState = 0;
+
+ // Initialize 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);
+
+ _pixelMap[i] = R2_GLOBALS._paletteMap[(av << 8) | (av << 4) | av];
+ }
+
+ _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(R2_COM_SCANNER) == 600) {
+ _scanner.postInit();
+ _scanner.setup(602, 5, 1);
+ _scanner.setPosition(Common::Point(246, 41));
+ _scanner.setDetails(600, 20, -1, -1, 1, (SceneItem *) NULL);
+ switch (R2_GLOBALS._scannerFrequencies[1] - 2) {
case 0:
R2_GLOBALS._sound4.play(45);
break;
@@ -5597,48 +5910,50 @@ 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);
- _actor1.setPosition(Common::Point(223, 51));
- _actor1.fixPriority(200);
+ _laserBeam.postInit();
+ _laserBeam.setup(600, 3, 5);
+ _laserBeam.setPosition(Common::Point(223, 51));
+ _laserBeam.fixPriority(200);
}
if (! R2_GLOBALS.getFlag(9))
- _object1.setup2(603, 1, 1, 244, 50, 10, 0);
+ _stasisArea.setup(603, 1, 1, 244, 50, 10);
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);
+ if (R2_INVENTORY.getObjectScene(R2_AEROSOL) == 600) {
+ _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)) {
if (R2_GLOBALS.getFlag(9)) {
- _actor2.postInit();
- _actor2.setup(603, 2, 1);
- _actor2.setPosition(Common::Point(233, 45));
- _actor2.animate(ANIM_MODE_2, NULL);_actor2.fixPriority(11);
+ // Computer is active
+ _computer.postInit();
+ _computer.setup(603, 2, 1);
+ _computer.setPosition(Common::Point(233, 45));
+ _computer.animate(ANIM_MODE_2, NULL);
+ _computer.fixPriority(11);
}
} else {
- _actor4.postInit();
- _actor4.setup(601, 1, 1);
- _actor4.setPosition(Common::Point(180, 110));
- _actor4._moveDiff = Common::Point(1, 1);
- _actor4._moveRate = 2;
- _actor4._numFrames = 3;
- _actor4.animate(ANIM_MODE_2, NULL);
- _actor4.fixPriority(130);
- _actor4._effect = 3;
- _actor4.setDetails(600, 24, 25, 26, 1, (SceneItem *) NULL);
- _actor4.signal();
+ _smoke.postInit();
+ _smoke.setup(601, 1, 1);
+ _smoke.setPosition(Common::Point(180, 110));
+ _smoke._moveDiff = Common::Point(1, 1);
+ _smoke._moveRate = 2;
+ _smoke._numFrames = 3;
+ _smoke.animate(ANIM_MODE_2, NULL);
+ _smoke.fixPriority(130);
+ _smoke._effect = EFFECT_3;
+ _smoke.setDetails(600, 24, 25, 26, 1, (SceneItem *) NULL);
+ _smoke.signal();
}
}
@@ -5647,34 +5962,34 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _item2.setDetails(12, 600, 17, -1, 19);
- _item3.setDetails(11, 600, 14, -1, -1);
+ _quantumRegulator.setDetails(12, 600, 17, -1, 19);
+ _powerNode.setDetails(11, 600, 14, -1, -1);
if (R2_GLOBALS.getFlag(9)) {
- _item1.setDetails(Rect(159, 3, 315, 95), 600, 7, -1, -1, 1, NULL);
+ _quantumDrive.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);
+ _engineCompartment.setDetails(Rect(173, 15, 315, 45), 600, 21, -1, 23, 1, NULL);
+ _quantumDrive.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);
+ _background.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, &_laserBeam, NULL);
} else {
- setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_actor5, &_actor6, &_actor1, NULL);
+ setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_doorway, &_laser, &_laserBeam, 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();
@@ -5682,7 +5997,7 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
}
void Scene600::remove() {
- if (R2_INVENTORY.getObjectScene(9) == 600)
+ if (R2_INVENTORY.getObjectScene(R2_COM_SCANNER) == 600)
R2_GLOBALS._sound4.fadeOut2(NULL);
SceneExt::remove();
}
@@ -5697,55 +6012,63 @@ void Scene600::signal() {
R2_GLOBALS._sceneManager.changeScene(700);
break;
case 605:
+ // After cloud is active
R2_GLOBALS._player.enableControl();
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(9);
- R2_GLOBALS._walkRegions.enableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ R2_GLOBALS._walkRegions.disableRegion(10);
- R2_INVENTORY.setObjectScene(12, 600);
+ R2_INVENTORY.setObjectScene(R2_AEROSOL, 600);
R2_GLOBALS.setFlag(5);
- _actor4._effect = 3;
- _actor4.signal();
+ _smoke._effect = EFFECT_3;
+ _smoke.signal();
break;
case 606:
- R2_INVENTORY.setObjectScene(15, 600);
+ // After Clamp is put on laser
+ R2_INVENTORY.setObjectScene(R2_CLAMP, 600);
R2_GLOBALS._player.enableControl();
break;
case 607:
- R2_INVENTORY.setObjectScene(9, 600);
+ // After scanner is put on laser
+ R2_INVENTORY.setObjectScene(R2_COM_SCANNER, 600);
R2_GLOBALS._player.enableControl();
break;
case 608:
+ // deactivate cloud
R2_GLOBALS.setFlag(8);
- _actor4.remove();
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(9);
- R2_GLOBALS._walkRegions.disableRegion(10);
+ _smoke.remove();
+ R2_GLOBALS._walkRegions.enableRegion(6);
+ R2_GLOBALS._walkRegions.enableRegion(9);
+ R2_GLOBALS._walkRegions.enableRegion(10);
R2_GLOBALS._player.enableControl();
break;
case 612:
+ // Deactivate stasis field
R2_GLOBALS.setFlag(9);
- _actor3.remove();
- R2_GLOBALS._sceneItems.remove(&_item4);
- _actor2.setDetails(600, 21, -1, 23, 4, &_item4);
- _item1.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL);
+ _stasisField.remove();
+ R2_GLOBALS._sceneItems.remove(&_engineCompartment);
+ _computer.setDetails(600, 21, -1, 23, 4, &_engineCompartment);
+ _engineCompartment.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL);
+ _quantumDrive._lookLineNum = 7;
R2_GLOBALS._player.enableControl(CURSOR_USE);
break;
case 614:
+ // Pick up Aerosol
R2_GLOBALS._player.enableControl();
- _actor7.remove();
- R2_INVENTORY.setObjectScene(12, 1);
- R2_GLOBALS._walkRegions.disableRegion(7);
+ _aerosol.remove();
+ R2_INVENTORY.setObjectScene(R2_AEROSOL, 1);
+ R2_GLOBALS._walkRegions.enableRegion(7);
break;
case 615:
- _actor8.remove();
- R2_INVENTORY.setObjectScene(9, 1);
+ // Pick up Com Scanner
+ _scanner.remove();
+ R2_INVENTORY.setObjectScene(R2_COM_SCANNER, 1);
R2_GLOBALS._player.enableControl();
break;
default:
- _field412 = 0;
+ _roomState = 0;
_sceneMode = 0;
R2_GLOBALS._player.enableControl();
break;
@@ -5753,59 +6076,64 @@ 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;
+ _roomState += 10;
} else {
R2_GLOBALS._player.disableControl();
_sceneMode = 604;
- setAction(&_sequenceManager1, this, 604, &_actor1, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager1, this, 604, &_laserBeam, &R2_GLOBALS._player, NULL);
event.handled = true;
}
} 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)){
- _field412 += 10;
+ } else if ((!R2_GLOBALS.getFlag(6)) && (R2_GLOBALS._player._mover) && (_roomState < 10)){
+ _roomState += 10;
}
Scene::process(event);
}
void Scene600::dispatch() {
- if ((_field412 != 0) && (_sceneMode != 600) && (_sceneMode != 603) && (_sceneMode != 602)) {
- if ( ((_actor6._strip == 4) && (_actor6._frame > 1))
+ if ((_roomState != 0) && (_sceneMode != 600) && (_sceneMode != 603) && (_sceneMode != 602)) {
+ if ( ((_laser._strip == 4) && (_laser._frame > 1))
|| (_sceneMode == 601)
- || ((_sceneMode == 616) && (_actor5._frame > 1)) )
- _field412 = 0;
+ || ((_sceneMode == 616) && (_doorway._frame > 1)) )
+ _roomState = 0;
else {
- _field412--;
- if (_field412 % 10 == 0) {
- _actor1.setAction(&_sequenceManager2, NULL, 611, &_actor1, NULL);
+ _roomState--;
+ if (_roomState % 10 == 0) {
+ _laserBeam.setAction(&_sequenceManager2, NULL, 611, &_laserBeam, NULL);
}
- if ((_field412 == 0) && (R2_GLOBALS._player._mover))
- _field412 = 10;
+ if ((_roomState == 0) && (R2_GLOBALS._player._mover))
+ _roomState = 10;
}
}
- if (_actor1._frame == 2)
- _aSound1.play(40);
+ if (_laserBeam._frame == 2)
+ _sound1.play(40);
Scene::dispatch();
- if ((_actor4._strip == 3) && (_actor4._frame == 3)) {
- _actor1.setStrip(4);
- _actor1.setFrame(1);
+ if ((_smoke._strip == 3) && (_smoke._frame == 3)) {
+ _laserBeam.setStrip(4);
+ _laserBeam.setFrame(1);
}
}
/*--------------------------------------------------------------------------
- * Scene 700 -
+ * Scene 700 - Lander Bay 2
*
*--------------------------------------------------------------------------*/
+
+#define CABLE700_X 26
+#define CABLE700_Y -5
+
Scene700::Scene700() {
_rotation = NULL;
}
@@ -5815,33 +6143,33 @@ void Scene700::synchronize(Serializer &s) {
SYNC_POINTER(_rotation);
}
-bool Scene700::Item11::startAction(CursorType action, Event &event) {
+bool Scene700::Loft::startAction(CursorType action, Event &event) {
if ((action == CURSOR_USE) && (R2_GLOBALS._player._position.x < 100))
return false;
return NamedHotspot::startAction(action, event);
}
-bool Scene700::Item12::startAction(CursorType action, Event &event) {
+bool Scene700::HandGrip::startAction(CursorType action, Event &event) {
Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case R2_CABLE_HARNESS:
R2_GLOBALS._player.disableControl();
- scene->_actor5.postInit();
- scene->_actor5.setup(701, 3, 2);
- scene->_actor5.setPosition(Common::Point(243, 98));
- scene->_actor5.setDetails(700, 37, -1, -1, 2, (SceneItem *) NULL);
- scene->_actor5.hide();
+ scene->_cable.postInit();
+ scene->_cable.setup(701, 3, 2);
+ scene->_cable.setPosition(Common::Point(243, 98));
+ scene->_cable.setDetails(700, 37, -1, -1, 2, (SceneItem *) NULL);
+ scene->_cable.hide();
scene->_sceneMode = 20;
break;
case R2_ATTRACTOR_CABLE_HARNESS:
R2_GLOBALS._player.disableControl();
- scene->_actor5.postInit();
- scene->_actor5.setup(701, 2, 8);
- scene->_actor5.setPosition(Common::Point(243, 98));
- scene->_actor5.setDetails(700, 38, -1, -1, 2, (SceneItem *) NULL);
- scene->_actor5.hide();
+ scene->_cable.postInit();
+ scene->_cable.setup(701, 2, 8);
+ scene->_cable.setPosition(Common::Point(243, 98));
+ scene->_cable.setDetails(700, 38, -1, -1, 2, (SceneItem *) NULL);
+ scene->_cable.hide();
scene->_sceneMode = 21;
break;
default:
@@ -5849,19 +6177,19 @@ 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->_cable, NULL);
return true;
}
-bool Scene700::Actor2::startAction(CursorType action, Event &event) {
- Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene700::LiftDoor::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
if (R2_GLOBALS._player._position.y <= 100)
return false;
+ Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 701;
scene->setAction(&scene->_sequenceManager, scene, 701, &R2_GLOBALS._player, this, NULL);
@@ -5869,15 +6197,15 @@ bool Scene700::Actor2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene700::Actor3::startAction(CursorType action, Event &event) {
- Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene700::SuitRoomDoor::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
if (R2_GLOBALS._player._position.y <= 100)
return false;
+ Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 702;
scene->setAction(&scene->_sequenceManager, scene, 702, &R2_GLOBALS._player, this, NULL);
@@ -5885,15 +6213,15 @@ bool Scene700::Actor3::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene700::Actor4::startAction(CursorType action, Event &event) {
- Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene700::ControlPanel::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
if (R2_GLOBALS._player._position.y <= 100)
return false;
+ Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 704;
scene->setAction(&scene->_sequenceManager, scene, 704, &R2_GLOBALS._player, this, NULL);
@@ -5901,7 +6229,7 @@ bool Scene700::Actor4::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene700::Actor5::startAction(CursorType action, Event &event) {
+bool Scene700::Cable::startAction(CursorType action, Event &event) {
Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -5910,7 +6238,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 {
@@ -5935,9 +6263,9 @@ bool Scene700::Actor5::startAction(CursorType action, Event &event) {
break;
case R2_ATTRACTOR_UNIT:
R2_GLOBALS._player.disableControl();
- if (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 700) {
+ if (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) != 700) {
scene->_sceneMode = 706;
- scene->setAction(&scene->_sequenceManager, scene, 706, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 706, &R2_GLOBALS._player, &scene->_cable, NULL);
} else {
scene->_sceneMode = 15;
Common::Point pt(_position.x - 12, _position.y + 1);
@@ -5953,12 +6281,12 @@ bool Scene700::Actor5::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene700::Actor6::startAction(CursorType action, Event &event) {
- Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene700::LoftDoor::startAction(CursorType action, Event &event) {
if ((action != CURSOR_USE) || (R2_GLOBALS._player._position.y >= 100))
return SceneActor::startAction(action, event);
+ Scene700 *scene = (Scene700 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1;
Common::Point pt(_position.x, 69);
@@ -5969,70 +6297,68 @@ bool Scene700::Actor6::startAction(CursorType action, Event &event) {
}
void Scene700::postInit(SceneObjectList *OwnerList) {
- if (R2_GLOBALS._sceneManager._previousScene == 900)
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
-
loadScene(700);
- R2_GLOBALS._v558B6.set(60, 0, 260, 200);
+ if (R2_GLOBALS._sceneManager._previousScene == 900)
+ _sceneBounds = Rect(160, 0, 480, 200);
SceneExt::postInit();
_rotation = R2_GLOBALS._scenePalette.addRotation(237, 246, -1);
_rotation->setDelay(5);
_rotation->_countdown = 1;
- _actor2.postInit();
- _actor2.setVisage(700);
- _actor2.setPosition(Common::Point(21, 128));
- _actor2.fixPriority(10);
- _actor2.setDetails(700, 3, -1, -1, 1, (SceneItem *) NULL);
-
- _actor3.postInit();
- _actor3.setup(700, 2, 1);
- _actor3.setPosition(Common::Point(217, 120));
- _actor3.fixPriority(10);
- _actor3.setDetails(700, 15, -1, -1, 1, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(700, 4, 1);
- _actor1.setPosition(Common::Point(355 - ((R2_GLOBALS._v565E3 * 8) / 5), ((R2_GLOBALS._v565E1 + 20 ) / 5) - 12));
- _actor1.fixPriority(10);
- _actor1.setDetails(700, 12, -1, 14, 1, (SceneItem *) NULL);
-
- _actor6.postInit();
- _actor6.setup(700, 8, 1);
- _actor6.setPosition(Common::Point(85, 53));
- _actor6.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
-
- _actor7.postInit();
- _actor7.setup(700, 8, 1);
- _actor7.setPosition(Common::Point(164, 53));
- _actor7.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
-
- _actor8.postInit();
- _actor8.setup(700, 8, 1);
- _actor8.setPosition(Common::Point(243, 53));
- _actor8.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
-
- _actor9.postInit();
- _actor9.setup(700, 8, 1);
- _actor9.setPosition(Common::Point(324, 53));
- _actor9.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
+ _liftDoor.postInit();
+ _liftDoor.setVisage(700);
+ _liftDoor.setPosition(Common::Point(21, 128));
+ _liftDoor.fixPriority(10);
+ _liftDoor.setDetails(700, 3, -1, -1, 1, (SceneItem *) NULL);
+
+ _suitRoomDoor.postInit();
+ _suitRoomDoor.setup(700, 2, 1);
+ _suitRoomDoor.setPosition(Common::Point(217, 120));
+ _suitRoomDoor.fixPriority(10);
+ _suitRoomDoor.setDetails(700, 15, -1, -1, 1, (SceneItem *) NULL);
+
+ _electromagnet.postInit();
+ _electromagnet.setup(700, 4, 1);
+ _electromagnet.setPosition(Common::Point(355 - ((R2_GLOBALS._electromagnetZoom * 8) / 5), ((R2_GLOBALS._electromagnetChangeAmount + 20 ) / 5) - 12));
+ _electromagnet.fixPriority(10);
+ _electromagnet.setDetails(700, 12, -1, 14, 1, (SceneItem *) NULL);
+
+ _loftDoor1.postInit();
+ _loftDoor1.setup(700, 8, 1);
+ _loftDoor1.setPosition(Common::Point(85, 53));
+ _loftDoor1.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
+
+ _loftDoor2.postInit();
+ _loftDoor2.setup(700, 8, 1);
+ _loftDoor2.setPosition(Common::Point(164, 53));
+ _loftDoor2.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
+
+ _loftDoor3.postInit();
+ _loftDoor3.setup(700, 8, 1);
+ _loftDoor3.setPosition(Common::Point(243, 53));
+ _loftDoor3.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
+
+ _loftDoor4.postInit();
+ _loftDoor4.setup(700, 8, 1);
+ _loftDoor4.setPosition(Common::Point(324, 53));
+ _loftDoor4.setDetails(700, 33, -1, 35, 1, (SceneItem *) NULL);
if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) != 1) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) != 1)) {
- _actor5.postInit();
- _actor5.fixPriority(10);
+ _cable.postInit();
+ _cable.fixPriority(10);
switch (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS)) {
case 0:
switch (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS)) {
case 0:
- _actor5.setup(701, 3, 2);
- _actor5.setPosition(Common::Point(243, 98));
- _actor5.setDetails(700, 37, -1, -1, 1, (SceneItem *) NULL);
+ _cable.setup(701, 3, 2);
+ _cable.setPosition(Common::Point(243, 98));
+ _cable.setDetails(700, 37, -1, -1, 1, (SceneItem *) NULL);
break;
case 700:
- _actor5.setup(701, 3, 1);
- _actor5.setPosition(Common::Point(356 - (R2_GLOBALS._v565EB * 8), 148 - (((R2_GLOBALS._v565E9 + 10) / 5) * 4)));
- _actor5.setDetails(700, 37, -1, -1, 1, (SceneItem *) NULL);
+ _cable.setup(701, 3, 1);
+ _cable.setPosition(Common::Point(356 - (CABLE700_X * 8), 148 - (((CABLE700_Y + 10) / 5) * 4)));
+ _cable.setDetails(700, 37, -1, -1, 1, (SceneItem *) NULL);
break;
default:
break;
@@ -6041,23 +6367,23 @@ 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))
- _actor5.setup(701, 2, 1);
+ if (R2_GLOBALS._tractorField && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
+ _cable.setup(701, 2, 1);
else
- _actor5.setup(701, 2, 8);
- _actor5.setPosition(Common::Point(243, 98));
- _actor5.fixPriority(77);
- _actor5.setDetails(700, 38, -1, -1, 1, (SceneItem *) NULL);
+ _cable.setup(701, 2, 8);
+ _cable.setPosition(Common::Point(243, 98));
+ _cable.fixPriority(77);
+ _cable.setDetails(700, 38, -1, -1, 1, (SceneItem *) NULL);
break;
case 700:
- _actor5.setup(701, 1, 8);
- if (R2_GLOBALS._v565E7 == 0) {
- _actor5.setPosition(Common::Point(356 - (R2_GLOBALS._v565EB * 8), 148 - (((R2_GLOBALS._v565E9 + 10) / 5) * 4)));
+ _cable.setup(701, 1, 8);
+ if (!R2_GLOBALS._cableAttached) {
+ _cable.setPosition(Common::Point(356 - (CABLE700_X * 8), 148 - (((CABLE700_Y + 10) / 5) * 4)));
} else {
- _actor5.setup(701, 1, 1);
- _actor5.setPosition(Common::Point(_actor1._position.x + 1, _actor1._position.y + 120));
+ _cable.setup(701, 1, 1);
+ _cable.setPosition(Common::Point(_electromagnet._position.x + 1, _electromagnet._position.y + 120));
}
- _actor5.setDetails(700, 38, -1, -1, 1, (SceneItem *) NULL);
+ _cable.setDetails(700, 38, -1, -1, 1, (SceneItem *) NULL);
break;
default:
break;
@@ -6067,23 +6393,23 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
}
}
- _actor4.postInit();
- _actor4.setup(700, 3, 1);
- _actor4.setPosition(Common::Point(454, 117));
- _actor4.setDetails(700, 27, -1, -1, 1, (SceneItem *) NULL);
-
- _item12.setDetails(Rect(234, 90, 252, 110), 700, 39, -1, -1, 1, NULL);
- _item6.setDetails(Rect(91, 158, 385, 167), 700, 6, -1, 8, 1, NULL);
- _item2.setDetails(Rect(47, 115, 149, 124), 700, 40, -1, 41, 1, NULL);
- _item3.setDetails(Rect(151, 108, 187, 124), 700, 40, -1, 41, 1, NULL);
- _item4.setDetails(Rect(247, 108, 275, 124), 700, 40, -1, 41, 1, NULL);
- _item5.setDetails(Rect(300, 105, 321, 124), 700, 40, -1, 41, 1, NULL);
- _item7.setDetails(Rect(255, 74, 368, 115), 700, 9, -1, 11, 1, NULL);
- _item8.setDetails(Rect(69, 74, 182, 115), 700, 9, -1, 11, 1, NULL);
- _item9.setDetails(Rect(370, 58, 475, 103), 700, 18, -1, -1, 1, NULL);
- _item10.setDetails(Rect(17, 11, 393, 31), 700, 24, -1, -1, 1, NULL);
- _item11.setDetails(Rect(42, 32, 368, 66), 700, 30, -1, 32, 1, NULL);
- _item1.setDetails(Rect(0, 0, 480, 200), 700, 0, -1, -1, 1, NULL);
+ _controlPanel.postInit();
+ _controlPanel.setup(700, 3, 1);
+ _controlPanel.setPosition(Common::Point(454, 117));
+ _controlPanel.setDetails(700, 27, -1, -1, 1, (SceneItem *) NULL);
+
+ _handGrip.setDetails(Rect(234, 90, 252, 110), 700, 39, -1, -1, 1, NULL);
+ _restraintCollar.setDetails(Rect(91, 158, 385, 167), 700, 6, -1, 8, 1, NULL);
+ _debris1.setDetails(Rect(47, 115, 149, 124), 700, 40, -1, 41, 1, NULL);
+ _debris2.setDetails(Rect(151, 108, 187, 124), 700, 40, -1, 41, 1, NULL);
+ _debris3.setDetails(Rect(247, 108, 275, 124), 700, 40, -1, 41, 1, NULL);
+ _debris4.setDetails(Rect(300, 105, 321, 124), 700, 40, -1, 41, 1, NULL);
+ _storage2.setDetails(Rect(255, 74, 368, 115), 700, 9, -1, 11, 1, NULL);
+ _storage1.setDetails(Rect(69, 74, 182, 115), 700, 9, -1, 11, 1, NULL);
+ _stars.setDetails(Rect(370, 58, 475, 103), 700, 18, -1, -1, 1, NULL);
+ _light.setDetails(Rect(17, 11, 393, 31), 700, 24, -1, -1, 1, NULL);
+ _loft.setDetails(Rect(42, 32, 368, 66), 700, 30, -1, 32, 1, NULL);
+ _background.setDetails(Rect(0, 0, 480, 200), 700, 0, -1, -1, 1, NULL);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setVisage(11);
@@ -6097,14 +6423,14 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
switch (R2_GLOBALS._sceneManager._previousScene) {
case 250:
- setAction(&_sequenceManager, this, 700, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 700, &R2_GLOBALS._player, &_liftDoor, NULL);
break;
case 500:
- setAction(&_sequenceManager, this, 703, &R2_GLOBALS._player, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 703, &R2_GLOBALS._player, &_suitRoomDoor, NULL);
break;
case 600: {
_sceneMode = 4;
- _actor7.setFrame(5);
+ _loftDoor2.setFrame(5);
R2_GLOBALS._player.setPosition(Common::Point(164, 74));
R2_GLOBALS._player.setStrip2(3);
Common::Point pt(164, 69);
@@ -6113,7 +6439,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
}
break;
case 900:
- setAction(&_sequenceManager, this, 705, &R2_GLOBALS._player, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 705, &R2_GLOBALS._player, &_controlPanel, NULL);
break;
default:
if (R2_GLOBALS.getFlag(41))
@@ -6128,11 +6454,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
void Scene700::remove() {
R2_GLOBALS._sound1.play(10);
-// CHECKME: Present in the original... But it crashes badly.
-// The instruction was removed as it's not used in other scene coded the same way
-// and reversed by dreammaster. A double check is required in order to verify it doesn't hide
-// a memory leak
-// _rotation->remove();
+
SceneExt::remove();
}
@@ -6142,11 +6464,11 @@ void Scene700::signal() {
_sceneMode = 2;
R2_GLOBALS._player.setStrip(4);
if (R2_GLOBALS._player._position.x != 164) {
- SceneItem::display(700, 36, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(700, 36, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
R2_GLOBALS._player.enableControl();
} else {
R2_GLOBALS._sound2.play(19);
- _actor7.animate(ANIM_MODE_5, this);
+ _loftDoor2.animate(ANIM_MODE_5, this);
}
break;
case 2: {
@@ -6158,16 +6480,14 @@ 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;
R2_GLOBALS._player.setStrip2(-1);
R2_GLOBALS._player.setObjectWrapper(new SceneObjectWrapper());
R2_GLOBALS._sound2.play(19);
- _actor7.animate(ANIM_MODE_6, this);
+ _loftDoor2.animate(ANIM_MODE_6, this);
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS.setFlag(41);
break;
@@ -6179,7 +6499,7 @@ void Scene700::signal() {
break;
case 11:
_sceneMode = 12;
- _actor5.remove();
+ _cable.remove();
R2_GLOBALS._player.animate(ANIM_MODE_6, this);
break;
case 12:
@@ -6204,14 +6524,14 @@ void Scene700::signal() {
break;
case 16:
_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))) {
- _actor5.animate(ANIM_MODE_6, NULL);
- Common::Point pt(_actor5._position.x, _actor1._position.y + 120);
+ _cable.setup(701, 1, 8);
+ _cable.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL);
+ if (R2_GLOBALS._tractorField && (_cable._position.x == _electromagnet._position.x + 1) && (_cable._position.x == 148 - (((R2_GLOBALS._electromagnetChangeAmount + 10) / 5) * 4))) {
+ _cable.animate(ANIM_MODE_6, NULL);
+ Common::Point pt(_cable._position.x, _electromagnet._position.y + 120);
NpcMover *mover = new NpcMover();
- _actor5.addMover(mover, &pt, NULL);
- R2_GLOBALS._v565E7 = 1;
+ _cable.addMover(mover, &pt, NULL);
+ R2_GLOBALS._cableAttached = true;
}
R2_GLOBALS._player.animate(ANIM_MODE_6, this);
break;
@@ -6230,9 +6550,9 @@ void Scene700::signal() {
R2_GLOBALS._player.enableControl();
break;
case 21:
- _actor5.fixPriority(77);
- if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70))
- _actor5.animate(ANIM_MODE_6, NULL);
+ _cable.fixPriority(77);
+ if (R2_GLOBALS._tractorField && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
+ _cable.animate(ANIM_MODE_6, NULL);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700);
R2_GLOBALS._player.enableControl();
@@ -6247,10 +6567,10 @@ void Scene700::signal() {
R2_GLOBALS._sceneManager.changeScene(900);
break;
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))
- _actor5.animate(ANIM_MODE_6, NULL);
+ _cable.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL);
+ _cable.fixPriority(77);
+ if (R2_GLOBALS._tractorField && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
+ _cable.animate(ANIM_MODE_6, NULL);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_UNIT, 0);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700);
R2_GLOBALS._player.enableControl();
@@ -6277,11 +6597,11 @@ void Scene700::signal() {
*--------------------------------------------------------------------------*/
bool Scene800::Button::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
if (action != CURSOR_USE) {
return NamedHotspot::startAction(action, event);
} else {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 802;
scene->setAction(&scene->_sequenceManager1, scene, 802, &R2_GLOBALS._player, &scene->_autodocCover, NULL);
@@ -6290,11 +6610,11 @@ bool Scene800::Button::startAction(CursorType action, Event &event) {
}
bool Scene800::CableJunction::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
if (action != R2_OPTICAL_FIBRE) {
return NamedHotspot::startAction(action, event);
} else {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_opticalFibre.postInit();
scene->_sceneMode = 803;
@@ -6317,12 +6637,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;
@@ -6334,24 +6668,25 @@ bool Scene800::DeviceSlot::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
bool Scene800::Door::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 801;
scene->setAction(&scene->_sequenceManager1, scene, 801, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
}
bool Scene800::Tray::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
if (!R2_GLOBALS.getFlag(10)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 806;
@@ -6366,16 +6701,17 @@ bool Scene800::Tray::startAction(CursorType action, Event &event) {
scene->setAction(&scene->_sequenceManager1, scene, 807, &R2_GLOBALS._player, &scene->_tray, NULL);
}
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
}
bool Scene800::ComScanner::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
if (scene->_cabinet._frame == 1)
return false;
@@ -6383,6 +6719,7 @@ bool Scene800::ComScanner::startAction(CursorType action, Event &event) {
scene->_sceneMode = 811;
scene->setAction(&scene->_sequenceManager1, scene, 811, &R2_GLOBALS._player, &scene->_comScanner, NULL);
return true;
+ }
case CURSOR_TALK:
SceneItem::display2(800, 35);
return true;
@@ -6392,10 +6729,10 @@ bool Scene800::ComScanner::startAction(CursorType action, Event &event) {
}
bool Scene800::Cabinet::startAction(CursorType action, Event &event) {
- Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
-
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene800 *scene = (Scene800 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (scene->_cabinet._frame == 1) {
@@ -6408,6 +6745,7 @@ bool Scene800::Cabinet::startAction(CursorType action, Event &event) {
R2_GLOBALS.clearFlag(56);
}
return true;
+ }
default:
return SceneActor::startAction(action, event);
}
@@ -6416,8 +6754,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);
@@ -6561,21 +6899,19 @@ void Scene800::signal() {
Scene825::Button::Button(): SceneObject() {
_buttonId = 0;
- _v2 = 0;
_buttonDown = false;
}
void Scene825::Button::synchronize(Serializer &s) {
SceneObject::synchronize(s);
s.syncAsSint16LE(_buttonId);
- s.syncAsSint16LE(_v2);
s.syncAsSint16LE(_buttonDown);
}
void Scene825::Button::process(Event &event) {
- Scene825 *scene = (Scene825 *)R2_GLOBALS._sceneManager._scene;
-
if (!event.handled) {
+ Scene825 *scene = (Scene825 *)R2_GLOBALS._sceneManager._scene;
+
if ((event.eventType == EVENT_BUTTON_DOWN) && _bounds.contains(event.mousePos) && !_buttonDown) {
scene->_sound1.play(14);
setFrame(2);
@@ -6602,7 +6938,6 @@ bool Scene825::Button::startAction(CursorType action, Event &event) {
void Scene825::Button::setButton(int buttonId) {
SceneObject::postInit();
- _v2 = buttonId;
_buttonDown = 0;
_sceneText._color1 = 92;
_sceneText._color2 = 0;
@@ -6640,14 +6975,14 @@ void Scene825::Button::setButton(int buttonId) {
}
void Scene825::Button::setText(int textId) {
- Scene825 *scene = (Scene825 *)R2_GLOBALS._sceneManager._scene;
-
_buttonId = textId;
_lookLineNum = textId;
_sceneText.remove();
- if (_buttonId != 0)
+ if (_buttonId != 0) {
+ Scene825 *scene = (Scene825 *)R2_GLOBALS._sceneManager._scene;
_sceneText.setup(scene->_autodocItems[textId - 1]);
+ }
}
/*--------------------------------------------------------------------------*/
@@ -6670,18 +7005,19 @@ Scene825::Scene825(): SceneExt() {
}
void Scene825::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(825);
- R2_GLOBALS._player._uiEnabled = false;
- BF_GLOBALS._interfaceY = 200;
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._player.postInit();
- R2_GLOBALS._player._effect = 0;
+ R2_GLOBALS._player._effect = EFFECT_NONE;
R2_GLOBALS._player.setVisage(10);
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _item2.setDetails(1, 825, 3, 4, 5);
+
+ _console.setDetails(1, 825, 3, 4, 5);
_background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 825, 0, -1, -1, 1, NULL);
_sceneMode = 10;
@@ -6728,7 +7064,7 @@ void Scene825::signal() {
R2_GLOBALS._player._canWalk = false;
break;
case 825:
- _object5.remove();
+ _vertLine5.remove();
_sceneText._color1 = 92;
_sceneText._color2 = 0;
_sceneText._width = 200;
@@ -6746,7 +7082,7 @@ void Scene825::signal() {
R2_GLOBALS._player._canWalk = false;
break;
case 827:
- _object5.remove();
+ _vertLine5.remove();
R2_INVENTORY.setObjectScene(R2_OPTO_DISK, 825);
_sceneText.setPosition(Common::Point(108, 75));
_sceneText.setup(FOREIGN_OBJECT_EXTRACTED);
@@ -6774,19 +7110,19 @@ void Scene825::process(Event &event) {
}
void Scene825::dispatch() {
- if (R2_GLOBALS._sceneObjects->contains(&_object4) &&
- ((_object4._frame == 1) || (_object4._frame == 3)) &&
- (_object4._frame != _frame1)) {
+ if (R2_GLOBALS._sceneObjects->contains(&_vertLine4) &&
+ ((_vertLine4._frame == 1) || (_vertLine4._frame == 3)) &&
+ (_vertLine4._frame != _frame1)) {
_sound2.play(25);
}
- if (R2_GLOBALS._sceneObjects->contains(&_object1) &&
- (_object1._frame == 3) && (_object1._frame != _frame2)) {
+ if (R2_GLOBALS._sceneObjects->contains(&_vertLine1) &&
+ (_vertLine1._frame == 3) && (_vertLine1._frame != _frame2)) {
_sound3.play(26);
}
- _frame1 = _object4._frame;
- _frame2 = _object1._frame;
+ _frame1 = _vertLine4._frame;
+ _frame2 = _vertLine1._frame;
Scene::dispatch();
}
@@ -6803,9 +7139,9 @@ void Scene825::doButtonPress(int buttonId) {
switch (buttonId) {
case 2:
R2_GLOBALS._player.disableControl();
- _object5.postInit();
+ _vertLine5.postInit();
_sceneMode = 825;
- setAction(&_sequenceManager1, this, 825, &R2_GLOBALS._player, &_object5, NULL);
+ setAction(&_sequenceManager1, this, 825, &R2_GLOBALS._player, &_vertLine5, NULL);
break;
case 3:
R2_GLOBALS._player.disableControl();
@@ -6826,9 +7162,10 @@ void Scene825::doButtonPress(int buttonId) {
_sceneText.setup(NO_TREATMENT_REQUIRED);
} else {
_button6._buttonId = 5;
+ _sceneMode = 827;
+ _vertLine5.postInit();
- _object5.postInit();
- setAction(&_sequenceManager1, this, 827, &_object5, NULL);
+ setAction(&_sequenceManager1, this, 827, &_vertLine5, NULL);
}
} else {
R2_GLOBALS.setFlag(2);
@@ -6852,44 +7189,44 @@ void Scene825::doButtonPress(int buttonId) {
_sound4.play(27);
_button6._buttonId = 5;
- _object1.postInit();
- _object1.setup(826, 7, 1);
- _object1.setPosition(Common::Point(112, 67));
- _object1._numFrames = 1;
- _object1.animate(ANIM_MODE_2);
-
- _object2.postInit();
- _object2.setup(826, 5, 1);
- _object2.setPosition(Common::Point(158, 67));
- _object2._numFrames = 5;
- _object2.animate(ANIM_MODE_2);
-
- _object3.postInit();
- _object3.setup(826, 6, 1);
- _object3.setPosition(Common::Point(206, 67));
- _object3._numFrames = 1;
- _object3.animate(ANIM_MODE_2);
-
- _object4.postInit();
- _object4.setup(826, 8, 1);
- _object4.setPosition(Common::Point(158, 84));
- _object4._numFrames = 1;
- _object4.animate(ANIM_MODE_2);
-
- _object5.postInit();
- _object5.setup(826, 4, 1);
- _object5.setPosition(Common::Point(161, 110));
+ _vertLine1.postInit();
+ _vertLine1.setup(826, 7, 1);
+ _vertLine1.setPosition(Common::Point(112, 67));
+ _vertLine1._numFrames = 1;
+ _vertLine1.animate(ANIM_MODE_2);
+
+ _vertLine2.postInit();
+ _vertLine2.setup(826, 5, 1);
+ _vertLine2.setPosition(Common::Point(158, 67));
+ _vertLine2._numFrames = 5;
+ _vertLine2.animate(ANIM_MODE_2);
+
+ _vertLine3.postInit();
+ _vertLine3.setup(826, 6, 1);
+ _vertLine3.setPosition(Common::Point(206, 67));
+ _vertLine3._numFrames = 1;
+ _vertLine3.animate(ANIM_MODE_2);
+
+ _vertLine4.postInit();
+ _vertLine4.setup(826, 8, 1);
+ _vertLine4.setPosition(Common::Point(158, 84));
+ _vertLine4._numFrames = 1;
+ _vertLine4.animate(ANIM_MODE_2);
+
+ _vertLine5.postInit();
+ _vertLine5.setup(826, 4, 1);
+ _vertLine5.setPosition(Common::Point(161, 110));
break;
case 5:
R2_GLOBALS._player.disableControl();
if (_menuId == 4) {
_menuId = 0;
- _object1.remove();
- _object2.remove();
- _object3.remove();
- _object4.remove();
- _object5.remove();
+ _vertLine1.remove();
+ _vertLine2.remove();
+ _vertLine3.remove();
+ _vertLine4.remove();
+ _vertLine5.remove();
_sound2.stop();
_sound3.stop();
@@ -6934,11 +7271,11 @@ void Scene825::doButtonPress(int buttonId) {
*--------------------------------------------------------------------------*/
bool Scene850::Indicator::startAction(CursorType action, Event &event) {
- Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
-
if ((action != CURSOR_USE) || (R2_INVENTORY.getObjectScene(R2_OPTICAL_FIBRE) != 850))
return NamedHotspot::startAction(action, event);
else {
+ Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 851;
scene->setAction(&scene->_sequenceManager1, scene, 851, &R2_GLOBALS._player, &scene->_fibre, NULL);
@@ -6949,11 +7286,11 @@ bool Scene850::Indicator::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
bool Scene850::LiftDoor::startAction(CursorType action, Event &event) {
- Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
-
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
else {
+ Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 202;
scene->setAction(&scene->_sequenceManager1, scene, 202, &R2_GLOBALS._player, this, NULL);
@@ -6962,11 +7299,11 @@ bool Scene850::LiftDoor::startAction(CursorType action, Event &event) {
}
bool Scene850::SickBayDoor::startAction(CursorType action, Event &event) {
- Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
-
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
else {
+ Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 204;
scene->setAction(&scene->_sequenceManager1, scene, 204, &R2_GLOBALS._player, this, NULL);
@@ -6975,30 +7312,32 @@ bool Scene850::SickBayDoor::startAction(CursorType action, Event &event) {
}
bool Scene850::Clamp::startAction(CursorType action, Event &event) {
- Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
-
if (!R2_GLOBALS.getFlag(7))
return false;
else if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
else {
+ Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- scene->_object1.postInit();
+ scene->_spark.postInit();
scene->_sceneMode = 850;
- scene->setAction(&scene->_sequenceManager1, scene, 850, &R2_GLOBALS._player, this, &scene->_object1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 850, &R2_GLOBALS._player, this,
+ &scene->_spark, NULL);
return true;
}
}
bool Scene850::Panel::startAction(CursorType action, Event &event) {
- Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
-
if ((action != CURSOR_USE) || R2_GLOBALS.getFlag(7))
return SceneActor::startAction(action, event);
else {
+ Scene850 *scene = (Scene850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 852;
- scene->setAction(&scene->_sequenceManager1, scene, 852, &R2_GLOBALS._player, this, &scene->_object1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 852, &R2_GLOBALS._player,
+ this, &scene->_spark, NULL);
return true;
}
}
@@ -7006,8 +7345,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);
@@ -7084,7 +7423,7 @@ void Scene850::signal() {
case 850:
R2_INVENTORY.setObjectScene(R2_CLAMP, 1);
_clamp.remove();
- _object1.remove();
+ _spark.remove();
R2_GLOBALS._player.enableControl();
break;
case 851:
@@ -7103,85 +7442,88 @@ 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;
+ _controlsScreenNumber = 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(_controlsScreenNumber);
+ 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) {
+ if (scene->_controlsScreenNumber == 1) {
scene->_sceneMode = 2;
scene->signal();
- } else if (scene->_field412 == 2) {
- if (R2_GLOBALS._v565E5 == 0) {
+ } else if (scene->_controlsScreenNumber == 2) {
+ if (!R2_GLOBALS._tractorField) {
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)) {
- scene->_actor2.animate(ANIM_MODE_6, NULL);
+ R2_GLOBALS._tractorField = true;
+ 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->_cable._animateMode != ANIM_MODE_6)) {
+ scene->_cable.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->_cable._position.x) {
+ if (scene->_cable._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->_cable._moveDiff.y = (scene->_cable._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);
+ scene->_cable.addMover(mover, &pt, this);
+ scene->_cable.animate(ANIM_MODE_6, NULL);
}
}
}
} else {
scene->_aSound1.play(53);
setup(900, 3, 9);
- R2_GLOBALS._v565E5 = 0;
+ R2_GLOBALS._tractorField = false;
- if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (scene->_actor2._frame < 8) && (scene->_actor2._animateMode != ANIM_MODE_5)) {
- scene->_actor2.animate(ANIM_MODE_5, NULL);
- } else if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 700) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (scene->_actor2._frame < 8)) {
- R2_GLOBALS._v565E7 = 0;
- if (scene->_actor2._animateMode != 5) {
+ if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (scene->_cable._frame < 8) && (scene->_cable._animateMode != ANIM_MODE_5)) {
+ scene->_cable.animate(ANIM_MODE_5, NULL);
+ } else if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 700) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (scene->_cable._frame < 8)) {
+ R2_GLOBALS._cableAttached = false;
+ if (scene->_cable._animateMode != 5) {
R2_GLOBALS._player.disableControl();
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));
+ scene->_cable.animate(ANIM_MODE_5, NULL);
+ scene->_cable._moveDiff.y = (166 - scene->_cable._position.y) / 9;
+ Common::Point pt(scene->_cable._position.x, 166 - (R2_GLOBALS._electromagnetZoom / 15));
NpcMover *mover = new NpcMover();
- scene->_actor2.addMover(mover, &pt, this);
+ scene->_cable.addMover(mover, &pt, this);
}
}
}
@@ -7189,61 +7531,61 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
return true;
break;
case 3:
- if (scene->_field412 == 1) {
+ if (scene->_controlsScreenNumber == 1) {
scene->_sceneMode = 3;
scene->signal();
}
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;
case 8:
- SceneItem::display(5, 11, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(5, 11, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
case 9:
- SceneItem::display(5, 12, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(5, 12, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
default:
- if (scene->_field412 == 1) {
+ if (scene->_controlsScreenNumber == 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);
- } else if ((scene->_field412 == 2) || (scene->_field412 == 3)) {
+ scene->setAction(&scene->_sequenceManager1, scene, 901, &scene->_controls, this ,NULL);
+ } else if ((scene->_controlsScreenNumber == 2) || (scene->_controlsScreenNumber == 3)) {
scene->_sceneMode = 1;
scene->signal();
}
@@ -7252,10 +7594,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->_controlsScreenNumber == 2)) ? 21 : _buttonId + 11,
+ SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1, SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
return true;
} else {
return SceneActor::startAction(action, event);
@@ -7272,48 +7612,48 @@ void Scene900::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor1.setDetails(900, 3, -1, -1, 1, (SceneItem *) NULL);
+ _controls.postInit();
+ _controls.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 = EFFECT_SHADED;
+ _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();
- _actor2.setPosition(Common::Point(0, 0));
- _actor2.fixPriority(1);
+ _cable.postInit();
+ _cable.setPosition(Common::Point(0, 0));
+ _cable.fixPriority(1);
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)) {
- _actor2.setup(901, 2, 1);
+ _cable.setup(901, 3, 2);
+ } else if (R2_GLOBALS._tractorField && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) {
+ _cable.setup(901, 2, 1);
} else {
- _actor2.setup(901, 2, 8);
+ _cable.setup(901, 2, 8);
}
- _actor2.setPosition(Common::Point(171, 145));
- _actor2.setDetails(700, -1, -1, -1, 1, (SceneItem *) NULL);
+ _cable.setPosition(Common::Point(171, 145));
+ _cable.setDetails(700, -1, -1, -1, 1, (SceneItem *) NULL);
} else {
- _actor2.setDetails(700, -1, -1, -1, 1, (SceneItem *) NULL);
- if (R2_GLOBALS._v565E7 == 0) {
- _actor2.setup(901, 1, 8);
+ _cable.setDetails(700, -1, -1, -1, 1, (SceneItem *) NULL);
+ if (!R2_GLOBALS._cableAttached) {
+ _cable.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.changeZoom(((100 - ((R2_GLOBALS._v565EB * 350) / 100) + 52) / 10) * 10);
+ _cable.setPosition(Common::Point((((100 - ((CABLE700_X * 350) / 100)) * 49) / 100) + ((CABLE700_Y * _electromagnet._percent * 6) / 100) + 89, 166 - (CABLE700_X / 3)));
+ _cable.changeZoom(((100 - ((CABLE700_X * 350) / 100) + 52) / 10) * 10);
}
}
}
- _item1.setDetails(Rect(0, 0, 320, 200), 900, 0, -1, -1, 1, NULL);
+
+ _background.setDetails(Rect(0, 0, 320, 200), 900, 0, -1, -1, 1, NULL);
_sceneMode = 900;
- setAction(&_sequenceManager1, this, 900, &_actor1, NULL);
+ setAction(&_sequenceManager1, this, 900, &_controls, NULL);
}
void Scene900::remove() {
@@ -7326,87 +7666,87 @@ void Scene900::remove() {
void Scene900::signal() {
switch (_sceneMode) {
case 1:
- _field412 = 1;
+ _controlsScreenNumber = 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;
+ _controlsScreenNumber = 2;
- _actor5.remove();
- _actor6.remove();
+ _button2.remove();
+ _button3.remove();
- _actor5.sub96135(2);
- if (R2_GLOBALS._v565E5 == 0)
- _actor5.setup(900, 3, 9);
+ _button2.initButton(2);
+ if (!R2_GLOBALS._tractorField)
+ _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;
+ _controlsScreenNumber = 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;
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- R2_GLOBALS._v565E7 = 1;
+ R2_GLOBALS._cableAttached = true;
break;
case 900:
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- _actor1.setup(900, 1, 1);
+ _controls.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,45 +7765,47 @@ 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 ((_actor2._frame > 1) && (_actor2._animateMode != ANIM_MODE_6))
- _actor2.animate(ANIM_MODE_6, NULL);
+ if (R2_GLOBALS._sceneObjects->contains(&_cable)) {
+ if (R2_GLOBALS._tractorField && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) {
+ if ((_cable._frame > 1) && (_cable._animateMode != ANIM_MODE_6))
+ _cable.animate(ANIM_MODE_6, NULL);
} else {
- if ((_actor2._frame < 8) && (_actor2._animateMode != ANIM_MODE_5) && (R2_GLOBALS._v565E7 == 0) && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (_sceneMode != 4))
- _actor2.animate(ANIM_MODE_5, NULL);
+ if ((_cable._frame < 8) && (_cable._animateMode != ANIM_MODE_5) && !R2_GLOBALS._cableAttached && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (_sceneMode != 4))
+ _cable.animate(ANIM_MODE_5, NULL);
}
}
- _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.setup(901, 1, 1);
- _actor2.changeZoom(((_actor3._percent + 52) / 10) * 10);
+ if ((R2_GLOBALS._sceneObjects->contains(&_cable)) && R2_GLOBALS._cableAttached && (!_cable._mover) && (_cable._animateMode == ANIM_MODE_NONE)) {
+ _cable.setPosition(Common::Point(_electromagnet._position.x + ((_electromagnet._percent * 49) / 100), _electromagnet._position.y + ((_electromagnet._percent * 3) / 10)));
+ if (R2_GLOBALS._electromagnetZoom >= 75) {
+ _cable.setup(901, 1, 1);
+ _cable.changeZoom(((_electromagnet._percent + 52) / 10) * 10);
} else {
- _actor2.setup(901, 5, 1);
- _actor2.changeZoom(((_actor3._percent / 10) * 10) + 30);
+ _cable.setup(901, 5, 1);
+ _cable.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..0e68b67ee7 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.h
@@ -85,7 +85,7 @@ class Scene100: public SceneExt {
public:
NamedHotspot _background, _duct, _bed, _desk;
Terminal _terminal;
- SceneActor _bedLights1, _bedLights2, _object3, _object4, _object5;
+ SceneActor _bedLights1, _bedLights2, _tableLocker, _wardrobeTopAnim, _wardrobeColorAnim;
SceneActor _wardrobe;
Door _door;
Table _table;
@@ -102,16 +102,16 @@ public:
class Scene125: public SceneExt {
/* Objects */
- class Object5: public SceneActor {
+ class Food: public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
class Icon: public SceneActor {
public:
- int _lookLineNum, _field98;
+ int _lookLineNum, _iconId;
bool _pressed;
- SceneObject _object1, _object2;
+ SceneObject _glyph, _horizLine;
SceneText _sceneText1, _sceneText2;
Icon();
@@ -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,9 @@ public:
ScenePalette _palette;
ASoundExt _sound1;
NamedHotspot _background, _item2, _item3;
- Item4 _item4;
- SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _object7;
+ DiskSlot _diskSlot;
+ SceneActor _starchart1, _starchart2, _starchart3, _starchart4;
+ SceneActor _food, _foodDispenser, _infoDisk;
Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6;
SequenceManager _sequenceManager;
SceneText _sceneText;
@@ -175,7 +176,6 @@ public:
ASound _sound1;
Action1 _action1;
int _frameNumber, _yChange;
- SceneObject _object1, _object2, _object3;
int _lineNum;
SynchronizedList<SceneText *> _creditsList;
public:
@@ -197,11 +197,11 @@ class Scene180: public SceneExt {
private:
void setSceneDelay(int v);
public:
- SpeakerWebbster _webbsterSpeaker;
- SpeakerDutyOfficer _dutyOfficerSpeaker;
- SpeakerTeal _tealSpeaker;
+ SpeakerWebbster180 _webbsterSpeaker;
+ SpeakerDutyOfficer180 _dutyOfficerSpeaker;
+ SpeakerTeal180 _tealSpeaker;
SpeakerGameText _gameTextSpeaker;
- SceneActor _object1, _object2, _object3, _object4, _object5;
+ SceneActor _dutyOfficer, _teal, _webbster, _door, _shipDisplay;
ScenePalette _palette;
SceneText _textList[20];
AnimationPlayerExt _animationPlayer;
@@ -210,10 +210,9 @@ public:
ASoundExt _sound1;
int _frameNumber;
- int _field412, _field480;
- int _field482, _frameInc;
+ bool _helpEnabled;
+ int _frameInc;
int _fontNumber, _fontHeight;
- int _scene180Mode;
public:
Scene180();
@@ -263,6 +262,13 @@ public:
virtual void signal();
};
+class Star: public SceneObject {
+public:
+ int _x100, _y100;
+public:
+ virtual Common::String getClassName() { return "Scene205_Star"; }
+};
+
class Scene205: public SceneExt {
/* Actions */
class Action1: public Action {
@@ -271,28 +277,18 @@ class Scene205: public SceneExt {
public:
virtual void signal();
};
-
- /* Objects */
- class Object: public SceneObject {
- public:
- int _x100, _y100;
- public:
- Object();
-
- virtual void synchronize(Serializer &s);
- };
private:
void setup();
- void processList(Object **ObjList, int count, const Common::Rect &bounds,
+ void processList(Star **ObjList, int count, const Common::Rect &bounds,
int xMultiply, int yMultiply, int xCenter, int yCenter);
void handleText();
public:
AnimationPlayer _animationPlayer;
int _fontHeight;
SceneText _textList[15];
- Object *_objList1[3];
- Object *_objList2[3];
- Object *_objList3[4];
+ Star *_starList1[3];
+ Star *_starList2[3];
+ Star *_starList3[4];
ASound _sound1;
Action1 _action1;
int _yp;
@@ -308,11 +304,10 @@ public:
virtual void dispatch();
};
-
class Scene250: public SceneExt {
class Button: public SceneActor {
public:
- int _floorNumber, _v2;
+ int _floorNumber;
Button();
void setFloor(int floorNumber);
@@ -320,9 +315,10 @@ class Scene250: public SceneExt {
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412, _field414, _field416, _field418, _field41A;
- NamedHotspot _background, _item2, _item3, _item4;
- Button _button1, _currentFloor;
+ int _currButtonY, _destButtonY, _elevatorSpeed;
+ bool _skippingFl, _skippableFl;
+ NamedHotspot _background, _door, _directionIndicator;
+ Button _destinationFloor, _currentFloor;
Button _floor1, _floor2, _floor3, _floor4, _floor5;
Button _floor6, _floor7, _floor8, _floor9;
ASoundExt _sound1;
@@ -404,8 +400,8 @@ public:
QuinnWorkstation _quinnWorkstation1, _quinnWorkstation2;
SeekerWorkstation _seekerWorkstation;
MirandaWorkstation _mirandaWorkstation1, _mirandaWorkstation2;
- SceneActor _object1, _object2, _object3, _object4, _protocolDisplay;
- SceneActor _object6, _object7, _object8, _object9;
+ SceneActor _atmosphereLeftWindow, _atmosphereRightWindow, _leftVerticalBarsAnim, _rightVerticalBarsAnim, _protocolDisplay;
+ SceneActor _rightTextDisplay, _mirandaScreen, _leftTextDisplay, _quinnScreen;
SceneActor _teal, _soldier, _object12;
Doorway _doorway;
Miranda _miranda;
@@ -430,9 +426,9 @@ public:
class Scene325: public SceneExt {
class Icon: public SceneActor {
public:
- int _lookLineNum, _field98;
+ int _lookLineNum, _iconId;
bool _pressed;
- SceneObject _object1, _object2;
+ SceneObject _glyph, _horizLine;
SceneText _sceneText1, _sceneText2;
Icon();
@@ -452,16 +448,17 @@ private:
void setMessage(int resNum, int lineNum);
Common::String parseMessage(const Common::String &msg);
public:
- int _field412, _iconFontNumber, _field416, _field418;
- int _field41A, _field41C, _field41E, _field420;
+ int _consoleAction, _iconFontNumber, _databasePage, _priorConsoleAction;
+ int _moveCounter, _yChange, _yDirection, _scannerLocation;
int _soundCount, _soundIndex;
int _soundQueue[10];
SpeakerQuinn _quinnSpeaker;
ScenePalette _palette;
- SceneHotspot _background, _item2;
- SceneObject _object1, _object2, _object3, _object4, _object5;
- SceneObject _object6, _object7, _object8, _object9, _object10;
- SceneObject _object11, _object12, _object13;
+ SceneHotspot _background, _terminal;
+ SceneObject _starGrid1, _starGrid2, _starGrid3; // Both starchart & scan grid objects
+ SceneObject _starGrid4, _starGrid5, _starGrid6, _starGrid7;
+ SceneObject _starGrid8, _starGrid9, _starGrid10, _starGrid11;
+ SceneObject _starGrid12, _starGrid13;
SceneObject _objList[4];
Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6;
ASoundExt _sound1;
@@ -478,7 +475,6 @@ public:
virtual void dispatch();
};
-
class Scene400: public SceneExt {
/* Items */
class Terminal: public NamedHotspot {
@@ -526,6 +522,31 @@ public:
};
class Scene500: public SceneExt {
+ /* Dialogs */
+ class PanelDialog: public SceneAreaObject {
+ class Button: public SceneActor {
+ private:
+ int _buttonId;
+ bool _buttonDown;
+
+ void doButtonPress();
+ public:
+ Button();
+ virtual Common::String getClassName() { return "Scene500_Button"; }
+ virtual void process(Event &event);
+ virtual bool startAction(CursorType action, Event &event);
+ virtual void synchronize(Serializer &s);
+
+ void setupButton(int buttonId);
+ };
+ public:
+ Button _button1, _button2, _button3;
+
+ virtual Common::String getClassName() { return "Scene500_PanelWindow"; }
+ virtual void remove();
+ void setDetails(int visage, int strip, int frameNumber, const Common::Point &pt);
+ };
+
/* Items */
class ControlPanel: public SceneHotspot {
public:
@@ -533,11 +554,11 @@ class Scene500: public SceneExt {
};
/* Objects */
- class Object2: public SceneActor {
+ class Seeker: public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Object3: public SceneActor {
+ class Suit: public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -553,8 +574,9 @@ class Scene500: public SceneExt {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Object8: public SceneActor {
- // This classes uses a custom draw method
+ class TransparentDoor: public SceneActor {
+ public:
+ virtual void draw();
};
class Aerosol: public SceneActor {
public:
@@ -572,30 +594,24 @@ class Scene500: public SceneExt {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Object: public SceneActor {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
public:
int _stripNumber;
- byte _buffer[2710];
- SpeakerSeeker _seekerSpeaker;
- SpeakerQuinn _quinnSpeaker;
- SceneHotspot _background, _item2;
+ SpeakerSeeker500 _seekerSpeaker;
+ SpeakerQuinn500 _quinnSpeaker;
+ SceneHotspot _background, _airlockCorridor;
ControlPanel _controlPanel;
- SceneActor _object1;
- Object2 _object2;
- Object3 _object3;
+ SceneActor _suits;
+ Seeker _seeker;
+ Suit _suit;
Doorway _doorway;
OxygenTanks _tanks1, _tanks2;
AirLock _airLock;
- Object8 _object8;
+ TransparentDoor _transparentDoor;
Aerosol _aerosol;
SonicStunner _sonicStunner;
Locker1 _locker1;
Locker2 _locker2;
- SceneAreaObject _area1;
- Object _obj1, _obj2, _obj3;
+ PanelDialog _panelDialog;
ASoundExt _sound1;
SequenceManager _sequenceManager1, _sequenceManager2;
public:
@@ -611,61 +627,60 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
-
};
class Scene600 : public SceneExt {
- class Item1 : public NamedHotspot {
+ class CompartmentHotspot : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item4 : public NamedHotspot {
+ class EngineCompartment : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Smoke : public SceneActor {
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);
};
- class Actor8 : public SceneActor {
+ class Scanner : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412;
- Item1 _item1;
- Item1 _item2;
- Item1 _item3;
- Item4 _item4;
- Item1 _item5;
- BackgroundSceneObject _object1;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Actor4 _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
- Actor8 _actor8;
- ASoundExt _aSound1;
+ int _roomState;
+ CompartmentHotspot _quantumDrive;
+ CompartmentHotspot _quantumRegulator;
+ CompartmentHotspot _powerNode;
+ EngineCompartment _engineCompartment;
+ CompartmentHotspot _background;
+ SceneActor _stasisArea;
+ SceneActor _laserBeam;
+ SceneActor _computer;
+ SceneActor _stasisField;
+ Smoke _smoke;
+ Doorway _doorway;
+ Laser _laser;
+ Aerosol _aerosol;
+ Scanner _scanner;
+ ASoundExt _sound1;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
- byte _fieldAD2[256];
+ byte _pixelMap[256];
Scene600();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -677,60 +692,59 @@ public:
};
class Scene700: public SceneExt {
- class Item11 : public NamedHotspot {
+ class Loft : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item12 : public NamedHotspot {
+ class HandGrip : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class LiftDoor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class SuitRoomDoor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class ControlPanel : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class Cable : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class LoftDoor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- NamedHotspot _item7;
- NamedHotspot _item8;
- NamedHotspot _item9;
- NamedHotspot _item10;
- Item11 _item11;
- Item12 _item12;
- SceneActor _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor6 _actor7;
- Actor6 _actor8;
- Actor6 _actor9;
+ NamedHotspot _background;
+ NamedHotspot _debris1;
+ NamedHotspot _debris2;
+ NamedHotspot _debris3;
+ NamedHotspot _debris4;
+ NamedHotspot _restraintCollar;
+ NamedHotspot _storage2;
+ NamedHotspot _storage1;
+ NamedHotspot _stars;
+ NamedHotspot _light;
+ Loft _loft;
+ HandGrip _handGrip;
+ SceneActor _electromagnet;
+ LiftDoor _liftDoor;
+ SuitRoomDoor _suitRoomDoor;
+ ControlPanel _controlPanel;
+ Cable _cable;
+ LoftDoor _loftDoor1;
+ LoftDoor _loftDoor2;
+ LoftDoor _loftDoor3;
+ LoftDoor _loftDoor4;
SequenceManager _sequenceManager;
PaletteRotation *_rotation;
- int _field100E;
Scene700();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -792,7 +806,7 @@ class Scene825: public SceneExt {
/* Objects */
class Button: public SceneObject {
public:
- int _buttonId, _v2;
+ int _buttonId;
bool _buttonDown;
SceneText _sceneText;
public:
@@ -805,8 +819,8 @@ class Scene825: public SceneExt {
virtual bool startAction(CursorType action, Event &event);
};
public:
- NamedHotspot _background, _item2;
- SceneActor _object1, _object2, _object3, _object4, _object5;
+ NamedHotspot _background, _console;
+ SceneActor _vertLine1, _vertLine2, _vertLine3, _vertLine4, _vertLine5;
Button _button1, _button2, _button3, _button4, _button5, _button6;
ASoundExt _sound1, _sound2, _sound3, _sound4;
SequenceManager _sequenceManager1;
@@ -853,7 +867,7 @@ public:
NamedHotspot _background, _eastDoor, _compartment, _sickBayIndicator;
NamedHotspot _liftControls;
Indicator _indicator;
- SceneActor _object1, _fibre;
+ SceneActor _spark, _fibre;
LiftDoor _liftDoor;
SickBayDoor _sickBayDoor;
Clamp _clamp;
@@ -865,30 +879,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;
- NamedHotspot _item1;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Actor4 _actor4;
- Actor4 _actor5;
- Actor4 _actor6;
- Actor4 _actor7;
- Actor4 _actor8;
- Actor4 _actor9;
- Actor4 _actor10;
+ int _controlsScreenNumber;
+ Common::Point _magnetChangeAmount;
+ NamedHotspot _background;
+ SceneActor _controls;
+ SceneActor _cable;
+ 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..5ed45efbbe 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -5,7 +5,7 @@
* 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
+ * modify it under the terms of the GNU GenWeral Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
@@ -20,6 +20,8 @@
*
*/
+#include "graphics/cursorman.h"
+
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
@@ -30,14 +32,458 @@ namespace TsAGE {
namespace Ringworld2 {
/*--------------------------------------------------------------------------
+ * Scene 1000 - Cutscene scene
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene1000::Scene1000(): SceneExt() {
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ R2_GLOBALS._uiElements._active = false;
+ _gameTextSpeaker._displayMode = 9;
+ _forceCheckAnimationFl = false;
+ _animCounter = 0;
+}
+
+void Scene1000::postInit(SceneObjectList *OwnerList) {
+ loadBlankScene();
+ SceneExt::postInit();
+
+ _stripManager.addSpeaker(&_gameTextSpeaker);
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.hide();
+ R2_GLOBALS._player.disableControl();
+
+ switch (R2_GLOBALS._sceneManager._previousScene) {
+ case 300:
+ _sceneMode = R2_GLOBALS.getFlag(57) ? 40 : 0;
+ break;
+ case 1010:
+ _sceneMode = 30;
+ break;
+ case 1100:
+ _sceneMode = 10;
+ break;
+ case 1530:
+ _sceneMode = 20;
+ break;
+ case 2500:
+ _sceneMode = 100;
+ break;
+ case 2800:
+ _sceneMode = 70;
+ break;
+ case 3100:
+ if (R2_GLOBALS._player._oldCharacterScene[R2_QUINN] == 1000)
+ _sceneMode = 90;
+ else
+ _sceneMode = 80;
+ break;
+ case 3500:
+ _sceneMode = 50;
+ break;
+ case 3700:
+ _sceneMode = 60;
+ break;
+ default:
+ _sceneMode = 999;
+ break;
+ }
+
+ R2_GLOBALS._uiElements._active = false;
+ setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL);
+}
+
+void Scene1000::remove() {
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._scenePalette.setEntry(255, 0xff, 0xff, 0xff);
+ SceneExt::remove();
+}
+
+void Scene1000::signal() {
+ ScenePalette scenePalette1, scenePalette2;
+ uint32 black = 0;
+
+ switch (_sceneMode++) {
+ case 0:
+ // TODO: Determine correct colors
+ R2_GLOBALS._gfxColors.foreground = 191;
+ R2_GLOBALS._gfxColors.background = 144;
+ R2_GLOBALS._fontColors.background = 224;
+ R2_GLOBALS._fontColors.foreground = 119;
+
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer.load(5, this);
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+
+ _animationPlayer.dispatch();
+ _forceCheckAnimationFl = true;
+
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound1.play(67);
+ break;
+
+ case 1:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+
+ // TODO: Determine correct colors
+ R2_GLOBALS._gfxColors.foreground = 191;
+ R2_GLOBALS._gfxColors.background = 144;
+ R2_GLOBALS._fontColors.background = 224;
+ R2_GLOBALS._fontColors.foreground = 119;
+
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ loadScene(9999);
+
+ R2_GLOBALS._player.setup(1140, 1, 1);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 100));
+ R2_GLOBALS._player.show();
+
+ _animCounter = 0;
+ _stripManager.start(29, this);
+ break;
+
+ case 2:
+ if (R2_GLOBALS._speechSubtitles & SPEECH_TEXT)
+ setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL);
+ else {
+ if (++_animCounter < 3)
+ _sceneMode = 2;
+
+ setAction(&_sequenceManager1, this, 2, &R2_GLOBALS._player, NULL);
+ }
+ break;
+
+ case 3:
+ // TODO: Determine correct colors
+ R2_GLOBALS._gfxColors.foreground = 191;
+ R2_GLOBALS._gfxColors.background = 144;
+ R2_GLOBALS._fontColors.background = 224;
+ R2_GLOBALS._fontColors.foreground = 119;
+
+ for (int percent = 100; percent >= 0; percent -= 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(7, this);
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound2.play(81);
+ R2_GLOBALS._sound1.play(80);
+ break;
+
+ case 4:
+ // TODO: Determine correct colors
+ R2_GLOBALS._gfxColors.foreground = 191;
+ R2_GLOBALS._gfxColors.background = 144;
+ R2_GLOBALS._fontColors.background = 224;
+ R2_GLOBALS._fontColors.foreground = 119;
+
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sceneManager.changeScene(1100);
+ break;
+
+ case 10:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(6, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound1.play(55);
+ break;
+
+ case 11:
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(300);
+ break;
+
+ case 20:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(8, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 21:
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(1530);
+ break;
+
+ case 30:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(17, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound2.play(91);
+ break;
+
+ case 31:
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS.setFlag(51);
+ R2_GLOBALS._sceneManager.changeScene(300);
+ break;
+
+ case 40:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(18, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound2.play(90);
+ break;
+
+ case 41:
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(1010);
+ break;
+
+ case 50:
+ R2_GLOBALS._sound2.play(306);
+ for (int percent = 100; percent >= 0; percent -= 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(13, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 51:
+ R2_GLOBALS._sound2.stop();
+ R2_GLOBALS._sound2.play(307);
+ R2_GLOBALS._sound1.play(308);
+
+ for (int percent = 100; percent >= 0; percent -= 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(14, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 52:
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(3350);
+ break;
+
+ case 60:
+ R2_GLOBALS._sound1.play(333);
+
+ for (int percent = 100; percent >= 0; percent -= 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(12, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 61:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(160);
+ break;
+
+ case 70:
+ R2_GLOBALS._sound2.play(113);
+ for (int percent = 100; percent >= 0; percent -= 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(9, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 71:
+ case 81:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(3100);
+ break;
+
+ case 80:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(10, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound1.play(242);
+ R2_GLOBALS._sound2.play(286);
+ break;
+
+ case 90:
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(11, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+
+ R2_GLOBALS._sound1.play(277);
+ break;
+
+ case 91:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._player._characterIndex = R2_SEEKER;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 3100;
+ R2_GLOBALS._sceneManager.changeScene(2500);
+ break;
+
+ case 100:
+ R2_GLOBALS._sound1.play(304);
+ R2_GLOBALS._sound2.play(82);
+
+ _animationPlayer._paletteMode = ANIMPALMODE_NONE;
+ _animationPlayer._objectMode = ANIMOBJMODE_2;
+ _animationPlayer.load(19, this);
+
+ R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256);
+ R2_GLOBALS._sceneManager._hasPalette = false;
+ _animationPlayer.dispatch();
+
+ _forceCheckAnimationFl = true;
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0);
+ for (int percent = 0; percent < 100; percent += 5)
+ R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent);
+ break;
+
+ case 101:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._sceneManager.changeScene(3500);
+ break;
+ }
+}
+
+void Scene1000::dispatch() {
+ if (_forceCheckAnimationFl) {
+ if (_animationPlayer.isCompleted()) {
+ _forceCheckAnimationFl = false;
+ _animationPlayer.close();
+ _animationPlayer.remove();
+
+ if (_sceneMode == 52)
+ _animationPlayer._endAction = this;
+ } else
+ _animationPlayer.dispatch();
+ }
+
+ Scene::dispatch();
+}
+
+
+/*--------------------------------------------------------------------------
* Scene 1010 - Cutscene: A pixel lost in space!
*
*--------------------------------------------------------------------------*/
+
void Scene1010::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(1010);
-
R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
setZoomPercents(100, 1, 160, 100);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setObjectWrapper(NULL);
@@ -89,18 +535,19 @@ void Scene1010::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1020 -
+ * Scene 1020 - Cutscene - trip in space 2
*
*--------------------------------------------------------------------------*/
+
void Scene1020::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(1020);
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
if (R2_GLOBALS._sceneManager._previousScene == 1010)
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
+ _sceneBounds = Rect(160, 0, SCREEN_WIDTH + 160, 200);
- R2_GLOBALS._v558B6.set(160, 0, 160, 161);
- R2_GLOBALS._uiElements._active = false;
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._player.postInit();
if (R2_GLOBALS._sceneManager._previousScene == 1010) {
@@ -214,47 +661,50 @@ void Scene1020::dispatch() {
}
/*--------------------------------------------------------------------------
- * Scene 1100 -
+ * Scene 1100 - Canyon
*
*--------------------------------------------------------------------------*/
+
Scene1100::Scene1100() {
- _field412 = 0;
- _field414 = 0;
+ _nextStripNum = 0;
+ _paletteRefreshStatus = 0;
}
void Scene1100::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
+ s.syncAsSint16LE(_nextStripNum);
+ s.syncAsSint16LE(_paletteRefreshStatus);
}
-bool Scene1100::Actor16::startAction(CursorType action, Event &event) {
- Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1100::Seeker::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
+
if (R2_GLOBALS.getFlag(52)) {
+ // The trouper is dead
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._characterIndex == 1)
- scene->_field412 = 327;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ scene->_nextStripNum = 327;
else
- scene->_field412 = 328;
+ scene->_nextStripNum = 328;
scene->_sceneMode = 53;
scene->setAction(&scene->_sequenceManager1, scene, 1122, &R2_GLOBALS._player, NULL);
} else {
+ // The trouper is not dead
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 55;
- if (R2_GLOBALS._v565AE >= 3) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._stripModifier >= 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_stripManager.start3(329, scene, R2_GLOBALS._stripManager_lookupList);
else
scene->_stripManager.start3(330, scene, R2_GLOBALS._stripManager_lookupList);
} else {
- ++R2_GLOBALS._v565AE;
+ ++R2_GLOBALS._stripModifier;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_stripManager.start3(304, scene, R2_GLOBALS._stripManager_lookupList);
else
scene->_stripManager.start3(308, scene, R2_GLOBALS._stripManager_lookupList);
@@ -263,45 +713,45 @@ bool Scene1100::Actor16::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1100::Actor17::startAction(CursorType action, Event &event) {
+bool Scene1100::Trooper::startAction(CursorType action, Event &event) {
Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case R2_NEGATOR_GUN:
if (_visage == 1105) {
+ // Trooper wears the stasis shield
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1114;
- scene->setAction(&scene->_sequenceManager1, scene, 1114, &R2_GLOBALS._player, &scene->_actor17, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1114, &R2_GLOBALS._player, &scene->_trooper, NULL);
return true;
- } else {
+ } else
return SceneActor::startAction(action, event);
- }
break;
case R2_SONIC_STUNNER:
// No break on purpose
case R2_PHOTON_STUNNER:
if (_visage == 1105) {
+ // If trooper wears the stasis shield
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
scene->_sceneMode = 1112;
- scene->setAction(&scene->_sequenceManager1, scene, 1112, &R2_GLOBALS._player, &scene->_actor17, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1112, &R2_GLOBALS._player, &scene->_trooper, NULL);
} else {
scene->_sceneMode = 1115;
- scene->setAction(&scene->_sequenceManager1, scene, 1115, &R2_GLOBALS._player, &scene->_actor17, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1115, &R2_GLOBALS._player, &scene->_trooper, NULL);
}
return true;
} else if (_strip == 2) {
+ // Trooper wears his black uniform
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1113;
- if (R2_GLOBALS._player._characterIndex == 1) {
- scene->setAction(&scene->_sequenceManager1, scene, 1113, &R2_GLOBALS._player, &scene->_actor17, NULL);
- } else {
- scene->setAction(&scene->_sequenceManager1, scene, 1118, &R2_GLOBALS._player, &scene->_actor17, NULL);
- }
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ scene->setAction(&scene->_sequenceManager1, scene, 1113, &R2_GLOBALS._player, &scene->_trooper, NULL);
+ else
+ scene->setAction(&scene->_sequenceManager1, scene, 1118, &R2_GLOBALS._player, &scene->_trooper, NULL);
return true;
- } else {
+ } else
return SceneActor::startAction(action, event);
- }
break;
default:
return SceneActor::startAction(action, event);
@@ -309,11 +759,13 @@ bool Scene1100::Actor17::startAction(CursorType action, Event &event) {
}
}
-bool Scene1100::Actor18::startAction(CursorType action, Event &event) {
- Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1100::Chief::startAction(CursorType action, Event &event) {
+ // CHECKME: Flag 54 is never set. Guess: the flag means "Chief is dead"
if ((action == CURSOR_TALK) && (!R2_GLOBALS.getFlag(54)) && (R2_GLOBALS.getFlag(52))) {
- scene->_field412 = 0;
+ // Talk to chief after the trooper dies
+ Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_nextStripNum = 0;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 53;
scene->setAction(&scene->_sequenceManager1, scene, 1122, &R2_GLOBALS._player, NULL);
@@ -329,20 +781,14 @@ void Scene1100::postInit(SceneObjectList *OwnerList) {
else
loadScene(1100);
- if ((R2_GLOBALS._sceneManager._previousScene == 1000) && (!R2_GLOBALS.getFlag(44))) {
+ if ((R2_GLOBALS._sceneManager._previousScene == 1000) && (!R2_GLOBALS.getFlag(44)))
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E.left = 0;
- R2_GLOBALS._v5589E.right = 200;
- }
- if (R2_GLOBALS._player._characterScene[1] == 1100)
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == 1100)
R2_GLOBALS._sceneManager._previousScene = 1100;
- if (R2_GLOBALS._sceneManager._previousScene == -1) {
+ if (R2_GLOBALS._sceneManager._previousScene == -1)
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E.left = 0;
- R2_GLOBALS._v5589E.right = 200;
- }
SceneExt::postInit();
@@ -357,71 +803,72 @@ void Scene1100::postInit(SceneObjectList *OwnerList) {
scalePalette(65, 65, 65);
- _actor2.postInit();
- _actor2.setup(1100, 1, 1);
- _actor2.fixPriority(10);
+ _cloud.postInit();
+ _cloud.setup(1100, 1, 1);
+ _cloud.fixPriority(10);
R2_GLOBALS._scrollFollower = NULL;
- _item3.setDetails(Rect(56, 47, 68, 83), 1100, 7, -1, -1, 1, NULL);
- _item4.setDetails(Rect(167, 132, 183, 167), 1100, 7, -1, -1, 1, NULL);
- _item5.setDetails(Rect(26, 112, 87, 145), 1100, 13, -1, -1, 1, NULL);
- _item7.setDetails(Rect(4, 70, 79, 167), 1100, 16, -1, -1, 1, NULL);
+ _fuana1.setDetails(Rect(56, 47, 68, 83), 1100, 7, -1, -1, 1, NULL);
+ _fauna2.setDetails(Rect(167, 132, 183, 167), 1100, 7, -1, -1, 1, NULL);
+ _bouldersBlockingCave.setDetails(Rect(26, 112, 87, 145), 1100, 13, -1, -1, 1, NULL);
+ _trail.setDetails(Rect(4, 70, 79, 167), 1100, 16, -1, -1, 1, NULL);
R2_GLOBALS._sound1.stop();
if (R2_GLOBALS._sceneManager._previousScene == 300) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
R2_GLOBALS._player._characterIndex = R2_QUINN;
- R2_GLOBALS._player._characterScene[1] = 1100;
- R2_GLOBALS._player._characterScene[2] = 1100;
- _actor2.setPosition(Common::Point(150, 30));
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1100;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1100;
+ _cloud.setPosition(Common::Point(150, 30));
R2_GLOBALS._sound1.play(93);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor16.postInit();
- _actor16.hide();
- if (R2_GLOBALS._player._characterIndex == 1)
- _actor16.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
+ _seeker.postInit();
+ _seeker.hide();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _seeker.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
else
- _actor16.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
+ _seeker.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
- _actor18.postInit();
- _actor18.setup(1113, 3, 1);
- _actor18.setPosition(Common::Point(181, 125));
- _actor18.fixPriority(110);
+ _chief.postInit();
+ _chief.setup(1113, 3, 1);
+ _chief.setPosition(Common::Point(181, 125));
+ _chief.fixPriority(110);
if (R2_GLOBALS.getFlag(54))
- _actor18.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL);
+ _chief.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL);
else
- _actor18.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL);
-
- _actor17.postInit();
- _actor17.setup(1105, 3, 1);
- _actor17.setPosition(Common::Point(312, 165));
- _actor17._numFrames = 5;
- _actor17.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1512, 1, 1);
- _actor1.setPosition(Common::Point(187, -25));
- _actor1.fixPriority(48);
- _actor1._moveDiff.y = 1;
- _actor1.setDetails(1100, 37, -1, -1, 1, (SceneItem *) NULL);
+ _chief.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL);
+
+ _trooper.postInit();
+ // Trooper wears his stasis shield
+ _trooper.setup(1105, 3, 1);
+ _trooper.setPosition(Common::Point(312, 165));
+ _trooper._numFrames = 5;
+ _trooper.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL);
+
+ _ship.postInit();
+ _ship.setup(1512, 1, 1);
+ _ship.setPosition(Common::Point(187, -25));
+ _ship.fixPriority(48);
+ _ship._moveDiff.y = 1;
+ _ship.setDetails(1100, 37, -1, -1, 1, (SceneItem *) NULL);
_sceneMode = 20;
setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL);
} else if (R2_GLOBALS._sceneManager._previousScene == 1000) {
- _actor2.setPosition(Common::Point(50, 30));
- _field414 = 0;
+ _cloud.setPosition(Common::Point(50, 30));
+ _paletteRefreshStatus = 0;
_palette1.loadPalette(1101);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._player._effect = 5;
- R2_GLOBALS._player._field9C = _field312;
+ R2_GLOBALS._player._effect = EFFECT_SHADOW_MAP;
+ R2_GLOBALS._player._shadowMap = _shadowPaletteMap;
R2_GLOBALS._player.setup(1102, 3, 2);
R2_GLOBALS._player.setObjectWrapper(NULL);
R2_GLOBALS._player.setPosition(Common::Point(111,-20));
@@ -429,25 +876,25 @@ void Scene1100::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveRate = 30;
R2_GLOBALS._player._moveDiff = Common::Point(16, 2);
- _object1.setup2(1104, 2, 1, 175, 125, 102, 1);
- _object2.setup2(1102, 5, 1, 216, 167, 1, 0);
+ _rightLandslide.setup2(1104, 2, 1, 175, 125, 102, 1);
+ _purplePlant.setup2(1102, 5, 1, 216, 167, 1, 0);
- _actor12.postInit();
- _actor12.setup(1113, 2, 1);
- _actor12.setPosition(Common::Point(67, 151));
- _actor12.fixPriority(255);
+ _leftImpacts.postInit();
+ _leftImpacts.setup(1113, 2, 1);
+ _leftImpacts.setPosition(Common::Point(67, 151));
+ _leftImpacts.fixPriority(255);
- _actor3.postInit();
- _actor3.setup(1102, 6, 1);
- _actor3._moveRate = 30;
- _actor3._moveDiff.x = 2;
+ _shipFormation.postInit();
+ _shipFormation.setup(1102, 6, 1);
+ _shipFormation._moveRate = 30;
+ _shipFormation._moveDiff.x = 2;
- _actor4.postInit();
- _actor4.setup(1102, 6, 2);
- _actor4._moveRate = 30;
- _actor4._moveDiff.x = 2;
- _actor4._effect = 5;
- _actor4._field9C = _field312;
+ _shipFormationShadow.postInit();
+ _shipFormationShadow.setup(1102, 6, 2);
+ _shipFormationShadow._moveRate = 30;
+ _shipFormationShadow._moveDiff.x = 2;
+ _shipFormationShadow._effect = EFFECT_SHADOW_MAP;
+ _shipFormationShadow._shadowMap = _shadowPaletteMap;
R2_GLOBALS._sound1.play(86);
@@ -455,86 +902,95 @@ void Scene1100::postInit(SceneObjectList *OwnerList) {
setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL);
} else {
- _actor2.setPosition(Common::Point(180, 30));
+ _cloud.setPosition(Common::Point(180, 30));
if (R2_GLOBALS.getFlag(52))
+ // Trooper is dead
R2_GLOBALS._sound1.play(98);
else
+ // Trooper is alive
R2_GLOBALS._sound1.play(95);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- _actor16.postInit();
+ _seeker.postInit();
if (R2_GLOBALS.getFlag(52)) {
- if (R2_GLOBALS._player._characterIndex == 1) {
+ // Trooper is dead
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(19, 7, 1);
- _actor16.setup(29, 6, 1);
+ _seeker.setup(29, 6, 1);
} else {
R2_GLOBALS._player.setup(29, 7, 1);
- _actor16.setup(19, 6, 1);
+ _seeker.setup(19, 6, 1);
}
R2_GLOBALS._player.setPosition(Common::Point(140, 124));
- _actor16.setPosition(Common::Point(237, 134));
+ _seeker.setPosition(Common::Point(237, 134));
R2_GLOBALS._player.enableControl();
} else {
- if (R2_GLOBALS._player._characterIndex == 1) {
+ // Trooper is alive
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(1107, 2, 1);
- _actor16.setup(1107, 4, 1);
+ _seeker.setup(1107, 4, 1);
R2_GLOBALS._player.setPosition(Common::Point(247, 169));
- _actor16.setPosition(Common::Point(213, 169));
+ _seeker.setPosition(Common::Point(213, 169));
} else {
R2_GLOBALS._player.setup(1107, 4, 1);
- _actor16.setup(1107, 2, 1);
+ _seeker.setup(1107, 2, 1);
R2_GLOBALS._player.setPosition(Common::Point(213, 169));
- _actor16.setPosition(Common::Point(247, 169));
+ _seeker.setPosition(Common::Point(247, 169));
}
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
}
- if (R2_GLOBALS._player._characterIndex == 1)
- _actor16.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _seeker.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
else
- _actor16.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
+ _seeker.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
- _actor18.postInit();
- _actor18.setup(1113, 3, 1);
- _actor18.setPosition(Common::Point(181, 125));
- _actor18.fixPriority(110);
+ _chief.postInit();
+ _chief.setup(1113, 3, 1);
+ _chief.setPosition(Common::Point(181, 125));
+ _chief.fixPriority(110);
if (R2_GLOBALS.getFlag(54))
- _actor18.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL);
+ _chief.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL);
else
- _actor18.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL);
+ _chief.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL);
if (!R2_GLOBALS.getFlag(52)) {
- _actor17.postInit();
+ // If trooper is alive, initialize him
+ _trooper.postInit();
if (R2_GLOBALS.getFlag(53))
- _actor17.setup(1106, 2, 4);
+ // Trooper wears his black uniform
+ _trooper.setup(1106, 2, 4);
else
- _actor17.setup(1105, 4, 4);
+ // Trooper wears a stasis shield
+ _trooper.setup(1105, 4, 4);
- _actor17.setPosition(Common::Point(17, 54));
- _actor17._numFrames = 5;
+ _trooper.setPosition(Common::Point(17, 54));
+ _trooper._numFrames = 5;
if (R2_GLOBALS.getFlag(53))
- _actor17.setDetails(1100, 28, -1, -1, 1, (SceneItem *) NULL);
+ // Trooper isn't wearing the stasis shield
+ _trooper.setDetails(1100, 28, -1, -1, 1, (SceneItem *) NULL);
else
- _actor17.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL);
+ _trooper.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL);
- _actor17.fixPriority(200);
+ _trooper.fixPriority(200);
}
- _actor1.postInit();
- _actor1.setup(1512, 1, 1);
- _actor1.setPosition(Common::Point(187, 45));
- _actor1.fixPriority(48);
- _actor1._moveDiff.y = 1;
- _actor1.setDetails(1100, 37, -1, -1, 1, (SceneItem *) NULL);
+ _ship.postInit();
+ _ship.setup(1512, 1, 1);
+ _ship.setPosition(Common::Point(187, 45));
+ _ship.fixPriority(48);
+ _ship._moveDiff.y = 1;
+ _ship.setDetails(1100, 37, -1, -1, 1, (SceneItem *) NULL);
}
- _item6.setDetails(Rect(123, 69, 222, 105), 1100, 13, -1, -1, 1, NULL);
- _item2.setDetails(Rect(0, 0, 480, 46), 1100, 0, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 480, 200), 1100, 40, 41, 42, 1, NULL);
+
+ _boulders.setDetails(Rect(123, 69, 222, 105), 1100, 13, -1, -1, 1, NULL);
+ _sky.setDetails(Rect(0, 0, 480, 46), 1100, 0, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 480, 200), 1100, 40, 41, 42, 1, NULL);
}
void Scene1100::remove() {
@@ -549,30 +1005,30 @@ void Scene1100::remove() {
void Scene1100::signal() {
switch (_sceneMode++) {
case 0:
- _actor3.setPosition(Common::Point(350, 20));
+ _shipFormation.setPosition(Common::Point(350, 20));
setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL);
break;
case 1:{
Common::Point pt(-150, 20);
NpcMover *mover = new NpcMover();
- _actor3.addMover(mover, &pt, this);
- _actor4.setPosition(Common::Point(350, 55));
+ _shipFormation.addMover(mover, &pt, this);
+ _shipFormationShadow.setPosition(Common::Point(350, 55));
Common::Point pt2(-150, 55);
NpcMover *mover2 = new NpcMover();
- _actor4.addMover(mover2, &pt2, NULL);
+ _shipFormationShadow.addMover(mover2, &pt2, NULL);
}
break;
case 2:
- _actor3.remove();
- _actor4.remove();
- _actor5.postInit();
- _actor6.postInit();
- _actor7.postInit();
- _actor8.postInit();
- _actor9.postInit();
- _actor10.postInit();
- setAction(&_sequenceManager1, this, 1102, &_actor5, &_actor6, &_actor7, &_actor8, &_actor9, &_actor10, NULL);
+ _shipFormation.remove();
+ _shipFormationShadow.remove();
+ _shotImpact1.postInit();
+ _shotImpact2.postInit();
+ _shotImpact3.postInit();
+ _shotImpact4.postInit();
+ _shotImpact5.postInit();
+ _laserShot.postInit();
+ setAction(&_sequenceManager1, this, 1102, &_shotImpact1, &_shotImpact2, &_shotImpact3, &_shotImpact4, &_shotImpact5, &_laserShot, NULL);
break;
case 3: {
R2_GLOBALS._sound2.play(84);
@@ -583,26 +1039,26 @@ void Scene1100::signal() {
}
break;
case 4:
- _actor18.postInit();
- _actor18.show();
- setAction(&_sequenceManager1, this, 1101, &_actor18, &_actor10, NULL);
+ _chief.postInit();
+ _chief.show();
+ setAction(&_sequenceManager1, this, 1101, &_chief, &_laserShot, NULL);
break;
case 5:
- _actor13.postInit();
- _actor13._effect = 6;
- _actor13.setup(1103, 3, 1);
- _actor13._moveRate = 30;
+ _runningGuy1.postInit();
+ _runningGuy1._effect = EFFECT_SHADED2;
+ _runningGuy1.setup(1103, 3, 1);
+ _runningGuy1._moveRate = 30;
- _actor14.postInit();
- _actor14._effect = 6;
- _actor14.setup(1103, 4, 1);
- _actor4._moveRate = 25;
+ _runningGuy2.postInit();
+ _runningGuy2._effect = EFFECT_SHADED2;
+ _runningGuy2.setup(1103, 4, 1);
+ _runningGuy2._moveRate = 25;
- _actor13.setAction(&_sequenceManager2, this, 1109, &_actor13, &_actor14, NULL);
+ _runningGuy1.setAction(&_sequenceManager2, this, 1109, &_runningGuy1, &_runningGuy2, NULL);
break;
case 6: {
- _actor13.remove();
- _actor14.remove();
+ _runningGuy1.remove();
+ _runningGuy2.remove();
R2_GLOBALS._player.setPosition(Common::Point(-50, 136));
R2_GLOBALS._sound2.play(84);
Common::Point pt(350, 236);
@@ -611,30 +1067,31 @@ void Scene1100::signal() {
}
break;
case 7:
- setAction(&_sequenceManager1, this, 1103, &_actor18, &_actor10);
+ setAction(&_sequenceManager1, this, 1103, &_chief, &_laserShot, NULL);
break;
case 8:
- R2_GLOBALS._player._effect = 0;
- _actor11.postInit();
- setAction(&_sequenceManager1, this, 1105, &R2_GLOBALS._player, &_actor10, &_actor11, &_actor18, NULL);
+ R2_GLOBALS._player._effect = EFFECT_NONE;
+ _animation.postInit();
+ setAction(&_sequenceManager1, this, 1105, &R2_GLOBALS._player, &_laserShot, &_animation, &_chief, NULL);
break;
case 9:
- _object1.proc27();
+ _rightLandslide.copySceneToBackground();
- _actor15.postInit();
- _actor15.setup(1103, 2, 1);
- _actor15._moveRate = 30;
- _actor15.setAction(&_sequenceManager3, this, 1107, &_actor15, NULL);
+ _runningGuy3.postInit();
+ _runningGuy3.setup(1103, 2, 1);
+ _runningGuy3._moveRate = 30;
+ _runningGuy3.setAction(&_sequenceManager3, this, 1107, &_runningGuy3, NULL);
break;
case 10:
- _actor13.postInit();
- _actor13.setup(1103, 1, 1);
- _actor13._moveRate = 15;
- _actor13.setAction(&_sequenceManager2, this, 1108, &_actor13, NULL);
+ _runningGuy1.postInit();
+ _runningGuy1.setup(1103, 1, 1);
+ _runningGuy1._moveRate = 15;
+ _runningGuy1.setAction(&_sequenceManager2, this, 1108, &_runningGuy1, NULL);
break;
case 11: {
- setAction(&_sequenceManager1, this, 1116, &_actor11, &_actor10, &_actor12, NULL);
- R2_GLOBALS._player._effect = 5;
+ setAction(&_sequenceManager1, this, 1106, &_animation, &_laserShot, &_leftImpacts, NULL);
+
+ R2_GLOBALS._player._effect = EFFECT_SHADOW_MAP;
R2_GLOBALS._player.setup(1102, 3, 2);
R2_GLOBALS._player.setPosition(Common::Point(-50, 131));
R2_GLOBALS._sound2.play(84);
@@ -647,19 +1104,19 @@ void Scene1100::signal() {
// Really nothing
break;
case 13:
- _actor17.postInit();
- R2_GLOBALS._scrollFollower = &_actor17;
+ _trooper.postInit();
+ R2_GLOBALS._scrollFollower = &_trooper;
- _actor11.setup(1100, 2, 1);
- _actor11.setPosition(Common::Point(408, 121));
+ _animation.setup(1100, 2, 1);
+ _animation.setPosition(Common::Point(408, 121));
- _actor10.setup(1100, 3, 5);
- _actor10.setPosition(Common::Point(409, 121));
+ _laserShot.setup(1100, 3, 5);
+ _laserShot.setPosition(Common::Point(409, 121));
- setAction(&_sequenceManager1, this, 1104, &_actor17, NULL);
+ setAction(&_sequenceManager1, this, 1104, &_trooper, NULL);
break;
case 14:
- setAction(&_sequenceManager1, this, 1100, &_actor11, &_actor10, NULL);
+ setAction(&_sequenceManager1, this, 1100, &_animation, &_laserShot, NULL);
break;
case 15:
R2_GLOBALS._sceneManager.changeScene(1000);
@@ -667,19 +1124,19 @@ void Scene1100::signal() {
case 20: {
Common::Point pt(187, -13);
NpcMover *mover = new NpcMover();
- _actor1.addMover(mover, &pt, this);
+ _ship.addMover(mover, &pt, this);
}
break;
case 21: {
R2_GLOBALS._sound2.play(92);
- _actor17.animate(ANIM_MODE_5, NULL);
+ _trooper.animate(ANIM_MODE_5, NULL);
Common::Point pt(187, 45);
NpcMover *mover = new NpcMover();
- _actor1.addMover(mover, &pt, this);
+ _ship.addMover(mover, &pt, this);
}
break;
case 22:
- setAction(&_sequenceManager1, this, 1110, &_actor16, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager1, this, 1110, &_seeker, &R2_GLOBALS._player, NULL);
break;
case 23:
R2_GLOBALS._player.disableControl();
@@ -693,74 +1150,79 @@ void Scene1100::signal() {
break;
case 25:
R2_GLOBALS._player.disableControl();
- _stripManager._lookupList[9] = 1;
- _stripManager._lookupList[10] = 1;
- _stripManager._lookupList[11] = 1;
+ R2_GLOBALS._stripManager_lookupList[9] = 1;
+ R2_GLOBALS._stripManager_lookupList[10] = 1;
+ R2_GLOBALS._stripManager_lookupList[11] = 1;
R2_GLOBALS._sound1.play(95);
- setAction(&_sequenceManager1, this, 1111, &_actor17, &R2_GLOBALS._player, &_actor16, NULL);
+ setAction(&_sequenceManager1, this, 1111, &_trooper, &R2_GLOBALS._player, &_seeker, NULL);
break;
case 26:
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_stripManager.start(302, this);
break;
case 27:
R2_GLOBALS._player.disableControl();
- setAction(&_sequenceManager1, this, 1120, &_actor16, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager1, this, 1120, &_seeker, &R2_GLOBALS._player, NULL);
break;
case 28:
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_stripManager.start(303, this);
break;
+ case 29:
+ case 50:
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
+ break;
case 51:
+ // Trooper no longer wears a statis shield
R2_GLOBALS.setFlag(53);
- _actor17.setDetails(1100, 28, -1, -1, 3, (SceneItem *) NULL);
- // No break on purpose
- case 50:
- // No break on purpose
- case 29:
+ _trooper.setDetails(1100, 28, -1, -1, 3, (SceneItem *) NULL);
+
R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
break;
case 52:
+ // Trooper is shot to death
R2_GLOBALS._sound1.play(98);
R2_GLOBALS.setFlag(52);
R2_GLOBALS._player.disableControl();
_sceneMode = 1116;
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
setAction(&_sequenceManager1, this, 1116, &R2_GLOBALS._player, NULL);
- _actor16.setAction(&_sequenceManager2, NULL, 1123, &_actor16, NULL);
+ _seeker.setAction(&_sequenceManager2, NULL, 1123, &_seeker, NULL);
} else {
setAction(&_sequenceManager1, this, 1124, &R2_GLOBALS._player, NULL);
- _actor16.setAction(&_sequenceManager2, NULL, 1117, &_actor16, NULL);
+ _seeker.setAction(&_sequenceManager2, NULL, 1117, &_seeker, NULL);
}
break;
case 53:
_sceneMode = 54;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (_field412 == 0) {
+ if (_nextStripNum == 0) {
R2_GLOBALS.setFlag(55);
if (R2_GLOBALS.getFlag(55)) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_stripManager.start(318, this);
else
_stripManager.start(323, this);
} else {
// This part is totally useless as flag 55 has been set right before the check
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_stripManager.start(317, this);
else
_stripManager.start(322, this);
}
- } else {
- _stripManager.start3(_field412, this, _stripManager._lookupList);
- }
+ } else
+ _stripManager.start3(_nextStripNum, this, _stripManager._lookupList);
+
break;
case 54:
- if (_stripManager._field2E8 == 1) {
+ if (_stripManager._exitMode == 1) {
R2_GLOBALS._player.disableControl();
_sceneMode = 1125;
- setAction(&_sequenceManager1, this, 1125, &R2_GLOBALS._player, &_actor16, NULL);
+ setAction(&_sequenceManager1, this, 1125, &R2_GLOBALS._player, &_seeker, NULL);
} else
R2_GLOBALS._player.enableControl(CURSOR_TALK);
break;
@@ -769,8 +1231,8 @@ void Scene1100::signal() {
R2_GLOBALS._player._canWalk = false;
break;
case 99:
- R2_GLOBALS._player._characterScene[1] = 300;
- R2_GLOBALS._player._characterScene[2] = 300;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 300;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 300;
R2_GLOBALS._player._characterIndex = R2_QUINN;
R2_GLOBALS._sceneManager.changeScene(300);
break;
@@ -800,10 +1262,10 @@ void Scene1100::signal() {
_stripManager.start3(314, this, _stripManager._lookupList);
break;
case 1116:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- _stripManager._lookupList[9] = 1;
- _stripManager._lookupList[10] = 1;
- _stripManager._lookupList[11] = 1;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ R2_GLOBALS._stripManager_lookupList[9] = 1;
+ R2_GLOBALS._stripManager_lookupList[10] = 1;
+ R2_GLOBALS._stripManager_lookupList[11] = 1;
break;
case 1125: {
_sceneMode = 99;
@@ -811,7 +1273,7 @@ void Scene1100::signal() {
R2_GLOBALS._sound1.play(101);
Common::Point pt(187, -13);
NpcMover *mover = new NpcMover();
- _actor1.addMover(mover, &pt, this);
+ _ship.addMover(mover, &pt, this);
}
break;
default:
@@ -822,76 +1284,79 @@ void Scene1100::signal() {
}
void Scene1100::dispatch() {
- if ((g_globals->_sceneObjects->contains(&_actor10)) && (_actor10._visage == 1102) && (_actor10._strip == 4) && (_actor10._frame == 1) && (_actor10._flags & OBJFLAG_HIDING)) {
- if (_field414 == 1) {
- _field414 = 2;
+ // WORKAROUND: This fixes a problem with an overhang that gets blasted re-appearing
+ if (_animation._frame > 5 && _sceneMode == 13) {
+ _animation._endFrame = 9;
+ if (_animation._frame == 9)
+ // Use one of the scene's background scene objects to copy the scene to the background.
+ // This fixes the problem with the cliff overhang still appearing during the cutscene
+ _rightLandslide.copySceneToBackground();
+ }
+
+ if ((g_globals->_sceneObjects->contains(&_laserShot)) && (_laserShot._visage == 1102) && (_laserShot._strip == 4) && (_laserShot._frame == 1) && (_laserShot._flags & OBJFLAG_HIDING)) {
+ if (_paletteRefreshStatus == 1) {
+ _paletteRefreshStatus = 2;
R2_GLOBALS._scenePalette.refresh();
}
} else {
- if (_field414 == 2)
+ if (_paletteRefreshStatus == 2)
R2_GLOBALS._scenePalette.refresh();
- _field414 = 1;
+ _paletteRefreshStatus = 1;
}
Scene::dispatch();
- if (R2_GLOBALS._player._bounds.contains(_actor13._position))
- _actor13._shade = 3;
+ if (R2_GLOBALS._player._bounds.contains(_runningGuy1._position))
+ _runningGuy1._shade = 3;
else
- _actor13._shade = 0;
+ _runningGuy1._shade = 0;
- if (R2_GLOBALS._player._bounds.contains(_actor14._position))
- _actor14._shade = 3;
+ if (R2_GLOBALS._player._bounds.contains(_runningGuy2._position))
+ _runningGuy2._shade = 3;
else
- _actor14._shade = 0;
+ _runningGuy2._shade = 0;
- if (R2_GLOBALS._player._bounds.contains(_actor15._position))
- _actor15._shade = 3;
+ if (R2_GLOBALS._player._bounds.contains(_runningGuy3._position))
+ _runningGuy3._shade = 3;
else
- _actor15._shade = 0;
+ _runningGuy3._shade = 0;
}
void Scene1100::saveCharacter(int characterIndex) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
R2_GLOBALS._sound1.fadeOut2(NULL);
SceneExt::saveCharacter(characterIndex);
}
/*--------------------------------------------------------------------------
- * Scene 1200 -
+ * Scene 1200 - Air Ducts Maze
*
*--------------------------------------------------------------------------*/
+
Scene1200::Scene1200() {
- _field412 = 0;
+ _nextCrawlDirection = 0;
_field414 = 0;
_field416 = 0;
_field418 = 0;
_field41A = 0;
- _field41C = 1; //CHECKME: Only if fixup_flag == 6??
+ _fixupMaze = false;
}
void Scene1200::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_nextCrawlDirection);
s.syncAsSint16LE(_field414);
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();
@@ -900,7 +1365,7 @@ void Scene1200::Area1::Actor3::init(int state) {
switch (_state) {
case 1:
- switch (R2_GLOBALS._v56AA6) {
+ switch (R2_GLOBALS._ductMazePanel1State) {
case 1:
setFrame2(2);
setPosition(Common::Point(129, 101));
@@ -912,8 +1377,9 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 2:
- switch (R2_GLOBALS._v56AA7) {
+ switch (R2_GLOBALS._ductMazePanel2State) {
case 1:
setFrame2(2);
setPosition(Common::Point(152, 101));
@@ -929,8 +1395,9 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 3:
- switch (R2_GLOBALS._v56AA8) {
+ switch (R2_GLOBALS._ductMazePanel3State) {
case 1:
setFrame2(3);
setPosition(Common::Point(158, 95));
@@ -942,6 +1409,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
default:
break;
}
@@ -949,31 +1417,31 @@ 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);
R2_GLOBALS._sound2.play(260);
switch (_state) {
case 1:
- if (R2_GLOBALS._v56AA6 == 1) {
- R2_GLOBALS._v56AA6 = 2;
+ if (R2_GLOBALS._ductMazePanel1State == 1) {
+ R2_GLOBALS._ductMazePanel1State = 2;
setFrame2(3);
setPosition(Common::Point(135, 95));
} else {
- R2_GLOBALS._v56AA6 = 1;
+ R2_GLOBALS._ductMazePanel1State = 1;
setFrame2(2);
setPosition(Common::Point(129, 101));
}
break;
case 2:
- ++R2_GLOBALS._v56AA7;
- if (R2_GLOBALS._v56AA7 == 4)
- R2_GLOBALS._v56AA7 = 1;
+ ++R2_GLOBALS._ductMazePanel2State;
+ if (R2_GLOBALS._ductMazePanel2State == 4)
+ R2_GLOBALS._ductMazePanel2State = 1;
- switch (R2_GLOBALS._v56AA7) {
+ switch (R2_GLOBALS._ductMazePanel2State) {
case 1:
- setFrame2(1);
+ setFrame2(2);
setPosition(Common::Point(152, 101));
break;
case 2:
@@ -989,12 +1457,12 @@ bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
}
break;
case 3:
- if (R2_GLOBALS._v56AA8 == 1) {
- R2_GLOBALS._v56AA8 = 2;
+ if (R2_GLOBALS._ductMazePanel3State == 1) {
+ R2_GLOBALS._ductMazePanel3State = 2;
setFrame2(2);
setPosition(Common::Point(175, 101));
} else {
- R2_GLOBALS._v56AA8 = 1;
+ R2_GLOBALS._ductMazePanel3State = 1;
setFrame2(3);
setPosition(Common::Point(158, 95));
}
@@ -1006,121 +1474,68 @@ bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field418 = 0;
- if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1))
+ if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
scene->_field418 = 1;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
scene->_field418 = 2;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 2))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
scene->_field418 = 3;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 3) && (R2_GLOBALS._v56AA8 == 1))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
scene->_field418 = 4;
return true;
}
-void Scene1200::Area1::postInit(SceneObjectList *OwnerList) {
+void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field41A = 1;
R2_GLOBALS._events.setCursor(CURSOR_USE);
- proc12(1003, 1, 1, 100, 40);
- proc13(1200, 11, -1, -1);
+ setup2(1003, 1, 1, 100, 40);
+ setup3(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();
-
- // sub201EA
- R2_GLOBALS._sceneItems.remove((SceneItem *)this);
- _actor2.remove();
- SceneArea::remove();
- R2_GLOBALS._insetUp--;
- //
-
+ scene->_sceneAreas.remove(&_jumper1);
+ scene->_sceneAreas.remove(&_jumper2);
+ scene->_sceneAreas.remove(&_jumper3);
+ _jumper1.remove();
+ _jumper2.remove();
+ _jumper3.remove();
+
+ ModalWindow::remove();
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();
if (R2_GLOBALS._sceneManager._previousScene < 3200)
R2_GLOBALS._sound1.play(257);
- _field412 = 1;
+ _nextCrawlDirection = CRAWL_EAST;
_field414 = 0;
_field416 = 0;
_field418 = 0;
_field41A = 0;
- _field41C = 0;
- if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1))
+ if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
_field418 = 1;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
_field418 = 2;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 2))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
_field418 = 3;
- else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 3) && (R2_GLOBALS._v56AA8 == 1))
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
_field418 = 4;
R2_GLOBALS._player.postInit();
@@ -1128,19 +1543,16 @@ void Scene1200::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setup(3156, 1, 6);
R2_GLOBALS._player.setPosition(Common::Point(160, 70));
R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player._oldCharacterScene[3] = 1200;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 1200;
_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.postInit();
+ _mazeUI.load(1);
+ _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
R2_GLOBALS._player.enableControl();
_item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL);
@@ -1158,7 +1570,7 @@ void Scene1200::signal() {
// No break on purpose
case 1203:
R2_GLOBALS._player.enableControl();
- warning("_eventManager.waitEvent()");
+ // CHECKME: The original is calling _eventManager.waitEvent();
_sceneMode = 2;
break;
case 10:
@@ -1337,7 +1749,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:
@@ -1380,7 +1792,7 @@ void Scene1200::signal() {
R2_GLOBALS._player.animate(ANIM_MODE_6, this);
break;
default:
- warning("_eventManager.waitEvent()");
+ // CHECKME: The original is walling _eventManager.waitEvent();
_sceneMode = 2;
break;
}
@@ -1396,61 +1808,63 @@ 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._ventCellPos;
+ _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;
case 33:
- if (R2_GLOBALS._v56AA1 >= 4)
+ if (R2_GLOBALS._scientistConvIndex >= 4)
R2_GLOBALS._sceneManager.changeScene(3250);
else
- SceneItem::display(1200, 6, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(1200, 6, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
default:
- SceneItem::display(1200, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(1200, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
}
event.handled = true;
@@ -1458,23 +1872,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:
- SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- break;
+ // It was your cell.
+ SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ 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
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ // A vent grill
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
case 17:
- switch (R2_GLOBALS._v56AA4) {
+ switch (cellPos.y) {
case 5:
R2_GLOBALS._sceneManager.changeScene(3230);
break;
@@ -1485,20 +1901,23 @@ void Scene1200::process(Event &event) {
R2_GLOBALS._sceneManager.changeScene(3200);
break;
default:
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ // A vent grill
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
}
+ break;
case 33:
R2_GLOBALS._sceneManager.changeScene(3245);
break;
default:
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
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);
+ SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
break;
case CURSOR_TALK:
@@ -1514,81 +1933,77 @@ void Scene1200::process(Event &event) {
}
switch (event.kbd.keycode) {
- case Common::KEYCODE_1:
- warning("FIXME: keycode = 0x4800");
- sub9DAD6(4);
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_UP:
+ startCrawling(CRAWL_NORTH);
break;
- case Common::KEYCODE_2:
- warning("FIXME: keycode = 0x4B00");
- sub9DAD6(2);
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_LEFT:
+ startCrawling(CRAWL_WEST);
break;
- case Common::KEYCODE_3:
- warning("FIXME: keycode = 0x4D00");
- sub9DAD6(1);
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_RIGHT:
+ startCrawling(CRAWL_EAST);
break;
- case Common::KEYCODE_4:
- warning("FIXME: keycode = 0x5000");
- sub9DAD6(3);
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_DOWN:
+ startCrawling(CRAWL_SOUTH);
break;
default:
event.handled = false;
return;
break;
}
- } else {
+ } else
return;
- }
}
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();
- warning("_gfxManager.sub294AC(unk);");
- warning("tmpRect.sub14DF3();");
- _field41C = 0;
+
+ if (_fixupMaze) {
+ _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
+ //_mazeUI.draw();
+ _fixupMaze = false;
}
if (_field414 != 0) {
tmpRect.set(110, 20, 210, 120);
_field414--;
- switch (_field412 - 1) {
- case 0:
- R2_GLOBALS._v56AA2 += 2;
+
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ R2_GLOBALS._ventCellPos.x += 2;
break;
- case 1:
- R2_GLOBALS._v56AA2 -= 2;
+ case CRAWL_WEST:
+ R2_GLOBALS._ventCellPos.x -= 2;
break;
- case 2:
- R2_GLOBALS._v56AA4 += 2;
+ case CRAWL_SOUTH:
+ R2_GLOBALS._ventCellPos.y += 2;
break;
- case 3:
- R2_GLOBALS._v56AA4 -= 2;
+ case CRAWL_NORTH:
+ R2_GLOBALS._ventCellPos.y -= 2;
break;
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(R2_GLOBALS._ventCellPos);
+ //_mazeUI.draw();
if (_field416 != 0) {
- switch(_field412 - 1) {
- case 0:
+ switch(_nextCrawlDirection) {
+ case CRAWL_EAST:
R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x - 2, R2_GLOBALS._player._position.y));
break;
- case 1:
+ case CRAWL_WEST:
R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x + 2, R2_GLOBALS._player._position.y));
break;
- case 2:
+ case CRAWL_SOUTH:
R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 2));
break;
- case 3:
+ case CRAWL_NORTH:
R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 2));
break;
default:
@@ -1608,14 +2023,198 @@ void Scene1200::saveCharacter(int characterIndex) {
SceneExt::saveCharacter(characterIndex);
}
+void Scene1200::startCrawling(CrawlDirection dir) {
+ Common::Point cellPos = R2_GLOBALS._ventCellPos;
+ _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 (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 15;
+ else
+ _sceneMode = 10;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 76;
+ else
+ _sceneMode = 75;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 101;
+ else
+ _sceneMode = 100;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 111;
+ else
+ _sceneMode = 110;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 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 (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 56;
+ else
+ _sceneMode = 55;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 25;
+ else
+ _sceneMode = 20;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 91;
+ else
+ _sceneMode = 90;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 121;
+ else
+ _sceneMode = 120;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 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 (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 51;
+ else
+ _sceneMode = 50;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 81;
+ else
+ _sceneMode = 80;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 35;
+ else
+ _sceneMode = 30;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 116;
+ else
+ _sceneMode = 115;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 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 (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 61;
+ else
+ _sceneMode = 60;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 71;
+ else
+ _sceneMode = 70;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 96;
+ else
+ _sceneMode = 95;
+ break;
+ case CRAWL_NORTH:
+ 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();
+ _nextCrawlDirection = 4;
+ signal();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
/*--------------------------------------------------------------------------
* Scene 1337 - Card game
*
*--------------------------------------------------------------------------*/
Scene1337::unkObj1337sub1::unkObj1337sub1() {
- _field34 = 0;
- _field36 = Common::Point(0, 0);
+ _cardId = 0;
+ _stationPos = Common::Point(0, 0);
}
void Scene1337::unkObj1337sub1::synchronize(Serializer &s) {
@@ -1636,42 +2235,50 @@ void Scene1337::unkObj1337_1::synchronize(Serializer &s) {
Scene1337::Scene1337() {
_autoplay = false;
- _field3E24 = 0;
+ _cardsAvailableNumb = 0;
_field3E26 = 0;
for (int i = 0; i < 100; i++)
- _field3E28[i] = 0;
+ _availableCardsPile[i] = 0;
- _field423C = 0;
- _field423E = 0;
+ _shuffleEndedFl = false;
+ _currentPlayerNumb = 0;
_field4240 = 0;
_field4242 = 0;
- _field4244 = 0;
- _field4246 = 0;
+ _field4244 = false;
+ _field4246 = false;
_field4248 = 0;
_field424A = 0;
- _field424C = 0;
- _field424E = 0;
+ _instructionsDisplayedFl = 0;
+ _instructionsWaitCount = 0;
+
+ _unkFctPtr412 = nullptr;
+ _field3EF0 = nullptr;
+ _field3EF4 = nullptr;
+ _field3EF8 = nullptr;
}
void Scene1337::synchronize(Serializer &s) {
warning("STUBBED: Scene1337::synchronize()");
}
-void Scene1337::Action1337::subD18B5(int resNum, int stripNum, int frameNum) {
- warning("STUBBED: Action1337::subD18B5()");
-}
-
-void Scene1337::Action1337::skipFrames(int32 skipCount) {
+void Scene1337::Action1337::waitFrames(int32 frameCount) {
uint32 firstFrameNumber = g_globals->_events.getFrameNumber();
- uint32 tmpFrameNumber = firstFrameNumber;
-
- while (tmpFrameNumber < firstFrameNumber + skipCount)
- tmpFrameNumber = g_globals->_events.getFrameNumber();
+ uint32 curFrame = firstFrameNumber;
+ uint32 destFrame = firstFrameNumber + frameCount;
- warning("_eventManager.waitEvent(-1)");
+ while ((curFrame < destFrame) && !g_vm->shouldQuit()) {
+ TsAGE::Event event;
+ g_globals->_events.getEvent(event);
+ curFrame = g_globals->_events.getFrameNumber();
+ }
+
+ // CHECKME: The original is calling _eventManager.waitEvent();
}
+/**
+ * Display instructions
+ */
void Scene1337::Action1::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
@@ -1682,393 +2289,392 @@ void Scene1337::Action1::signal() {
scene->actionDisplay(1331, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
scene->actionDisplay(1331, 8, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrunkObj1337[1]._arr2[0]._field34 = 2;
- scene->_arrunkObj1337[1]._arr2[0]._object1.postInit();
- scene->_arrunkObj1337[1]._arr2[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr2[0]._object1.setPosition(scene->_arrunkObj1337[1]._arr2[0]._field36, 0);
- scene->_arrunkObj1337[1]._arr2[0]._object1.setStrip(2);
- scene->_arrunkObj1337[1]._arr2[0]._object1.setFrame(scene->_arrunkObj1337[1]._arr2[0]._field34);
- scene->_arrunkObj1337[1]._arr2[0]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[1]._arr2[0]);
-
- scene->_arrunkObj1337[1]._arr2[1]._field34 = 3;
- scene->_arrunkObj1337[1]._arr2[1]._object1.postInit();
- scene->_arrunkObj1337[1]._arr2[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr2[1]._object1.setPosition(scene->_arrunkObj1337[1]._arr2[1]._field36, 0);
- scene->_arrunkObj1337[1]._arr2[1]._object1.setStrip(2);
- scene->_arrunkObj1337[1]._arr2[1]._object1.setFrame(scene->_arrunkObj1337[1]._arr2[1]._field34);
- scene->_arrunkObj1337[1]._arr2[1]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[1]._arr2[1]);
-
- scene->_arrunkObj1337[2]._arr2[0]._field34 = 4;
- scene->_arrunkObj1337[2]._arr2[0]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[0]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[0]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[0]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[0]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[0]._field34);
- scene->_arrunkObj1337[2]._arr2[0]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[0]);
-
- scene->_arrunkObj1337[3]._arr2[0]._field34 = 5;
- scene->_arrunkObj1337[3]._arr2[0]._object1.postInit();
- scene->_arrunkObj1337[3]._arr2[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr2[0]._object1.setPosition(scene->_arrunkObj1337[3]._arr2[0]._field36, 0);
- scene->_arrunkObj1337[3]._arr2[0]._object1.setStrip(2);
- scene->_arrunkObj1337[3]._arr2[0]._object1.setFrame(scene->_arrunkObj1337[3]._arr2[0]._field34);
- scene->_arrunkObj1337[3]._arr2[0]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[3]._arr2[0]);
-
- scene->_arrunkObj1337[3]._arr2[1]._field34 = 6;
- scene->_arrunkObj1337[3]._arr2[1]._object1.postInit();
- scene->_arrunkObj1337[3]._arr2[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr2[1]._object1.setPosition(scene->_arrunkObj1337[3]._arr2[1]._field36, 0);
- scene->_arrunkObj1337[3]._arr2[1]._object1.setStrip(2);
- scene->_arrunkObj1337[3]._arr2[1]._object1.setFrame(scene->_arrunkObj1337[3]._arr2[1]._field34);
- scene->_arrunkObj1337[3]._arr2[1]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[3]._arr2[1]);
-
- scene->_arrunkObj1337[3]._arr2[2]._field34 = 7;
- scene->_arrunkObj1337[3]._arr2[2]._object1.postInit();
- scene->_arrunkObj1337[3]._arr2[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr2[2]._object1.setPosition(scene->_arrunkObj1337[3]._arr2[2]._field36, 0);
- scene->_arrunkObj1337[3]._arr2[2]._object1.setStrip(2);
- scene->_arrunkObj1337[3]._arr2[2]._object1.setFrame(scene->_arrunkObj1337[3]._arr2[2]._field34);
- scene->_arrunkObj1337[3]._arr2[2]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[3]._arr2[2]);
-
- scene->_arrunkObj1337[0]._arr2[0]._field34 = 8;
- scene->_arrunkObj1337[0]._arr2[0]._object1.postInit();
- scene->_arrunkObj1337[0]._arr2[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr2[0]._object1.setPosition(scene->_arrunkObj1337[0]._arr2[0]._field36, 0);
- scene->_arrunkObj1337[0]._arr2[0]._object1.setStrip(2);
- scene->_arrunkObj1337[0]._arr2[0]._object1.setFrame(scene->_arrunkObj1337[0]._arr2[0]._field34);
- scene->_arrunkObj1337[0]._arr2[0]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[0]._arr2[0]);
-
- scene->_arrunkObj1337[0]._arr2[1]._field34 = 9;
- scene->_arrunkObj1337[0]._arr2[1]._object1.postInit();
- scene->_arrunkObj1337[0]._arr2[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr2[1]._object1.setPosition(scene->_arrunkObj1337[0]._arr2[1]._field36, 0);
- scene->_arrunkObj1337[0]._arr2[1]._object1.setStrip(2);
- scene->_arrunkObj1337[0]._arr2[1]._object1.setFrame(scene->_arrunkObj1337[0]._arr2[1]._field34);
- scene->_arrunkObj1337[0]._arr2[1]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[0]._arr2[1]);
+ scene->_gameBoardSide[1]._outpostStation[0]._cardId = 2;
+ scene->_gameBoardSide[1]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[0]);
+
+ scene->_gameBoardSide[1]._outpostStation[1]._cardId = 3;
+ scene->_gameBoardSide[1]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[1]);
+
+ scene->_gameBoardSide[2]._outpostStation[0]._cardId = 4;
+ scene->_gameBoardSide[2]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[0]._cardId);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[0]);
+
+ scene->_gameBoardSide[3]._outpostStation[0]._cardId = 5;
+ scene->_gameBoardSide[3]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[0]);
+
+ scene->_gameBoardSide[3]._outpostStation[1]._cardId = 6;
+ scene->_gameBoardSide[3]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[1]);
+
+ scene->_gameBoardSide[3]._outpostStation[2]._cardId = 7;
+ scene->_gameBoardSide[3]._outpostStation[2]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[2]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[2]);
+
+ scene->_gameBoardSide[0]._outpostStation[0]._cardId = 8;
+ scene->_gameBoardSide[0]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[0]);
+
+ scene->_gameBoardSide[0]._outpostStation[1]._cardId = 9;
+ scene->_gameBoardSide[0]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[1]);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(60);
+ waitFrames(60);
scene->actionDisplay(1331, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrunkObj1337[2]._arr2[1]._field34 = 2;
- scene->_arrunkObj1337[2]._arr2[1]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[1]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[1]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[1]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[1]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[1]._field34);
- scene->_arrunkObj1337[2]._arr2[1]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[1]);
-
- scene->_arrunkObj1337[2]._arr2[2]._field34 = 3;
- scene->_arrunkObj1337[2]._arr2[2]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[2]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[2]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[2]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[2]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[2]._field34);
- scene->_arrunkObj1337[2]._arr2[2]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[2]);
-
- scene->_arrunkObj1337[2]._arr2[3]._field34 = 5;
- scene->_arrunkObj1337[2]._arr2[3]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[3]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[3]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[3]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[3]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[3]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[3]._field34);
- scene->_arrunkObj1337[2]._arr2[3]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[3]);
-
- scene->_arrunkObj1337[2]._arr2[4]._field34 = 6;
- scene->_arrunkObj1337[2]._arr2[4]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[4]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[4]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[4]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[4]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[4]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[4]._field34);
- scene->_arrunkObj1337[2]._arr2[4]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[4]);
-
- scene->_arrunkObj1337[2]._arr2[5]._field34 = 7;
- scene->_arrunkObj1337[2]._arr2[5]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[5]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[5]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[5]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[5]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[5]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[5]._field34);
- scene->_arrunkObj1337[2]._arr2[5]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[5]);
-
- scene->_arrunkObj1337[2]._arr2[6]._field34 = 8;
- scene->_arrunkObj1337[2]._arr2[6]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[6]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[6]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[6]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[6]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[6]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[6]._field34);
- scene->_arrunkObj1337[2]._arr2[6]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[6]);
-
- scene->_arrunkObj1337[2]._arr2[7]._field34 = 9;
- scene->_arrunkObj1337[2]._arr2[7]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[7]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[7]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[7]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[7]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr2[7]._object1.setFrame(scene->_arrunkObj1337[2]._arr2[7]._field34);
- scene->_arrunkObj1337[2]._arr2[7]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[7]);
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = 2;
+ scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
+
+ scene->_gameBoardSide[2]._outpostStation[2]._cardId = 3;
+ scene->_gameBoardSide[2]._outpostStation[2]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[2]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[2]);
+
+ scene->_gameBoardSide[2]._outpostStation[3]._cardId = 5;
+ scene->_gameBoardSide[2]._outpostStation[3]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[3]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[3]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[3]);
+
+ scene->_gameBoardSide[2]._outpostStation[4]._cardId = 6;
+ scene->_gameBoardSide[2]._outpostStation[4]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[4]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[4]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[4]);
+
+ scene->_gameBoardSide[2]._outpostStation[5]._cardId = 7;
+ scene->_gameBoardSide[2]._outpostStation[5]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[5]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[5]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[5]);
+
+ scene->_gameBoardSide[2]._outpostStation[6]._cardId = 8;
+ scene->_gameBoardSide[2]._outpostStation[6]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[6]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[6]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[6]);
+
+ scene->_gameBoardSide[2]._outpostStation[7]._cardId = 9;
+ scene->_gameBoardSide[2]._outpostStation[7]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[7]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[7]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[7]);
scene->_aSound1.play(62);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(120);
- scene->_arrunkObj1337[2]._arr2[0]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[1]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[2]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[3]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[4]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[5]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[6]._object1.remove();
- scene->_arrunkObj1337[2]._arr2[7]._object1.remove();
+ waitFrames(120);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[2]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[3]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[4]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[5]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[6]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[7]._card.remove();
- scene->_arrunkObj1337[1]._arr2[0]._object1.remove();
- scene->_arrunkObj1337[1]._arr2[1]._object1.remove();
+ scene->_gameBoardSide[1]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[1]._outpostStation[1]._card.remove();
- scene->_arrunkObj1337[3]._arr2[0]._object1.remove();
- scene->_arrunkObj1337[3]._arr2[1]._object1.remove();
- scene->_arrunkObj1337[3]._arr2[2]._object1.remove();
+ scene->_gameBoardSide[3]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[3]._outpostStation[1]._card.remove();
+ scene->_gameBoardSide[3]._outpostStation[2]._card.remove();
- scene->_arrunkObj1337[0]._arr2[0]._object1.remove();
- scene->_arrunkObj1337[0]._arr2[1]._object1.remove();
+ scene->_gameBoardSide[0]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[0]._outpostStation[1]._card.remove();
scene->_background2.setup2(1332, 5, 1, 165, 95, 110, 1);
- scene->_arrunkObj1337[1]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[0]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[1]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[1]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[1]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[2]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[2]._arr1[0]._field34 = 30;
- scene->_arrunkObj1337[2]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setFrame(2);
- scene->_arrunkObj1337[2]._arr1[0]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr1[0]);
-
- scene->_arrunkObj1337[2]._arr1[1]._field34 = 16;
- scene->_arrunkObj1337[2]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setFrame(2);
- scene->_arrunkObj1337[2]._arr1[1]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr1[1]);
-
- scene->_arrunkObj1337[2]._arr1[2]._field34 = 1;
- scene->_arrunkObj1337[2]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setFrame(2);
- scene->_arrunkObj1337[2]._arr1[2]._object1.fixPriority(170);
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr1[2]);
-
- scene->_arrunkObj1337[3]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[0]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[3]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[1]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[3]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[2]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[0]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setFrame(2);
- scene->_arrunkObj1337[0]._arr1[0]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[0]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setFrame(2);
- scene->_arrunkObj1337[0]._arr1[1]._object1.fixPriority(170);
-
- scene->_arrunkObj1337[0]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setFrame(2);
- scene->_arrunkObj1337[0]._arr1[2]._object1.fixPriority(170);
+ scene->_gameBoardSide[1]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[1]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[1]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
+
+ scene->_gameBoardSide[2]._handCard[0]._cardId = 30;
+ scene->_gameBoardSide[2]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[0]);
+
+ scene->_gameBoardSide[2]._handCard[1]._cardId = 16;
+ scene->_gameBoardSide[2]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[1]);
+
+ scene->_gameBoardSide[2]._handCard[2]._cardId = 1;
+ scene->_gameBoardSide[2]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[2]);
+
+ scene->_gameBoardSide[3]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[3]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[3]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[0]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[1]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[2]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
R2_GLOBALS._sceneObjects->draw();
scene->actionDisplay(1331, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_item2._object1.setPosition(Common::Point(162, 95), 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
+ scene->_animatedCard._card.show();
scene->_aSound2.play(61);
Common::Point pt(91, 174);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
}
break;
case 2: {
- scene->_arrunkObj1337[2]._arr1[3]._field34 = 2;
- scene->_arrunkObj1337[2]._arr1[3]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[3]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[3]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[3]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[3]._object1.setStrip(1);
- scene->_arrunkObj1337[2]._arr1[3]._object1.setFrame(2);
- scene->_arrunkObj1337[2]._arr1[3]._object1.fixPriority(170);
+ scene->_gameBoardSide[2]._handCard[3]._cardId = 2;
+ scene->_gameBoardSide[2]._handCard[3]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[3]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[3]._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[3]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[3]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[3]._card.fixPriority(170);
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr1[3]);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[3]);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(60);
+ waitFrames(60);
scene->actionDisplay(1331, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
scene->actionDisplay(1331, 12, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrunkObj1337[2]._arr2[1]._field34 = 1;
- scene->_arrunkObj1337[2]._arr2[1]._object1.postInit();
- scene->_arrunkObj1337[2]._arr2[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr2[1]._object1.setPosition(scene->_arrunkObj1337[2]._arr2[1]._field36, 0);
- scene->_arrunkObj1337[2]._arr2[1]._object1.hide();
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = 1;
+ scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.hide();
- scene->_item2._object1.setStrip(scene->_arrunkObj1337[2]._arr1[2]._object1._strip);
- scene->_item2._object1.setFrame(scene->_arrunkObj1337[2]._arr1[2]._object1._frame);
- scene->_item2._object1.animate(ANIM_MODE_NONE, NULL);
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[2]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
- scene->_arrunkObj1337[2]._arr1[2]._field34 = 0;
- scene->_arrunkObj1337[2]._arr1[2]._object1.remove();
+ scene->_gameBoardSide[2]._handCard[2]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[2]._card.remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr1[2]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[2]._arr2[1]._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
}
break;
case 3: {
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[1]);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
scene->_aSound1.play(59);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(60);
+ waitFrames(60);
scene->actionDisplay(1331, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrunkObj1337[2]._arr2[1]._field34 = scene->_arrunkObj1337[2]._arr1[3]._field34;
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = scene->_gameBoardSide[2]._handCard[3]._cardId;
- scene->_item2._object1.setStrip(scene->_arrunkObj1337[2]._arr1[3]._object1._strip);
- scene->_item2._object1.setFrame(scene->_arrunkObj1337[2]._arr1[3]._object1._frame);
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[3]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[3]._card._frame);
- scene->_arrunkObj1337[2]._arr1[3]._field34 = 0;
- scene->_arrunkObj1337[2]._arr1[3]._object1.remove();
+ scene->_gameBoardSide[2]._handCard[3]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[3]._card.remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr1[3]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[2]._arr2[1]._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
}
break;
case 4: {
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr2[1]);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
scene->_aSound1.play(59);
- scene->_item7._field34 = 1;
- scene->_item7._object1.hide();
+ scene->_discardPile._cardId = 1;
+ scene->_discardPile._card.hide();
- scene->_item2._object1.setStrip(5);
- scene->_item2._object1.setFrame(1);
- scene->_item2._object1.animate(ANIM_MODE_2, NULL);
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr2[1]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_item7._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
}
break;
case 5: {
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
- scene->_item7._object1.postInit();
- scene->_item7._object1.setVisage(1332);
- scene->_item7._object1.setPosition(scene->_item7._field36, 0);
- scene->setAnimationInfo(&scene->_item7);
+ scene->_discardPile._card.postInit();
+ scene->_discardPile._card.setVisage(1332);
+ scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
+ scene->setAnimationInfo(&scene->_discardPile);
scene->_aSound2.play(61);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(60);
+ waitFrames(60);
scene->actionDisplay(1331, 14, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrunkObj1337[2]._arr3[0]._object1.postInit();
- scene->_arrunkObj1337[2]._arr3[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr3[0]._object1.setPosition(scene->_arrunkObj1337[2]._arr3[0]._field36, 0);
- scene->_arrunkObj1337[2]._arr3[0]._object1.hide();
+ scene->_gameBoardSide[2]._delayPile[0]._card.postInit();
+ scene->_gameBoardSide[2]._delayPile[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._delayPile[0]._card.setPosition(scene->_gameBoardSide[2]._delayPile[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._delayPile[0]._card.hide();
- scene->_arrunkObj1337[3]._arr1[2]._field34 = 0;
- scene->_arrunkObj1337[3]._arr1[2].remove();
+ scene->_gameBoardSide[3]._handCard[2]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[2].remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[3]._arr1[2]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[2]._arr3[0]._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayPile[0]._stationPos, this);
}
break;
case 6: {
- scene->_item2._object1.hide();
- scene->_arrunkObj1337[2]._arr3[0]._field34 = 21;
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr3[0]);
+ scene->_animatedCard._card.hide();
+ scene->_gameBoardSide[2]._delayPile[0]._cardId = 21;
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayPile[0]);
scene->_aSound1.play(57);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(60);
+ waitFrames(60);
scene->actionDisplay(1331, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
int tmpVal = 15;
@@ -2077,89 +2683,89 @@ void Scene1337::Action1::signal() {
for (i = 0; i <= 7; i++) {
tmpVal += 29;
- scene->_arrObject1[i].postInit();
- scene->_arrObject1[i].setVisage(1332);
- scene->_arrObject1[i].setPosition(Common::Point(tmpVal, 90), 0);
- scene->_arrObject1[i].setStrip(3);
- scene->_arrObject1[i].fixPriority(190);
-
- scene->_arrObject2[i].postInit();
- scene->_arrObject2[i].setVisage(1332);
- scene->_arrObject2[i].setPosition(Common::Point(tmpVal, 90), 0);
- scene->_arrObject2[i].setStrip(7);
- scene->_arrObject2[i].setFrame(1);
- scene->_arrObject2[i].fixPriority(180);
- }
-
- scene->_arrObject1[0].setFrame(1);
- scene->_arrObject1[1].setFrame(3);
- scene->_arrObject1[2].setFrame(6);
- scene->_arrObject1[3].setFrame(8);
- scene->_arrObject1[4].setFrame(9);
- scene->_arrObject1[5].setFrame(10);
- scene->_arrObject1[6].setFrame(11);
- scene->_arrObject1[7].setFrame(12);
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
+ scene->_upperDisplayCard[i].setStrip(3);
+ scene->_upperDisplayCard[i].fixPriority(190);
+
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
+ }
+
+ scene->_upperDisplayCard[0].setFrame(1);
+ scene->_upperDisplayCard[1].setFrame(3);
+ scene->_upperDisplayCard[2].setFrame(6);
+ scene->_upperDisplayCard[3].setFrame(8);
+ scene->_upperDisplayCard[4].setFrame(9);
+ scene->_upperDisplayCard[5].setFrame(10);
+ scene->_upperDisplayCard[6].setFrame(11);
+ scene->_upperDisplayCard[7].setFrame(12);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(240);
+ waitFrames(240);
- scene->_arrObject1[0].remove();
- scene->_arrObject1[1].remove();
- scene->_arrObject1[2].remove();
- scene->_arrObject1[3].remove();
- scene->_arrObject1[4].remove();
- scene->_arrObject1[5].remove();
- scene->_arrObject1[6].remove();
- scene->_arrObject1[7].remove();
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
+ scene->_upperDisplayCard[4].remove();
+ scene->_upperDisplayCard[5].remove();
+ scene->_upperDisplayCard[6].remove();
+ scene->_upperDisplayCard[7].remove();
- scene->_arrObject2[0].remove();
- scene->_arrObject2[1].remove();
- scene->_arrObject2[2].remove();
- scene->_arrObject2[3].remove();
- scene->_arrObject2[4].remove();
- scene->_arrObject2[5].remove();
- scene->_arrObject2[6].remove();
- scene->_arrObject2[7].remove();
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
+ scene->_lowerDisplayCard[4].remove();
+ scene->_lowerDisplayCard[5].remove();
+ scene->_lowerDisplayCard[6].remove();
+ scene->_lowerDisplayCard[7].remove();
- scene->_item7._field34 = scene->_arrunkObj1337[2]._arr3[0]._field34;
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._delayPile[0]._cardId;
- scene->_arrunkObj1337[2]._arr3[0]._field34 = 0;
- scene->_arrunkObj1337[2]._arr3[0]._object1.remove();
+ scene->_gameBoardSide[2]._delayPile[0]._cardId = 0;
+ scene->_gameBoardSide[2]._delayPile[0]._card.remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr3[0]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayPile[0]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_item7._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
}
break;
case 7: {
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_item7);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
scene->_aSound2.play(61);
R2_GLOBALS._sceneObjects->draw();
- scene->_arrunkObj1337[2]._arr3[0]._object1.postInit();
- scene->_arrunkObj1337[2]._arr3[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr3[0]._object1.setPosition(scene->_arrunkObj1337[2]._arr3[0]._field36, 0);
- scene->_arrunkObj1337[2]._arr3[0]._object1.hide();
+ scene->_gameBoardSide[2]._delayPile[0]._card.postInit();
+ scene->_gameBoardSide[2]._delayPile[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._delayPile[0]._card.setPosition(scene->_gameBoardSide[2]._delayPile[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._delayPile[0]._card.hide();
- scene->_arrunkObj1337[3]._arr1[1]._field34 = 0;
- scene->_arrunkObj1337[3]._arr1[1].remove();
+ scene->_gameBoardSide[3]._handCard[1]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[1].remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[3]._arr1[1]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[2]._arr3[0]._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayPile[0]._stationPos, this);
}
break;
case 8: {
- scene->_item2._object1.hide();
- scene->_arrunkObj1337[2]._arr3[0]._field34 = 14;
- scene->setAnimationInfo(&scene->_arrunkObj1337[2]._arr3[0]);
+ scene->_animatedCard._card.hide();
+ scene->_gameBoardSide[2]._delayPile[0]._cardId = 14;
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayPile[0]);
scene->_aSound1.play(57);
R2_GLOBALS._sceneObjects->draw();
@@ -2170,219 +2776,219 @@ void Scene1337::Action1::signal() {
for (i = 0; i <= 3; i++) {
tmpVal += 29;
- scene->_arrObject1[i].postInit();
- scene->_arrObject1[i].setVisage(1332);
- scene->_arrObject1[i].setPosition(Common::Point(tmpVal, 71), 0);
- scene->_arrObject1[i].setStrip(3);
- scene->_arrObject1[i].fixPriority(190);
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
+ scene->_upperDisplayCard[i].setStrip(3);
+ scene->_upperDisplayCard[i].fixPriority(190);
- scene->_arrObject2[i].postInit();
- scene->_arrObject2[i].setVisage(1332);
- scene->_arrObject2[i].setPosition(Common::Point(tmpVal, 71), 0);
- scene->_arrObject2[i].setStrip(7);
- scene->_arrObject2[i].setFrame(1);
- scene->_arrObject2[i].fixPriority(180);
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
}
- scene->_arrObject1[0].setFrame(2);
- scene->_arrObject1[1].setFrame(5);
- scene->_arrObject1[2].setFrame(7);
- scene->_arrObject1[3].setFrame(15);
+ scene->_upperDisplayCard[0].setFrame(2);
+ scene->_upperDisplayCard[1].setFrame(5);
+ scene->_upperDisplayCard[2].setFrame(7);
+ scene->_upperDisplayCard[3].setFrame(15);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(240);
+ waitFrames(240);
scene->actionDisplay(1331, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
tmpVal = 72;
for (i = 4; i <= 7; i++) {
tmpVal += 29;
- scene->_arrObject1[i].postInit();
- scene->_arrObject1[i].setVisage(1332);
- scene->_arrObject1[i].setPosition(Common::Point(tmpVal, 100), 0);
- scene->_arrObject1[i].setStrip(4);
- scene->_arrObject1[i].fixPriority(190);
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
+ scene->_upperDisplayCard[i].setStrip(4);
+ scene->_upperDisplayCard[i].fixPriority(190);
- scene->_arrObject2[i].postInit();
- scene->_arrObject2[i].setVisage(1332);
- scene->_arrObject2[i].setPosition(Common::Point(tmpVal, 100), 0);
- scene->_arrObject2[i].setStrip(7);
- scene->_arrObject2[i].setFrame(1);
- scene->_arrObject2[i].fixPriority(180);
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
}
- scene->_arrObject1[4].setFrame(1);
- scene->_arrObject1[5].setFrame(5);
- scene->_arrObject1[6].setFrame(7);
- scene->_arrObject1[7].setFrame(3);
+ scene->_upperDisplayCard[4].setFrame(1);
+ scene->_upperDisplayCard[5].setFrame(5);
+ scene->_upperDisplayCard[6].setFrame(7);
+ scene->_upperDisplayCard[7].setFrame(3);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(240);
+ waitFrames(240);
- scene->_arrObject1[0].remove();
- scene->_arrObject1[1].remove();
- scene->_arrObject1[2].remove();
- scene->_arrObject1[3].remove();
- scene->_arrObject1[4].remove();
- scene->_arrObject1[5].remove();
- scene->_arrObject1[6].remove();
- scene->_arrObject1[7].remove();
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
+ scene->_upperDisplayCard[4].remove();
+ scene->_upperDisplayCard[5].remove();
+ scene->_upperDisplayCard[6].remove();
+ scene->_upperDisplayCard[7].remove();
- scene->_arrObject2[0].remove();
- scene->_arrObject2[1].remove();
- scene->_arrObject2[2].remove();
- scene->_arrObject2[3].remove();
- scene->_arrObject2[4].remove();
- scene->_arrObject2[5].remove();
- scene->_arrObject2[6].remove();
- scene->_arrObject2[7].remove();
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
+ scene->_lowerDisplayCard[4].remove();
+ scene->_lowerDisplayCard[5].remove();
+ scene->_lowerDisplayCard[6].remove();
+ scene->_lowerDisplayCard[7].remove();
- scene->_item7._field34 = scene->_arrunkObj1337[2]._arr1[0]._field34;
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[0]._cardId;
- scene->_item2._object1.setStrip(scene->_arrunkObj1337[2]._arr1[0]._object1._strip);
- scene->_item2._object1.setFrame(scene->_arrunkObj1337[2]._arr1[0]._object1._frame);
- scene->_item2._object1.animate(ANIM_MODE_NONE, NULL);
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[0]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
- scene->_arrunkObj1337[2]._arr1[0]._field34 = 0;
- scene->_arrunkObj1337[2]._arr1[0]._object1.remove();
+ scene->_gameBoardSide[2]._handCard[0]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[0]._card.remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr1[0]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[2]._arr3[0]._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayPile[0]._stationPos, this);
}
break;
case 9: {
scene->_aSound1.play(58);
- scene->_arrunkObj1337[2]._arr3[0]._field34 = 0;
- scene->_arrunkObj1337[2]._arr3[0].remove();
- scene->_item2._object1.setStrip(5);
- scene->_item2._object1.setFrame(1);
- scene->_item2._object1.animate(ANIM_MODE_2, NULL);
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr3[0]._field36, 0);
- scene->_item2._object1.show();
+ scene->_gameBoardSide[2]._delayPile[0]._cardId = 0;
+ scene->_gameBoardSide[2]._delayPile[0].remove();
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayPile[0]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_item7._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
}
break;
case 10: {
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_item7);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
scene->_aSound2.play(61);
R2_GLOBALS._sceneObjects->draw();
scene->actionDisplay(1331, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_arrObject1[0].postInit();
- scene->_arrObject1[0].setVisage(1332);
- scene->_arrObject1[0].setPosition(Common::Point(131, 71), 0);
- scene->_arrObject1[0].fixPriority(190);
- scene->_arrObject1[0].setStrip(3);
- scene->_arrObject1[0].setFrame(4);
-
- scene->_arrObject2[0].postInit();
- scene->_arrObject2[0].setVisage(1332);
- scene->_arrObject2[0].setPosition(Common::Point(131, 71), 0);
- scene->_arrObject2[0].setStrip(7);
- scene->_arrObject2[0].setFrame(1);
- scene->_arrObject2[0].fixPriority(180);
-
- scene->_arrObject1[1].postInit();
- scene->_arrObject1[1].setVisage(1332);
- scene->_arrObject1[1].setPosition(Common::Point(160, 71), 0);
- scene->_arrObject1[1].fixPriority(190);
- scene->_arrObject1[1].setStrip(3);
- scene->_arrObject1[1].setFrame(16);
-
- scene->_arrObject2[1].postInit();
- scene->_arrObject2[1].setVisage(1332);
- scene->_arrObject2[1].setPosition(Common::Point(160, 71), 0);
- scene->_arrObject2[1].setStrip(7);
- scene->_arrObject2[1].setFrame(1);
- scene->_arrObject2[1].fixPriority(180);
-
- scene->_arrObject1[2].postInit();
- scene->_arrObject1[2].setVisage(1332);
- scene->_arrObject1[2].setPosition(Common::Point(131, 100), 0);
- scene->_arrObject1[2].fixPriority(190);
- scene->_arrObject1[2].setStrip(4);
- scene->_arrObject1[2].setFrame(4);
-
- scene->_arrObject2[2].postInit();
- scene->_arrObject2[2].setVisage(1332);
- scene->_arrObject2[2].setPosition(Common::Point(131, 100), 0);
- scene->_arrObject2[2].setStrip(7);
- scene->_arrObject2[2].setFrame(1);
- scene->_arrObject2[2].fixPriority(180);
-
- scene->_arrObject1[3].postInit();
- scene->_arrObject1[3].setVisage(1332);
- scene->_arrObject1[3].setPosition(Common::Point(160, 100), 0);
- scene->_arrObject1[3].fixPriority(190);
- scene->_arrObject1[3].setStrip(4);
- scene->_arrObject1[3].setFrame(2);
-
- scene->_arrObject2[3].postInit();
- scene->_arrObject2[3].setVisage(1332);
- scene->_arrObject2[3].setPosition(Common::Point(160, 100), 0);
- scene->_arrObject2[3].setStrip(7);
- scene->_arrObject2[3].setFrame(1);
- scene->_arrObject2[3].fixPriority(180);
+ scene->_upperDisplayCard[0].postInit();
+ scene->_upperDisplayCard[0].setVisage(1332);
+ scene->_upperDisplayCard[0].setPosition(Common::Point(131, 71), 0);
+ scene->_upperDisplayCard[0].fixPriority(190);
+ scene->_upperDisplayCard[0].setStrip(3);
+ scene->_upperDisplayCard[0].setFrame(4);
+
+ scene->_lowerDisplayCard[0].postInit();
+ scene->_lowerDisplayCard[0].setVisage(1332);
+ scene->_lowerDisplayCard[0].setPosition(Common::Point(131, 71), 0);
+ scene->_lowerDisplayCard[0].setStrip(7);
+ scene->_lowerDisplayCard[0].setFrame(1);
+ scene->_lowerDisplayCard[0].fixPriority(180);
+
+ scene->_upperDisplayCard[1].postInit();
+ scene->_upperDisplayCard[1].setVisage(1332);
+ scene->_upperDisplayCard[1].setPosition(Common::Point(160, 71), 0);
+ scene->_upperDisplayCard[1].fixPriority(190);
+ scene->_upperDisplayCard[1].setStrip(3);
+ scene->_upperDisplayCard[1].setFrame(16);
+
+ scene->_lowerDisplayCard[1].postInit();
+ scene->_lowerDisplayCard[1].setVisage(1332);
+ scene->_lowerDisplayCard[1].setPosition(Common::Point(160, 71), 0);
+ scene->_lowerDisplayCard[1].setStrip(7);
+ scene->_lowerDisplayCard[1].setFrame(1);
+ scene->_lowerDisplayCard[1].fixPriority(180);
+
+ scene->_upperDisplayCard[2].postInit();
+ scene->_upperDisplayCard[2].setVisage(1332);
+ scene->_upperDisplayCard[2].setPosition(Common::Point(131, 100), 0);
+ scene->_upperDisplayCard[2].fixPriority(190);
+ scene->_upperDisplayCard[2].setStrip(4);
+ scene->_upperDisplayCard[2].setFrame(4);
+
+ scene->_lowerDisplayCard[2].postInit();
+ scene->_lowerDisplayCard[2].setVisage(1332);
+ scene->_lowerDisplayCard[2].setPosition(Common::Point(131, 100), 0);
+ scene->_lowerDisplayCard[2].setStrip(7);
+ scene->_lowerDisplayCard[2].setFrame(1);
+ scene->_lowerDisplayCard[2].fixPriority(180);
+
+ scene->_upperDisplayCard[3].postInit();
+ scene->_upperDisplayCard[3].setVisage(1332);
+ scene->_upperDisplayCard[3].setPosition(Common::Point(160, 100), 0);
+ scene->_upperDisplayCard[3].fixPriority(190);
+ scene->_upperDisplayCard[3].setStrip(4);
+ scene->_upperDisplayCard[3].setFrame(2);
+
+ scene->_lowerDisplayCard[3].postInit();
+ scene->_lowerDisplayCard[3].setVisage(1332);
+ scene->_lowerDisplayCard[3].setPosition(Common::Point(160, 100), 0);
+ scene->_lowerDisplayCard[3].setStrip(7);
+ scene->_lowerDisplayCard[3].setFrame(1);
+ scene->_lowerDisplayCard[3].fixPriority(180);
R2_GLOBALS._sceneObjects->draw();
- skipFrames(240);
+ waitFrames(240);
- scene->_arrObject1[0].remove();
- scene->_arrObject1[1].remove();
- scene->_arrObject1[2].remove();
- scene->_arrObject1[3].remove();
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
- scene->_arrObject2[0].remove();
- scene->_arrObject2[1].remove();
- scene->_arrObject2[2].remove();
- scene->_arrObject2[3].remove();
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
- scene->_object1.setFrame(1);
- scene->_object1.show();
- scene->_object1.animate(ANIM_MODE_2, NULL);
+ scene->_currentPlayerArrow.setFrame(1);
+ scene->_currentPlayerArrow.show();
+ scene->_currentPlayerArrow.animate(ANIM_MODE_2, NULL);
R2_GLOBALS._sceneObjects->draw();
scene->actionDisplay(1331, 19, 159, 10, 1, 220, 0, 7, 0, 154, 154);
- scene->_object1.hide();
+ scene->_currentPlayerArrow.hide();
scene->actionDisplay(1331, 20, 159, 10, 1, 220, 0, 7, 0, 154, 154);
scene->actionDisplay(1331, 21, 159, 10, 1, 220, 0, 7, 0, 154, 154);
- scene->_item7._field34 = scene->_arrunkObj1337[2]._arr1[1]._field34;
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[1]._cardId;
- scene->_item2._object1.setStrip(scene->_arrunkObj1337[2]._arr1[1]._object1._strip);
- scene->_item2._object1.setFrame(scene->_arrunkObj1337[2]._arr1[1]._object1._frame);
- scene->_item2._object1.animate(ANIM_MODE_NONE, NULL);
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[1]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
- scene->_arrunkObj1337[2]._arr1[1]._field34 = 0;
- scene->_arrunkObj1337[2]._arr1[1]._object1.remove();
+ scene->_gameBoardSide[2]._handCard[1]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[1]._card.remove();
- scene->_item2._object1.setPosition(scene->_arrunkObj1337[2]._arr1[1]._field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_item7._field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
}
break;
case 11: {
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_item7);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
scene->_aSound2.play(61);
- scene->_item2._object1.setStrip(5);
- scene->_item2._object1.setFrame(1);
- scene->_item2._object1.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
R2_GLOBALS._sceneObjects->draw();
@@ -2390,38 +2996,38 @@ void Scene1337::Action1::signal() {
int i = -1;
for (i = 0; i <= 3; i ++) {
- scene->_arrunkObj1337[3]._arr1[i]._field34 = 0;
- scene->_arrunkObj1337[3]._arr1[i]._object1.remove();
+ scene->_gameBoardSide[3]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[i]._card.remove();
- scene->_arrunkObj1337[2]._arr1[i]._field34 = 0;
- scene->_arrunkObj1337[2]._arr1[i]._object1.remove();
+ scene->_gameBoardSide[2]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[i]._card.remove();
- scene->_arrunkObj1337[0]._arr1[i]._field34 = 0;
- scene->_arrunkObj1337[0]._arr1[i]._object1.remove();
+ scene->_gameBoardSide[0]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[0]._handCard[i]._card.remove();
- scene->_arrunkObj1337[1]._arr1[i]._field34 = 0;
- scene->_arrunkObj1337[1]._arr1[i]._object1.remove();
+ scene->_gameBoardSide[1]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[1]._handCard[i]._card.remove();
}
for (i = 0; i <= 7; i++) {
- scene->_arrunkObj1337[3]._arr2[i]._field34 = 0;
- scene->_arrunkObj1337[3]._arr2[i]._object1.remove();
+ scene->_gameBoardSide[3]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[3]._outpostStation[i]._card.remove();
- scene->_arrunkObj1337[2]._arr2[i]._field34 = 0;
- scene->_arrunkObj1337[2]._arr2[i]._object1.remove();
+ scene->_gameBoardSide[2]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[2]._outpostStation[i]._card.remove();
- scene->_arrunkObj1337[0]._arr2[i]._field34 = 0;
- scene->_arrunkObj1337[0]._arr2[i]._object1.remove();
+ scene->_gameBoardSide[0]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[0]._outpostStation[i]._card.remove();
- scene->_arrunkObj1337[1]._arr2[i]._field34 = 0;
- scene->_arrunkObj1337[1]._arr2[i]._object1.remove();
+ scene->_gameBoardSide[1]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[1]._outpostStation[i]._card.remove();
}
- scene->_arrunkObj1337[2]._arr3[0]._field34 = 0;
- scene->_arrunkObj1337[2]._arr3[0]._object1.remove();
+ scene->_gameBoardSide[2]._delayPile[0]._cardId = 0;
+ scene->_gameBoardSide[2]._delayPile[0]._card.remove();
- scene->_item7._field34 = 0;
- scene->_item7._object1.remove();
+ scene->_discardPile._cardId = 0;
+ scene->_discardPile._card.remove();
scene->_background2.remove();
}
@@ -2439,40 +3045,43 @@ void Scene1337::Action1::signal() {
}
}
+/**
+ * Shuffle cards animation
+ */
void Scene1337::Action2::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
switch (_actionIndex++) {
case 0:
- scene->_item3._object1.postInit();
- scene->_item3._object1.setVisage(1332);
- scene->_item3._object1.setStrip(8);
- scene->_item3._object1.setFrame(1);
- scene->_item3._object1.fixPriority(300);
- scene->_item3._object1.setPosition(Common::Point(156, 108));
+ scene->_shuffleAnimation._card.postInit();
+ scene->_shuffleAnimation._card.setVisage(1332);
+ scene->_shuffleAnimation._card.setStrip(8);
+ scene->_shuffleAnimation._card.setFrame(1);
+ scene->_shuffleAnimation._card.fixPriority(300);
+ scene->_shuffleAnimation._card.setPosition(Common::Point(156, 108));
- scene->_item7._object1.remove();
- scene->_item7._field34 = 0;
+ scene->_discardPile._card.remove();
+ scene->_discardPile._cardId = 0;
scene->_aSound1.play(60);
- scene->_item3._object1.animate(ANIM_MODE_5, this);
+ scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
break;
case 1:
- scene->_item3._object1.setFrame(1);
+ scene->_shuffleAnimation._card.setFrame(1);
scene->_aSound1.play(60);
- scene->_item3._object1.animate(ANIM_MODE_5, this);
+ scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
break;
case 2: {
Common::Point pt(156, 108);
NpcMover *mover = new NpcMover();
- scene->_item3._object1.addMover(mover, &pt, this);
+ scene->_shuffleAnimation._card.addMover(mover, &pt, this);
}
break;
case 3:
- scene->_item3._object1.remove();
+ scene->_shuffleAnimation._card.remove();
scene->_background2.setup2(1332, 5, 1, 162, 95, 110, 1);
- scene->_field423C = 1;
+ scene->_shuffleEndedFl = true;
break;
default:
break;
@@ -2482,268 +3091,268 @@ void Scene1337::Action2::signal() {
void Scene1337::Action3::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
- scene->_item2._object1.setPosition(Common::Point(162, 95), 0);
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
switch (_actionIndex++) {
case 0: {
- scene->_item2._object1._moveDiff = Common::Point(30, 30);
- scene->_item2._object1.setVisage(1332);
- scene->_item2._object1.setStrip(5);
- scene->_item2._object1.setFrame(1);
- scene->_item2._object1.fixPriority(400);
- scene->_item2._object1.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card._moveDiff = Common::Point(30, 30);
+ scene->_animatedCard._card.setVisage(1332);
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.fixPriority(400);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
scene->_aSound2.play(61);
Common::Point pt(283, 146);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_item2._object1.show();
- scene->_arrunkObj1337[1]._arr1[0]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_animatedCard._card.show();
+ scene->_gameBoardSide[1]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 1: {
- scene->_arrunkObj1337[1]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[0]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[0]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[0]._object1.fixPriority(170);
+ scene->_gameBoardSide[1]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(10, 174);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[2]._arr1[0]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[2]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 2: {
- scene->_arrunkObj1337[2]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[0]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[0]._object1.fixPriority(170);
- if (scene->_arrunkObj1337[2]._arr1[0]._field34 > 9) {
- if (scene->_arrunkObj1337[2]._arr1[0]._field34 > 25) {
- scene->_arrunkObj1337[2]._arr1[0]._object1.setStrip(4);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[0]._field34 - 25);
+ scene->_gameBoardSide[2]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
+ if (scene->_gameBoardSide[2]._handCard[0]._cardId > 9) {
+ if (scene->_gameBoardSide[2]._handCard[0]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 25);
} else {
- scene->_arrunkObj1337[2]._arr1[0]._object1.setStrip(3);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[0]._field34 - 9);
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 9);
}
} else {
- scene->_arrunkObj1337[2]._arr1[0]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr1[0]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[0]._field34);
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId);
}
scene->_aSound2.play(61);
Common::Point pt(14, 14);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[3]._arr1[0]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[3]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 3: {
- scene->_arrunkObj1337[3]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[0]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[0]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[0]._object1.fixPriority(170);
+ scene->_gameBoardSide[3]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(280, 5);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[0]._arr1[0]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[0]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 4: {
- scene->_arrunkObj1337[0]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[0]._object1._moveDiff = Common::Point(30,30);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setStrip(5);
- scene->_arrunkObj1337[0]._arr1[0]._object1.setFrame(1);
- scene->_arrunkObj1337[0]._arr1[0]._object1.fixPriority(170);
+ scene->_gameBoardSide[0]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[0]._card._moveDiff = Common::Point(30,30);
+ scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[0]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[0]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(283, 124);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[1]._arr1[1]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[1]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 5: {
- scene->_arrunkObj1337[1]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[1]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[1]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[1]._object1.fixPriority(170);
+ scene->_gameBoardSide[1]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(37, 174);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[2]._arr1[1]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[2]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 6: {
- scene->_arrunkObj1337[2]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[1]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[1]._object1.fixPriority(170);
-
- if (scene->_arrunkObj1337[2]._arr1[1]._field34 > 9) {
- if (scene->_arrunkObj1337[2]._arr1[1]._field34 > 25) {
- scene->_arrunkObj1337[2]._arr1[1]._object1.setStrip(4);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[1]._field34 - 25);
+ scene->_gameBoardSide[2]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
+
+ if (scene->_gameBoardSide[2]._handCard[1]._cardId > 9) {
+ if (scene->_gameBoardSide[2]._handCard[1]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 25);
} else {
- scene->_arrunkObj1337[2]._arr1[1]._object1.setStrip(3);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[1]._field34 - 9);
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 9);
}
} else {
- scene->_arrunkObj1337[2]._arr1[1]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr1[1]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[1]._field34);
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId);
}
scene->_aSound2.play(61);
Common::Point pt(14, 36);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[3]._arr1[1]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[3]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 7: {
- scene->_arrunkObj1337[3]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[1]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[1]._field36);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[1]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[1]._object1.fixPriority(170);
+ scene->_gameBoardSide[3]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos);
+ scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(253, 5);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[0]._arr1[1]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[0]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 8: {
- scene->_arrunkObj1337[0]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[1]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setStrip(5);
- scene->_arrunkObj1337[0]._arr1[1]._object1.setFrame(1);
- scene->_arrunkObj1337[0]._arr1[1]._object1.fixPriority(170);
+ scene->_gameBoardSide[0]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[1]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[1]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(283, 102);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[1]._arr1[2]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[1]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 9: {
- scene->_arrunkObj1337[1]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[1]._arr1[2]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[1]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[1]._arr1[2]._object1.setFrame(4);
- scene->_arrunkObj1337[1]._arr1[2]._object1.fixPriority(170);
+ scene->_gameBoardSide[1]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(64, 174);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[2]._arr1[2]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[2]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 10: {
- scene->_arrunkObj1337[2]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[2]._arr1[2]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[2]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[2]._arr1[2]._object1.fixPriority(170);
-
- if (scene->_arrunkObj1337[2]._arr1[2]._field34 > 9) {
- if (scene->_arrunkObj1337[2]._arr1[2]._field34 > 25) {
- scene->_arrunkObj1337[2]._arr1[2]._object1.setStrip(4);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[2]._field34 - 25);
+ scene->_gameBoardSide[2]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
+
+ if (scene->_gameBoardSide[2]._handCard[2]._cardId > 9) {
+ if (scene->_gameBoardSide[2]._handCard[2]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 25);
} else {
- scene->_arrunkObj1337[2]._arr1[2]._object1.setStrip(3);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[2]._field34 - 9);
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 9);
}
} else {
- scene->_arrunkObj1337[2]._arr1[2]._object1.setStrip(2);
- scene->_arrunkObj1337[2]._arr1[2]._object1.setFrame(scene->_arrunkObj1337[2]._arr1[2]._field34);
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId);
}
scene->_aSound2.play(61);
Common::Point pt(14, 58);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[3]._arr1[2]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[3]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 11: {
- scene->_arrunkObj1337[3]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[3]._arr1[2]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[3]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[3]._arr1[2]._object1.setFrame(3);
- scene->_arrunkObj1337[3]._arr1[2]._object1.fixPriority(170);
+ scene->_gameBoardSide[3]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
scene->_aSound2.play(61);
Common::Point pt(226, 5);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
- scene->_arrunkObj1337[0]._arr1[2]._field34 = scene->_field3E28[scene->_field3E24];
+ scene->_gameBoardSide[0]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
}
break;
case 12:
- scene->_arrunkObj1337[0]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[0]._arr1[2]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[0]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setStrip(5);
- scene->_arrunkObj1337[0]._arr1[2]._object1.setFrame(1);
- scene->_arrunkObj1337[0]._arr1[2]._object1.fixPriority(170);
- scene->_arrunkObj1337[0]._arr1[2]._object1.hide();
+ scene->_gameBoardSide[0]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[2]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[2]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
+ scene->_gameBoardSide[0]._handCard[2]._card.hide();
default:
break;
}
if (_actionIndex > 12) {
- scene->_field423E = 0;
+ scene->_currentPlayerNumb = 0;
R2_GLOBALS._sceneObjects->draw();
scene->actionDisplay(1330, 0, 159, 10, 1, 200, 0, 7, 0, 154, 154);
scene->subC20F9();
} else if (_actionIndex >= 1) {
- scene->_field3E28[scene->_field3E24] = 0;
- scene->_field3E24--;
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
}
}
@@ -2752,21 +3361,21 @@ void Scene1337::Action4::signal() {
switch (_actionIndex++) {
case 0:
- if ((scene->_arrunkObj1337[scene->_field423E]._arr1[0]._field34 == 0) && (scene->subC264B(scene->_arrunkObj1337[scene->_field423E]._arr3[0]._field34))) {
- if (scene->_field3E24 < 0)
- scene->subC264B(scene->_arrunkObj1337[scene->_field423E]._arr3[0]._field34);
- scene->_item2._object1.setPosition(Common::Point(162, 95), 0);
- scene->_item2._object1.show();
+ if ((scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0) && (scene->subC264B(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayPile[0]._cardId))) {
+ if (scene->_cardsAvailableNumb < 0)
+ scene->subC264B(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayPile[0]._cardId);
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
+ scene->_animatedCard._card.show();
scene->_aSound2.play(61);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[scene->_field423E]._fieldB94, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB94, this);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._field34 = scene->_field3E28[scene->_field3E24];
- scene->_field3E28[scene->_field3E24] = 0;
- scene->_field3E24--;
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
- if (scene->_field3E24 < 0)
+ if (scene->_cardsAvailableNumb < 0)
scene->_background2.remove();
} else {
// Self call, forcing next actionIndex
@@ -2774,127 +3383,127 @@ void Scene1337::Action4::signal() {
}
break;
case 1:
- if ( ( scene->_item2._object1._position.x == scene->_arrunkObj1337[scene->_field423E]._fieldB94.x)
- && ( scene->_item2._object1._position.y == scene->_arrunkObj1337[scene->_field423E]._fieldB94.y) ) {
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.postInit();
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.setVisage(1332);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.setPosition(scene->_arrunkObj1337[scene->_field423E]._arr1[0]._field36, 0);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.setStrip(1);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.setFrame(scene->_arrunkObj1337[scene->_field423E]._fieldBA4);
- scene->_arrunkObj1337[scene->_field423E]._arr1[0]._object1.fixPriority(170);
- }
-
- if ((scene->_field4248 == 1) || (scene->_field423E == 2))
- scene->setAnimationInfo(&scene->_arrunkObj1337[scene->_field423E]._arr1[0]);
-
- scene->_item2._object1.hide();
- if ((scene->_arrunkObj1337[scene->_field423E]._arr1[0]._field34 == 0) && (scene->subC264B(scene->_arrunkObj1337[scene->_field423E]._arr3[0]._field34 == 0))) {
- if (scene->_field3E24 < 0)
+ if ( ( scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB94.x)
+ && ( scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB94.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA4);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.fixPriority(170);
+ }
+
+ if ((scene->_field4248 == 1) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]);
+
+ scene->_animatedCard._card.hide();
+ if ((scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0) && (scene->subC264B(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayPile[0]._cardId == 0))) {
+ if (scene->_cardsAvailableNumb < 0)
scene->shuffleCards();
- scene->_item2._object1.setPosition(Common::Point(162, 95));
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
scene->_aSound2.play(61);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[scene->_field423E]._fieldB98, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB98, this);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._field34 = scene->_field3E28[scene->_field3E24];
- scene->_field3E28[scene->_field3E24] = 0;
- scene->_field3E24--;
- if (scene->_field3E24 < 0)
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
scene->_background2.remove();
} else
signal();
break;
case 2:
- if ( ( scene->_item2._object1._position.x == scene->_arrunkObj1337[scene->_field423E]._fieldB98.x)
- && ( scene->_item2._object1._position.y == scene->_arrunkObj1337[scene->_field423E]._fieldB98.y) ) {
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.postInit();
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.setVisage(1332);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.setPosition(scene->_arrunkObj1337[scene->_field423E]._arr1[1]._field36, 0);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.setStrip(1);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.setFrame(scene->_arrunkObj1337[scene->_field423E]._fieldBA4);
- scene->_arrunkObj1337[scene->_field423E]._arr1[1]._object1.fixPriority(170);
- }
-
- if ((scene->_field4248 == 1) || (scene->_field423E == 2))
- scene->setAnimationInfo(&scene->_arrunkObj1337[scene->_field423E]._arr1[1]);
-
- scene->_item2._object1.hide();
- if ((scene->_arrunkObj1337[scene->_field423E]._arr1[2]._field34 == 0) && (scene->subC264B(scene->_arrunkObj1337[scene->_field423E]._arr3[0]._field34 == 0))) {
- if (scene->_field3E24 < 0)
+ if ( ( scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB98.x)
+ && ( scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB98.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA4);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.fixPriority(170);
+ }
+
+ if ((scene->_field4248 == 1) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]);
+
+ scene->_animatedCard._card.hide();
+ if ((scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId == 0) && (scene->subC264B(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayPile[0]._cardId == 0))) {
+ if (scene->_cardsAvailableNumb < 0)
scene->shuffleCards();
- scene->_item2._object1.setPosition(Common::Point(162, 95));
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
scene->_aSound2.play(61);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[scene->_field423E]._fieldB9C, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB9C, this);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._field34 = scene->_field3E28[scene->_field3E24];
- scene->_field3E28[scene->_field3E24] = 0;
- scene->_field3E24--;
- if (scene->_field3E24 < 0)
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
scene->_background2.remove();
} else
signal();
break;
case 3:
- if ( ( scene->_item2._object1._position.x == scene->_arrunkObj1337[scene->_field423E]._fieldB9C.x)
- && ( scene->_item2._object1._position.y == scene->_arrunkObj1337[scene->_field423E]._fieldB9C.y) ) {
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.postInit();
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.setVisage(1332);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.setPosition(scene->_arrunkObj1337[scene->_field423E]._arr1[2]._field36, 0);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.setStrip(1);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.setFrame(scene->_arrunkObj1337[scene->_field423E]._fieldBA4);
- scene->_arrunkObj1337[scene->_field423E]._arr1[2]._object1.fixPriority(170);
- }
-
- if ((scene->_field4248 == 1) || (scene->_field423E == 2))
- scene->setAnimationInfo(&scene->_arrunkObj1337[scene->_field423E]._arr1[2]);
-
- scene->_item2._object1.hide();
- if ((scene->_arrunkObj1337[scene->_field423E]._arr1[3]._field34 == 0) && (scene->subC264B(scene->_arrunkObj1337[scene->_field423E]._arr3[0]._field34 == 0))) {
- if (scene->_field3E24 < 0)
+ if ( ( scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB9C.x)
+ && ( scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldB9C.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA4);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.fixPriority(170);
+ }
+
+ if ((scene->_field4248 == 1) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]);
+
+ scene->_animatedCard._card.hide();
+ if ((scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId == 0) && (scene->subC264B(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayPile[0]._cardId == 0))) {
+ if (scene->_cardsAvailableNumb < 0)
scene->shuffleCards();
- scene->_item2._object1.setPosition(Common::Point(162, 95));
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
scene->_aSound2.play(61);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_arrunkObj1337[scene->_field423E]._fieldBA0, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA0, this);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._field34 = scene->_field3E28[scene->_field3E24];
- scene->_field3E28[scene->_field3E24] = 0;
- scene->_field3E24--;
- if (scene->_field3E24 < 0)
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
scene->_background2.remove();
} else
signal();
break;
case 4:
- if ( ( scene->_item2._object1._position.x == scene->_arrunkObj1337[scene->_field423E]._fieldBA0.x)
- && ( scene->_item2._object1._position.y == scene->_arrunkObj1337[scene->_field423E]._fieldBA0.y) ) {
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.postInit();
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1._moveDiff = Common::Point(30, 30);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.setVisage(1332);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.setPosition(scene->_arrunkObj1337[scene->_field423E]._arr1[3]._field36, 0);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.setStrip(1);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.setFrame(scene->_arrunkObj1337[scene->_field423E]._fieldBA4);
- scene->_arrunkObj1337[scene->_field423E]._arr1[3]._object1.fixPriority(170);
- }
-
- if ((scene->_field4248 == 1) || (scene->_field423E == 2))
- scene->setAnimationInfo(&scene->_arrunkObj1337[scene->_field423E]._arr1[3]);
-
- scene->_item2._object1.hide();
- switch (scene->_field423E) {
+ if ( ( scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA0.x)
+ && ( scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA0.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._fieldBA4);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.fixPriority(170);
+ }
+
+ if ((scene->_field4248 == 1) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]);
+
+ scene->_animatedCard._card.hide();
+ switch (scene->_currentPlayerNumb) {
case 0:
scene->subCF979();
break;
@@ -2921,34 +3530,34 @@ void Scene1337::Action5::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3E28[scene->_field3E26] = scene->_field3EF0->_field34;
+ scene->_availableCardsPile[scene->_field3E26] = scene->_field3EF0->_cardId;
scene->_field3E26--;
- if (!g_globals->_sceneObjects->contains(&scene->_item7._object1)) {
- scene->_item7._object1.postInit();
- scene->_item7._object1.hide();
- scene->_item7._object1.setVisage(1332);
- scene->_item7._object1.setPosition(scene->_item7._field36, 0);
- scene->_item7._object1.fixPriority(170);
+ if (!g_globals->_sceneObjects->contains(&scene->_discardPile._card)) {
+ scene->_discardPile._card.postInit();
+ scene->_discardPile._card.hide();
+ scene->_discardPile._card.setVisage(1332);
+ scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
+ scene->_discardPile._card.fixPriority(170);
}
- scene->_item7._field34 = scene->_field3EF0->_field34;
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_discardPile._cardId = scene->_field3EF0->_cardId;
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
Common::Point pt(128, 95);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &pt, this);
+ scene->_animatedCard._card.addMover(mover, &pt, this);
}
break;
case 1:
- scene->_item2._object1.hide();
- scene->setAnimationInfo(&scene->_item7);
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
scene->_aSound2.play(61);
scene->subC20F9();
break;
@@ -2962,29 +3571,29 @@ void Scene1337::Action6::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3EF4->_field34 = 1;
- scene->_field3EF4->_object1.postInit();
- scene->_field3EF4->_object1.hide();
- scene->_field3EF4->_object1.setVisage(1332);
- scene->_field3EF4->_object1.setPosition(scene->_field3EF4->_field36);
- scene->_field3EF4->_object1.fixPriority(170);
+ scene->_field3EF4->_cardId = 1;
+ scene->_field3EF4->_card.postInit();
+ scene->_field3EF4->_card.hide();
+ scene->_field3EF4->_card.setVisage(1332);
+ scene->_field3EF4->_card.setPosition(scene->_field3EF4->_stationPos);
+ scene->_field3EF4->_card.fixPriority(170);
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(59);
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
scene->subC20F9();
@@ -2999,30 +3608,30 @@ void Scene1337::Action7::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3EF4->_field34 = scene->_field3EF0->_field34;
+ scene->_field3EF4->_cardId = scene->_field3EF0->_cardId;
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1:
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(59);
- scene->_item5._field34 = 1;
- scene->_item5._field36.x = scene->_field3EF4->_field36.x;
- scene->_item5._field36.y = scene->_field3EF4->_field36.y;
- scene->_item5._object1.postInit();
- scene->_item5._object1.hide();
- scene->_item5._object1._flags = 0x200;
+ scene->_item5._cardId = 1;
+ scene->_item5._stationPos.x = scene->_field3EF4->_stationPos.x;
+ scene->_item5._stationPos.y = scene->_field3EF4->_stationPos.y;
+ scene->_item5._card.postInit();
+ scene->_item5._card.hide();
+ scene->_item5._card._flags = 0x200;
scene->subC4A39(&scene->_item5);
break;
@@ -3036,24 +3645,24 @@ void Scene1337::Action8::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3E28[scene->_field3E26] = scene->_field3EF4->_field34;
+ scene->_availableCardsPile[scene->_field3E26] = scene->_field3EF4->_cardId;
scene->_field3E26--;
- scene->_field3EF4->_field34 = scene->_field3EF0->_field34;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF4->_cardId = scene->_field3EF0->_cardId;
+ scene->_field3EF0->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
scene->setAnimationInfo(scene->_field3EF4);
@@ -3070,30 +3679,30 @@ void Scene1337::Action9::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3EF4->_field34 = scene->_field3EF0->_field34;
- scene->_field3EF4->_object1.postInit();
- scene->_field3EF4->_object1.hide();
- scene->_field3EF4->_object1.setVisage(1332);
- scene->_field3EF4->_object1.setPosition(scene->_field3EF4->_field36, 0);
- scene->_field3EF4->_object1.fixPriority(170);
+ scene->_field3EF4->_cardId = scene->_field3EF0->_cardId;
+ scene->_field3EF4->_card.postInit();
+ scene->_field3EF4->_card.hide();
+ scene->_field3EF4->_card.setVisage(1332);
+ scene->_field3EF4->_card.setPosition(scene->_field3EF4->_stationPos, 0);
+ scene->_field3EF4->_card.fixPriority(170);
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(57);
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
@@ -3109,29 +3718,29 @@ void Scene1337::Action10::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3EF8->_object1.postInit();
- scene->_field3EF8->_object1.hide();
- scene->_field3EF8->_object1.setVisage(1332);
- scene->_field3EF8->_object1.setPosition(scene->_field3EF8->_field36, 0);
- scene->_field3EF8->_object1.fixPriority(170);
- scene->_field3EF8->_field34 = scene->_field3EF0->_field34;
+ scene->_field3EF8->_card.postInit();
+ scene->_field3EF8->_card.hide();
+ scene->_field3EF8->_card.setVisage(1332);
+ scene->_field3EF8->_card.setPosition(scene->_field3EF8->_stationPos, 0);
+ scene->_field3EF8->_card.fixPriority(170);
+ scene->_field3EF8->_cardId = scene->_field3EF0->_cardId;
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
if (scene->_field3EF0 == &scene->_item6) {
- subD18B5(5, 1, 4);
+ scene->setCursorData(5, 1, 4);
scene->subC4CEC();
}
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF8->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF8->_stationPos, this);
}
break;
case 1: {
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF8);
scene->_aSound1.play(57);
@@ -3141,7 +3750,7 @@ void Scene1337::Action10::signal() {
switch (scene->_field4240) {
case 0:
for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_arrunkObj1337[0]._arr1[indexFound]._field34 == 29) {
+ if (scene->_gameBoardSide[0]._handCard[indexFound]._cardId == 29) {
found = true;
break;
}
@@ -3149,7 +3758,7 @@ void Scene1337::Action10::signal() {
break;
case 1:
for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_arrunkObj1337[1]._arr1[indexFound]._field34 == 29) {
+ if (scene->_gameBoardSide[1]._handCard[indexFound]._cardId == 29) {
found = true;
break;
}
@@ -3157,7 +3766,7 @@ void Scene1337::Action10::signal() {
break;
case 2:
for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_arrunkObj1337[2]._arr1[indexFound]._field34 == 29) {
+ if (scene->_gameBoardSide[2]._handCard[indexFound]._cardId == 29) {
found = true;
break;
}
@@ -3165,7 +3774,7 @@ void Scene1337::Action10::signal() {
break;
case 3:
for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_arrunkObj1337[3]._arr1[indexFound]._field34 == 29) {
+ if (scene->_gameBoardSide[3]._handCard[indexFound]._cardId == 29) {
found = true;
break;
}
@@ -3180,11 +3789,11 @@ void Scene1337::Action10::signal() {
if (found) {
switch (scene->_field4240) {
case 0:
- scene->subC51A0(&scene->_arrunkObj1337[0]._arr1[indexFound], scene->_field3EF8);
+ scene->subC51A0(&scene->_gameBoardSide[0]._handCard[indexFound], scene->_field3EF8);
found2 = true;
break;
case 1:
- scene->subC51A0(&scene->_arrunkObj1337[1]._arr1[indexFound], scene->_field3EF8);
+ scene->subC51A0(&scene->_gameBoardSide[1]._handCard[indexFound], scene->_field3EF8);
found2 = true;
break;
case 2:
@@ -3192,12 +3801,12 @@ void Scene1337::Action10::signal() {
if (MessageDialog::show(USE_INTERCEPTOR, NO_MSG, YES_MSG) == 0)
scene->subC4CEC();
else {
- scene->subC51A0(&scene->_arrunkObj1337[2]._arr1[indexFound], scene->_field3EF8);
+ scene->subC51A0(&scene->_gameBoardSide[2]._handCard[indexFound], scene->_field3EF8);
found2 = true;
}
break;
case 3:
- scene->subC51A0(&scene->_arrunkObj1337[3]._arr1[indexFound], scene->_field3EF8);
+ scene->subC51A0(&scene->_gameBoardSide[3]._handCard[indexFound], scene->_field3EF8);
found2 = true;
break;
default:
@@ -3211,14 +3820,14 @@ void Scene1337::Action10::signal() {
if (scene->_field4240 == 2) {
int j = 0;
for (int i = 0; i <= 7; i++) {
- if (scene->_arrunkObj1337[2]._arr2[i]._field34 != 0)
+ if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)
++j;
}
if (j <= 1) {
for (int i = 0; i <= 7; i++) {
- if (scene->_arrunkObj1337[2]._arr2[i]._field34 != 0) {
- scene->_field3EF4 = &scene->_arrunkObj1337[2]._arr2[i];
+ if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
+ scene->_field3EF4 = &scene->_gameBoardSide[2]._outpostStation[i];
break;
}
}
@@ -3237,11 +3846,11 @@ void Scene1337::Action10::signal() {
g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
}
- scene->_item6._field36 = event.mousePos;
+ scene->_item6._stationPos = event.mousePos;
for (int i = 0; i <= 7; i++) {
- if ((scene->subC2BF8(&scene->_arrunkObj1337[2]._arr2[i], scene->_item6._field36) != 0) && (scene->_arrunkObj1337[2]._arr2[i]._field34 != 0)) {
- scene->_field3EF4 = &scene->_arrunkObj1337[2]._arr2[0];
+ if ((scene->subC2BF8(&scene->_gameBoardSide[2]._outpostStation[i], scene->_item6._stationPos) != 0) && (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)) {
+ scene->_field3EF4 = &scene->_gameBoardSide[2]._outpostStation[0];
found2 = true;
break;
}
@@ -3251,20 +3860,20 @@ void Scene1337::Action10::signal() {
}
}
- scene->_field3E28[scene->_field3E26] = scene->_field3EF4->_field34;
+ scene->_availableCardsPile[scene->_field3E26] = scene->_field3EF4->_cardId;
scene->_field3E26--;
- scene->_field3EF4->_field34 = 0;
- scene->_field3EF4->_object1.remove();
+ scene->_field3EF4->_cardId = 0;
+ scene->_field3EF4->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF4->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF4->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF8->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF8->_stationPos, this);
}
break;
case 2:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->subC4A39(scene->_field3EF8);
break;
default:
@@ -3279,29 +3888,29 @@ void Scene1337::Action11::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3EF4->_object1.postInit();
- scene->_field3EF4->_object1.hide();
- scene->_field3EF4->_object1.setVisage(1332);
- scene->_field3EF4->_object1.setPosition(scene->_field3EF4->_field36, 0);
- scene->_field3EF4->_object1.fixPriority(170);
- scene->_field3EF4->_field34 = 25;
+ scene->_field3EF4->_card.postInit();
+ scene->_field3EF4->_card.hide();
+ scene->_field3EF4->_card.setVisage(1332);
+ scene->_field3EF4->_card.setPosition(scene->_field3EF4->_stationPos, 0);
+ scene->_field3EF4->_card.fixPriority(170);
+ scene->_field3EF4->_cardId = 25;
if (scene->_field4240 == 2) {
- scene->_item2._object1.setPosition(scene->_field3EF4->_field36, 0);
- subD18B5(5, 1, 4);
+ scene->_animatedCard._card.setPosition(scene->_field3EF4->_stationPos, 0);
+ scene->setCursorData(5, 1, 4);
} else {
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
}
- scene->_item2._object1.show();
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1: {
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(57);
@@ -3311,18 +3920,18 @@ void Scene1337::Action11::signal() {
switch (scene->_field4242) {
case 0:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[0]._arr1[i]._field34 == 27) {
+ if (scene->_gameBoardSide[0]._handCard[i]._cardId == 27) {
found = true;
break;
}
}
if ((found) && (scene->subC3E92(scene->_field4240) != -1)) {
- scene->_field3EF0 = &scene->_arrunkObj1337[0]._arr1[i];
- scene->_field3EF4 = &scene->_arrunkObj1337[0]._arr4[0];
+ scene->_field3EF0 = &scene->_gameBoardSide[0]._handCard[i];
+ scene->_field3EF4 = &scene->_gameBoardSide[0]._arr4[0];
if (scene->_field4240 != 0) {
int tmpVal = scene->subC3E92(scene->_field4240);
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4240]._arr1[tmpVal];
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4240]._handCard[tmpVal];
}
scene->_item1.setAction(&scene->_action12);
noAction = false;
@@ -3330,18 +3939,18 @@ void Scene1337::Action11::signal() {
break;
case 1:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[1]._arr1[i]._field34 == 27) {
+ if (scene->_gameBoardSide[1]._handCard[i]._cardId == 27) {
found = true;
break;
}
}
if ((found) && (scene->subC3E92(scene->_field4240) != -1)) {
- scene->_field3EF0 = &scene->_arrunkObj1337[1]._arr1[i];
- scene->_field3EF4 = &scene->_arrunkObj1337[1]._arr4[0];
+ scene->_field3EF0 = &scene->_gameBoardSide[1]._handCard[i];
+ scene->_field3EF4 = &scene->_gameBoardSide[1]._arr4[0];
if (scene->_field4240 != 1) {
int tmpVal = scene->subC3E92(scene->_field4240);
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4240]._arr1[tmpVal];
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4240]._handCard[tmpVal];
}
scene->_item1.setAction(&scene->_action12);
noAction = false;
@@ -3349,7 +3958,7 @@ void Scene1337::Action11::signal() {
break;
case 2:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[2]._arr1[i]._field34 == 27) {
+ if (scene->_gameBoardSide[2]._handCard[i]._cardId == 27) {
found = true;
break;
}
@@ -3361,11 +3970,11 @@ void Scene1337::Action11::signal() {
scene->subC4CEC();
else {
scene->subC4CEC();
- scene->_field3EF0 = &scene->_arrunkObj1337[2]._arr1[i];
- scene->_field3EF4 = &scene->_arrunkObj1337[2]._arr4[0];
+ scene->_field3EF0 = &scene->_gameBoardSide[2]._handCard[i];
+ scene->_field3EF4 = &scene->_gameBoardSide[2]._arr4[0];
if (scene->_field4240 != 2) {
int tmpVal = scene->subC3E92(scene->_field4240);
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4240]._arr1[tmpVal];
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4240]._handCard[tmpVal];
}
scene->_item1.setAction(&scene->_action12);
noAction = false;
@@ -3374,18 +3983,18 @@ void Scene1337::Action11::signal() {
break;
case 3:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[3]._arr1[i]._field34 == 27) {
+ if (scene->_gameBoardSide[3]._handCard[i]._cardId == 27) {
found = true;
break;
}
}
if ((found) && (scene->subC3E92(scene->_field4240) != -1)) {
- scene->_field3EF0 = &scene->_arrunkObj1337[3]._arr1[i];
- scene->_field3EF4 = &scene->_arrunkObj1337[3]._arr4[0];
+ scene->_field3EF0 = &scene->_gameBoardSide[3]._handCard[i];
+ scene->_field3EF4 = &scene->_gameBoardSide[3]._arr4[0];
if (scene->_field4240 != 3) {
int tmpVal = scene->subC3E92(scene->_field4240);
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4240]._arr1[tmpVal];
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4240]._handCard[tmpVal];
}
scene->_item1.setAction(&scene->_action12);
noAction = false;
@@ -3402,7 +4011,7 @@ void Scene1337::Action11::signal() {
int count = 0;
if (scene->_field4242 != 2) {
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[scene->_field4242]._arr1[i]._field34 == 0)
+ if (scene->_gameBoardSide[scene->_field4242]._handCard[i]._cardId == 0)
++count;
}
}
@@ -3433,74 +4042,70 @@ void Scene1337::Action11::signal() {
g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
}
- scene->_item6._field36 = event.mousePos;
+ scene->_item6._stationPos = event.mousePos;
found = false;
if (scene->_field4242 != 2) {
for (i = 0; i <= 3; i++) {
- if ((scene->subC2BF8(&scene->_arrunkObj1337[scene->_field4242]._arr1[i], scene->_item6._field36) != 0) && (scene->_arrunkObj1337[scene->_field4242]._arr1[i]._field34 != 0)) {
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4242]._arr1[i];
+ if ((scene->subC2BF8(&scene->_gameBoardSide[scene->_field4242]._handCard[i], scene->_item6._stationPos) != 0) && (scene->_gameBoardSide[scene->_field4242]._handCard[i]._cardId != 0)) {
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4242]._handCard[i];
found = true;
break;
}
}
}
} // while
- scene->_field4246 = 1;
+ scene->_field4246 = true;
scene->subC4CEC();
} else {
if (scene->_field4242 != 2) {
int tmpVal = scene->subC3E92(scene->_field4242);
- scene->_field3EF8 = &scene->_arrunkObj1337[scene->_field4242]._arr1[tmpVal];
+ scene->_field3EF8 = &scene->_gameBoardSide[scene->_field4242]._handCard[tmpVal];
}
}
}
- scene->_field3EF0->_object1.postInit();
- scene->_field3EF0->_object1.hide();
- scene->_field3EF0->_object1.setVisage(1332);
- scene->_field3EF0->_object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_field3EF0->_object1.fixPriority(170);
- scene->_field3EF0->_object1.setStrip2(1);
- scene->_field3EF0->_field34 = scene->_field3EF8->_field34;
+ scene->_field3EF0->_card.postInit();
+ scene->_field3EF0->_card.hide();
+ scene->_field3EF0->_card.setVisage(1332);
+ scene->_field3EF0->_card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_field3EF0->_card.fixPriority(170);
+ scene->_field3EF0->_card.setStrip2(1);
+ scene->_field3EF0->_cardId = scene->_field3EF8->_cardId;
- scene->_field3EF8->_field34 = 0;
- scene->_field3EF8->_object1.remove();
+ scene->_field3EF8->_cardId = 0;
+ scene->_field3EF8->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF8->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF8->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF0->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF0->_stationPos, this);
}
break;
case 2:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
switch (scene->_field4240) {
case 0:
- scene->_field3EF0->_object1.setFrame(2);
- scene->_field3EF0->_object1.show();
- scene->_field423E--;
- scene->_field4244 = 0;
+ scene->_field3EF0->_card.setFrame(2);
+ scene->_field3EF0->_card.show();
break;
case 1:
- scene->_field3EF0->_object1.setFrame(4);
- scene->_field3EF0->_object1.show();
- scene->_field423E--;
- scene->_field4244 = 0;
+ scene->_field3EF0->_card.setFrame(4);
+ scene->_field3EF0->_card.show();
break;
case 3:
- scene->_field3EF0->_object1.setFrame(3);
- scene->_field3EF0->_object1.show();
- scene->_field423E--;
- scene->_field4244 = 0;
+ scene->_field3EF0->_card.setFrame(3);
+ scene->_field3EF0->_card.show();
break;
default:
scene->setAnimationInfo(scene->_field3EF0);
break;
}
+ scene->_currentPlayerNumb--;
+ scene->_field4244 = false;
scene->subC4A39(scene->_field3EF4);
break;
default:
@@ -3516,19 +4121,19 @@ void Scene1337::Action12::signal() {
signal();
break;
case 1: {
- scene->_field3E28[scene->_field3E26] = scene->_field3EF4->_field34;
- scene->_field3EF4->_field34 = scene->_field3EF0->_field34;
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_availableCardsPile[scene->_field3E26] = scene->_field3EF4->_cardId;
+ scene->_field3EF4->_cardId = scene->_field3EF0->_cardId;
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 2:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(58);
if (scene->_field4242 == 2) {
@@ -3537,19 +4142,19 @@ void Scene1337::Action12::signal() {
switch (scene->_field4240) {
case 0:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[0]._arr1[i]._field34 != 0)
+ if (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)
++count;
}
break;
case 1:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[3]._arr1[i]._field34 != 0)
+ if (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)
++count;
}
break;
case 3:
for (i = 0; i <= 3; i++) {
- if (scene->_arrunkObj1337[3]._arr1[i]._field34 != 0)
+ if (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)
++count;
}
break;
@@ -3584,13 +4189,13 @@ void Scene1337::Action12::signal() {
g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
}
- scene->_item6._field36 = event.mousePos;
+ scene->_item6._stationPos = event.mousePos;
if (scene->_field4240 == 0) {
for (i = 0; i <= 3; i++) {
- if ((scene->subC2BF8(&scene->_arrunkObj1337[0]._arr1[i], scene->_item6._field36) != 0) && (scene->_arrunkObj1337[0]._arr1[i]._field34 != 0)) {
+ if ((scene->subC2BF8(&scene->_gameBoardSide[0]._handCard[i], scene->_item6._stationPos) != 0) && (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)) {
found = true;
- scene->_field3EF8 = &scene->_arrunkObj1337[0]._arr1[i];
+ scene->_field3EF8 = &scene->_gameBoardSide[0]._handCard[i];
break;
}
}
@@ -3598,9 +4203,9 @@ void Scene1337::Action12::signal() {
if (scene->_field4240 == 3) {
for (i = 0; i <= 3; i++) {
- if ((scene->subC2BF8(&scene->_arrunkObj1337[3]._arr1[i], scene->_item6._field36) != 0) && (scene->_arrunkObj1337[3]._arr1[i]._field34 != 0)) {
+ if ((scene->subC2BF8(&scene->_gameBoardSide[3]._handCard[i], scene->_item6._stationPos) != 0) && (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)) {
found = true;
- scene->_field3EF8 = &scene->_arrunkObj1337[3]._arr1[i];
+ scene->_field3EF8 = &scene->_gameBoardSide[3]._handCard[i];
break;
}
}
@@ -3608,9 +4213,9 @@ void Scene1337::Action12::signal() {
if (scene->_field4240 == 1) {
for (i = 0; i <= 3; i++) {
- if ((scene->subC2BF8(&scene->_arrunkObj1337[1]._arr1[i], scene->_item6._field36) != 0) && (scene->_arrunkObj1337[1]._arr1[i]._field34 != 0)) {
+ if ((scene->subC2BF8(&scene->_gameBoardSide[1]._handCard[i], scene->_item6._stationPos) != 0) && (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)) {
found = true;
- scene->_field3EF8 = &scene->_arrunkObj1337[1]._arr1[i];
+ scene->_field3EF8 = &scene->_gameBoardSide[1]._handCard[i];
break;
}
}
@@ -3621,52 +4226,52 @@ void Scene1337::Action12::signal() {
if (scene->_field4240 != 1) {
switch (scene->_field4240) {
case 0:
- scene->_field3EF8 = &scene->_arrunkObj1337[0]._arr1[scene->subC3E92(0)];
+ scene->_field3EF8 = &scene->_gameBoardSide[0]._handCard[scene->subC3E92(0)];
break;
case 3:
- scene->_field3EF8 = &scene->_arrunkObj1337[3]._arr1[scene->subC3E92(3)];
+ scene->_field3EF8 = &scene->_gameBoardSide[3]._handCard[scene->subC3E92(3)];
break;
default:
break;
}
} else {
- scene->_field3EF8 = &scene->_arrunkObj1337[1]._arr1[scene->subC3E92(1)];
+ scene->_field3EF8 = &scene->_gameBoardSide[1]._handCard[scene->subC3E92(1)];
}
}
- scene->_field3EF0->_object1.postInit();
- scene->_field3EF0->_object1.hide();
- scene->_field3EF0->_object1.setVisage(1332);
- scene->_field3EF0->_object1.setPosition(scene->_field3EF0->_field36);
- scene->_field3EF0->_object1.fixPriority(170);
- scene->_field3EF0->_object1.setStrip2(1);
- scene->_field3EF0->_field34 = scene->_field3EF8->_field34;
+ scene->_field3EF0->_card.postInit();
+ scene->_field3EF0->_card.hide();
+ scene->_field3EF0->_card.setVisage(1332);
+ scene->_field3EF0->_card.setPosition(scene->_field3EF0->_stationPos);
+ scene->_field3EF0->_card.fixPriority(170);
+ scene->_field3EF0->_card.setStrip2(1);
+ scene->_field3EF0->_cardId = scene->_field3EF8->_cardId;
- scene->_field3EF8->_field34 = 0;
- scene->_field3EF8->_object1.remove();
+ scene->_field3EF8->_cardId = 0;
+ scene->_field3EF8->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF8->_field36);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF8->_stationPos);
+ scene->_animatedCard._card.show();
scene->_aSound1.play(57);
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF0->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF0->_stationPos, this);
}
break;
case 3:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
switch (scene->_field4242) {
case 0:
- scene->_field3EF0->_object1.setFrame2(2);
- scene->_field3EF0->_object1.show();
+ scene->_field3EF0->_card.setFrame2(2);
+ scene->_field3EF0->_card.show();
break;
case 1:
- scene->_field3EF0->_object1.setFrame2(4);
- scene->_field3EF0->_object1.show();
+ scene->_field3EF0->_card.setFrame2(4);
+ scene->_field3EF0->_card.show();
break;
case 3:
- scene->_field3EF0->_object1.setFrame2(3);
- scene->_field3EF0->_object1.show();
+ scene->_field3EF0->_card.setFrame2(3);
+ scene->_field3EF0->_card.show();
break;
default:
scene->setAnimationInfo(scene->_field3EF0);
@@ -3684,23 +4289,23 @@ void Scene1337::Action13::signal() {
switch (_actionIndex++) {
case 0: {
- scene->_field3E28[scene->_field3E26] = scene->_field3EF4->_field34;
+ scene->_availableCardsPile[scene->_field3E26] = scene->_field3EF4->_cardId;
scene->_field3E26--;
- scene->_field3EF4->_field34 = scene->_field3EF0->_field34;
+ scene->_field3EF4->_cardId = scene->_field3EF0->_cardId;
- scene->_field3EF0->_field34 = 0;
- scene->_field3EF0->_object1.remove();
+ scene->_field3EF0->_cardId = 0;
+ scene->_field3EF0->_card.remove();
- scene->_item2._object1.setPosition(scene->_field3EF0->_field36, 0);
- scene->_item2._object1.show();
+ scene->_animatedCard._card.setPosition(scene->_field3EF0->_stationPos, 0);
+ scene->_animatedCard._card.show();
NpcMover *mover = new NpcMover();
- scene->_item2._object1.addMover(mover, &scene->_field3EF4->_field36, this);
+ scene->_animatedCard._card.addMover(mover, &scene->_field3EF4->_stationPos, this);
}
break;
case 1:
- scene->_item2._object1.hide();
+ scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_field3EF4);
scene->_aSound1.play(58);
signal();
@@ -3717,12 +4322,12 @@ void Scene1337::postInit(SceneObjectList *OwnerList) {
// In the original, may be found in subPostInit.
// Without it, enableControl asserts
loadScene(1330);
+ R2_GLOBALS._uiElements._active = false;
SceneExt::postInit();
//
// Hide the user interface
- R2_GLOBALS._uiElements._active = false;
- BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
@@ -3733,101 +4338,101 @@ void Scene1337::postInit(SceneObjectList *OwnerList) {
_field3EF4 = NULL;
_field3EF8 = NULL;
- _arrunkObj1337[2]._arr1[0]._field36 = Common::Point(10, 174);
- _arrunkObj1337[2]._arr1[1]._field36 = Common::Point(37, 174);
- _arrunkObj1337[2]._arr1[2]._field36 = Common::Point(64, 174);
- _arrunkObj1337[2]._arr1[3]._field36 = Common::Point(91, 174);
-
- _arrunkObj1337[2]._arr2[0]._field36 = Common::Point(119, 174);
- _arrunkObj1337[2]._arr2[1]._field36 = Common::Point(119, 148);
- _arrunkObj1337[2]._arr2[2]._field36 = Common::Point(119, 122);
- _arrunkObj1337[2]._arr2[3]._field36 = Common::Point(145, 122);
- _arrunkObj1337[2]._arr2[4]._field36 = Common::Point(171, 122);
- _arrunkObj1337[2]._arr2[5]._field36 = Common::Point(171, 148);
- _arrunkObj1337[2]._arr2[6]._field36 = Common::Point(171, 174);
- _arrunkObj1337[2]._arr2[7]._field36 = Common::Point(145, 174);
-
- _arrunkObj1337[2]._arr3[0]._field36 = Common::Point(199, 174);
-
- _arrunkObj1337[2]._arr4[0]._field36 = Common::Point(145, 148);
-
- _arrunkObj1337[2]._fieldB94 = Common::Point(10, 174);
- _arrunkObj1337[2]._fieldB98 = Common::Point(37, 174);
- _arrunkObj1337[2]._fieldB9C = Common::Point(64, 174);
- _arrunkObj1337[2]._fieldBA0 = Common::Point(91, 174);
- _arrunkObj1337[2]._fieldBA4 = 2;
-
- _arrunkObj1337[3]._arr1[0]._field36 = Common::Point(14, 14);
- _arrunkObj1337[3]._arr1[1]._field36 = Common::Point(14, 36);
- _arrunkObj1337[3]._arr1[2]._field36 = Common::Point(14, 58);
- _arrunkObj1337[3]._arr1[3]._field36 = Common::Point(14, 80);
-
- _arrunkObj1337[3]._arr2[0]._field36 = Common::Point(37, 66);
- _arrunkObj1337[3]._arr2[1]._field36 = Common::Point(63, 66);
- _arrunkObj1337[3]._arr2[2]._field36 = Common::Point(89, 66);
- _arrunkObj1337[3]._arr2[3]._field36 = Common::Point(89, 92);
- _arrunkObj1337[3]._arr2[4]._field36 = Common::Point(89, 118);
- _arrunkObj1337[3]._arr2[5]._field36 = Common::Point(63, 118);
- _arrunkObj1337[3]._arr2[6]._field36 = Common::Point(37, 118);
- _arrunkObj1337[3]._arr2[7]._field36 = Common::Point(37, 92);
-
- _arrunkObj1337[3]._arr3[0]._field36 = Common::Point(37, 145);
-
- _arrunkObj1337[3]._arr4[0]._field36 = Common::Point(63, 92);
-
- _arrunkObj1337[3]._fieldB94 = Common::Point(14, 14);
- _arrunkObj1337[3]._fieldB98 = Common::Point(14, 36);
- _arrunkObj1337[3]._fieldB9C = Common::Point(14, 58);
- _arrunkObj1337[3]._fieldBA0 = Common::Point(14, 80);
- _arrunkObj1337[3]._fieldBA4 = 3;
-
- _arrunkObj1337[0]._arr1[0]._field36 = Common::Point(280, 5);
- _arrunkObj1337[0]._arr1[1]._field36 = Common::Point(253, 5);
- _arrunkObj1337[0]._arr1[2]._field36 = Common::Point(226, 5);
- _arrunkObj1337[0]._arr1[3]._field36 = Common::Point(199, 5);
-
- _arrunkObj1337[0]._arr2[0]._field36 = Common::Point(171, 16);
- _arrunkObj1337[0]._arr2[1]._field36 = Common::Point(171, 42);
- _arrunkObj1337[0]._arr2[2]._field36 = Common::Point(171, 68);
- _arrunkObj1337[0]._arr2[3]._field36 = Common::Point(145, 68);
- _arrunkObj1337[0]._arr2[4]._field36 = Common::Point(119, 68);
- _arrunkObj1337[0]._arr2[5]._field36 = Common::Point(119, 42);
- _arrunkObj1337[0]._arr2[6]._field36 = Common::Point(119, 16);
- _arrunkObj1337[0]._arr2[7]._field36 = Common::Point(145, 16);
-
- _arrunkObj1337[0]._arr3[0]._field36 = Common::Point(91, 16);
-
- _arrunkObj1337[0]._arr4[0]._field36 = Common::Point(145, 42);
-
- _arrunkObj1337[0]._fieldB94 = Common::Point(280, 5);
- _arrunkObj1337[0]._fieldB98 = Common::Point(253, 5);
- _arrunkObj1337[0]._fieldB9C = Common::Point(226, 5);
- _arrunkObj1337[0]._fieldBA0 = Common::Point(199, 5);
- _arrunkObj1337[0]._fieldBA4 = 2;
-
- _arrunkObj1337[1]._arr1[0]._field36 = Common::Point(283, 146);
- _arrunkObj1337[1]._arr1[1]._field36 = Common::Point(283, 124);
- _arrunkObj1337[1]._arr1[2]._field36 = Common::Point(283, 102);
- _arrunkObj1337[1]._arr1[3]._field36 = Common::Point(283, 80);
-
- _arrunkObj1337[1]._arr2[0]._field36 = Common::Point(253, 122);
- _arrunkObj1337[1]._arr2[1]._field36 = Common::Point(227, 122);
- _arrunkObj1337[1]._arr2[2]._field36 = Common::Point(201, 122);
- _arrunkObj1337[1]._arr2[3]._field36 = Common::Point(201, 96);
- _arrunkObj1337[1]._arr2[4]._field36 = Common::Point(201, 70);
- _arrunkObj1337[1]._arr2[5]._field36 = Common::Point(227, 70);
- _arrunkObj1337[1]._arr2[6]._field36 = Common::Point(253, 70);
- _arrunkObj1337[1]._arr2[7]._field36 = Common::Point(253, 96);
-
- _arrunkObj1337[1]._arr3[0]._field36 = Common::Point(253, 43);
-
- _arrunkObj1337[1]._arr4[0]._field36 = Common::Point(227, 96);
-
- _arrunkObj1337[1]._fieldB94 = Common::Point(283, 146);
- _arrunkObj1337[1]._fieldB98 = Common::Point(283, 124);
- _arrunkObj1337[1]._fieldB9C = Common::Point(283, 102);
- _arrunkObj1337[1]._fieldBA0 = Common::Point(283, 80);
- _arrunkObj1337[1]._fieldBA4 = 4;
+ _gameBoardSide[2]._handCard[0]._stationPos = Common::Point(10, 174);
+ _gameBoardSide[2]._handCard[1]._stationPos = Common::Point(37, 174);
+ _gameBoardSide[2]._handCard[2]._stationPos = Common::Point(64, 174);
+ _gameBoardSide[2]._handCard[3]._stationPos = Common::Point(91, 174);
+
+ _gameBoardSide[2]._outpostStation[0]._stationPos = Common::Point(119, 174);
+ _gameBoardSide[2]._outpostStation[1]._stationPos = Common::Point(119, 148);
+ _gameBoardSide[2]._outpostStation[2]._stationPos = Common::Point(119, 122);
+ _gameBoardSide[2]._outpostStation[3]._stationPos = Common::Point(145, 122);
+ _gameBoardSide[2]._outpostStation[4]._stationPos = Common::Point(171, 122);
+ _gameBoardSide[2]._outpostStation[5]._stationPos = Common::Point(171, 148);
+ _gameBoardSide[2]._outpostStation[6]._stationPos = Common::Point(171, 174);
+ _gameBoardSide[2]._outpostStation[7]._stationPos = Common::Point(145, 174);
+
+ _gameBoardSide[2]._delayPile[0]._stationPos = Common::Point(199, 174);
+
+ _gameBoardSide[2]._arr4[0]._stationPos = Common::Point(145, 148);
+
+ _gameBoardSide[2]._fieldB94 = Common::Point(10, 174);
+ _gameBoardSide[2]._fieldB98 = Common::Point(37, 174);
+ _gameBoardSide[2]._fieldB9C = Common::Point(64, 174);
+ _gameBoardSide[2]._fieldBA0 = Common::Point(91, 174);
+ _gameBoardSide[2]._fieldBA4 = 2;
+
+ _gameBoardSide[3]._handCard[0]._stationPos = Common::Point(14, 14);
+ _gameBoardSide[3]._handCard[1]._stationPos = Common::Point(14, 36);
+ _gameBoardSide[3]._handCard[2]._stationPos = Common::Point(14, 58);
+ _gameBoardSide[3]._handCard[3]._stationPos = Common::Point(14, 80);
+
+ _gameBoardSide[3]._outpostStation[0]._stationPos = Common::Point(37, 66);
+ _gameBoardSide[3]._outpostStation[1]._stationPos = Common::Point(63, 66);
+ _gameBoardSide[3]._outpostStation[2]._stationPos = Common::Point(89, 66);
+ _gameBoardSide[3]._outpostStation[3]._stationPos = Common::Point(89, 92);
+ _gameBoardSide[3]._outpostStation[4]._stationPos = Common::Point(89, 118);
+ _gameBoardSide[3]._outpostStation[5]._stationPos = Common::Point(63, 118);
+ _gameBoardSide[3]._outpostStation[6]._stationPos = Common::Point(37, 118);
+ _gameBoardSide[3]._outpostStation[7]._stationPos = Common::Point(37, 92);
+
+ _gameBoardSide[3]._delayPile[0]._stationPos = Common::Point(37, 145);
+
+ _gameBoardSide[3]._arr4[0]._stationPos = Common::Point(63, 92);
+
+ _gameBoardSide[3]._fieldB94 = Common::Point(14, 14);
+ _gameBoardSide[3]._fieldB98 = Common::Point(14, 36);
+ _gameBoardSide[3]._fieldB9C = Common::Point(14, 58);
+ _gameBoardSide[3]._fieldBA0 = Common::Point(14, 80);
+ _gameBoardSide[3]._fieldBA4 = 3;
+
+ _gameBoardSide[0]._handCard[0]._stationPos = Common::Point(280, 5);
+ _gameBoardSide[0]._handCard[1]._stationPos = Common::Point(253, 5);
+ _gameBoardSide[0]._handCard[2]._stationPos = Common::Point(226, 5);
+ _gameBoardSide[0]._handCard[3]._stationPos = Common::Point(199, 5);
+
+ _gameBoardSide[0]._outpostStation[0]._stationPos = Common::Point(171, 16);
+ _gameBoardSide[0]._outpostStation[1]._stationPos = Common::Point(171, 42);
+ _gameBoardSide[0]._outpostStation[2]._stationPos = Common::Point(171, 68);
+ _gameBoardSide[0]._outpostStation[3]._stationPos = Common::Point(145, 68);
+ _gameBoardSide[0]._outpostStation[4]._stationPos = Common::Point(119, 68);
+ _gameBoardSide[0]._outpostStation[5]._stationPos = Common::Point(119, 42);
+ _gameBoardSide[0]._outpostStation[6]._stationPos = Common::Point(119, 16);
+ _gameBoardSide[0]._outpostStation[7]._stationPos = Common::Point(145, 16);
+
+ _gameBoardSide[0]._delayPile[0]._stationPos = Common::Point(91, 16);
+
+ _gameBoardSide[0]._arr4[0]._stationPos = Common::Point(145, 42);
+
+ _gameBoardSide[0]._fieldB94 = Common::Point(280, 5);
+ _gameBoardSide[0]._fieldB98 = Common::Point(253, 5);
+ _gameBoardSide[0]._fieldB9C = Common::Point(226, 5);
+ _gameBoardSide[0]._fieldBA0 = Common::Point(199, 5);
+ _gameBoardSide[0]._fieldBA4 = 2;
+
+ _gameBoardSide[1]._handCard[0]._stationPos = Common::Point(283, 146);
+ _gameBoardSide[1]._handCard[1]._stationPos = Common::Point(283, 124);
+ _gameBoardSide[1]._handCard[2]._stationPos = Common::Point(283, 102);
+ _gameBoardSide[1]._handCard[3]._stationPos = Common::Point(283, 80);
+
+ _gameBoardSide[1]._outpostStation[0]._stationPos = Common::Point(253, 122);
+ _gameBoardSide[1]._outpostStation[1]._stationPos = Common::Point(227, 122);
+ _gameBoardSide[1]._outpostStation[2]._stationPos = Common::Point(201, 122);
+ _gameBoardSide[1]._outpostStation[3]._stationPos = Common::Point(201, 96);
+ _gameBoardSide[1]._outpostStation[4]._stationPos = Common::Point(201, 70);
+ _gameBoardSide[1]._outpostStation[5]._stationPos = Common::Point(227, 70);
+ _gameBoardSide[1]._outpostStation[6]._stationPos = Common::Point(253, 70);
+ _gameBoardSide[1]._outpostStation[7]._stationPos = Common::Point(253, 96);
+
+ _gameBoardSide[1]._delayPile[0]._stationPos = Common::Point(253, 43);
+
+ _gameBoardSide[1]._arr4[0]._stationPos = Common::Point(227, 96);
+
+ _gameBoardSide[1]._fieldB94 = Common::Point(283, 146);
+ _gameBoardSide[1]._fieldB98 = Common::Point(283, 124);
+ _gameBoardSide[1]._fieldB9C = Common::Point(283, 102);
+ _gameBoardSide[1]._fieldBA0 = Common::Point(283, 80);
+ _gameBoardSide[1]._fieldBA4 = 4;
subPostInit();
}
@@ -3870,10 +4475,10 @@ void Scene1337::process(Event &event) {
}
void Scene1337::dispatch() {
- if (_field424C == 0) {
- ++_field424E;
- if (_field424E == 4) {
- _field424C = 1;
+ if (_instructionsDisplayedFl == 0) {
+ ++_instructionsWaitCount;
+ if (_instructionsWaitCount == 4) {
+ _instructionsDisplayedFl = 1;
suggestInstructions();
}
}
@@ -3891,20 +4496,20 @@ void Scene1337::setAnimationInfo(unkObj1337sub1 *subObj) {
if (!subObj)
return;
- if (subObj->_field34 > 9) {
- if (subObj->_field34 > 25) {
- subObj->_object1.setStrip2(4);
- subObj->_object1.setFrame(subObj->_field34 - 25);
+ if (subObj->_cardId > 9) {
+ if (subObj->_cardId > 25) {
+ subObj->_card.setStrip2(4);
+ subObj->_card.setFrame(subObj->_cardId - 25);
} else {
- subObj->_object1.setStrip2(3);
- subObj->_object1.setFrame(subObj->_field34 - 9);
+ subObj->_card.setStrip2(3);
+ subObj->_card.setFrame(subObj->_cardId - 9);
}
} else {
- subObj->_object1.setStrip2(2);
- subObj->_object1.setFrame(subObj->_field34);
+ subObj->_card.setStrip2(2);
+ subObj->_card.setFrame(subObj->_cardId);
}
- subObj->_object1.show();
+ subObj->_card.show();
R2_GLOBALS._sceneObjects->draw();
}
@@ -3915,26 +4520,26 @@ void Scene1337::subC20E5() {
void Scene1337::subC20F9() {
switch (_field424A) {
case -1:
- ++_field423E;
- if (_field423E == 3)
- _field423E = 0;
+ ++_currentPlayerNumb;
+ if (_currentPlayerNumb == 3)
+ _currentPlayerNumb = 0;
- if (_field4244 == 1) {
- _object1.show();
- switch (_field423E) {
+ if (_field4244) {
+ _currentPlayerArrow.show();
+ switch (_currentPlayerNumb) {
case 0:
- _object1.setStrip(3);
+ _currentPlayerArrow.setStrip(3);
break;
case 1:
- _object1.setStrip(4);
+ _currentPlayerArrow.setStrip(4);
break;
case 2:
subD1975(174, 107);
- _object1.setStrip(1);
+ _currentPlayerArrow.setStrip(1);
break;
case 3:
subC4CEC();
- _object1.setStrip(2);
+ _currentPlayerArrow.setStrip(2);
break;
default:
break;
@@ -3990,15 +4595,15 @@ void Scene1337::subC20F9() {
}
void Scene1337::subC2586() {
- if (_field4244 != 0)
- _object1.hide();
+ if (_field4244)
+ _currentPlayerArrow.hide();
- switch (_field423E) {
+ switch (_currentPlayerNumb) {
case 2:
subC4CD2();
- if (_field4246 == 1)
+ if (_field4246)
actionDisplay(1330, 114, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- _field4246 = 0;
+ _field4246 = false;
// No break on purpose
case 0:
// No break on purpose
@@ -4010,7 +4615,7 @@ void Scene1337::subC2586() {
break;
}
- _field4244 = 1;
+ _field4244 = true;
}
@@ -4053,7 +4658,7 @@ bool Scene1337::subC2687(int arg1) {
}
int Scene1337::subC26CB(int arg1, int arg2) {
- if ((_arrunkObj1337[arg1]._arr1[arg2]._field34 > 1) && (_arrunkObj1337[arg1]._arr1[arg2]._field34 <= 9)) {
+ if ((_gameBoardSide[arg1]._handCard[arg2]._cardId > 1) && (_gameBoardSide[arg1]._handCard[arg2]._cardId <= 9)) {
return arg2;
}
@@ -4062,7 +4667,7 @@ int Scene1337::subC26CB(int arg1, int arg2) {
int Scene1337::subC2719(int arg1) {
for (int i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 1)
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 1)
return i;
}
@@ -4071,7 +4676,7 @@ int Scene1337::subC2719(int arg1) {
int Scene1337::subC274D(int arg1) {
for (int i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 13)
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 13)
return i;
}
@@ -4080,7 +4685,7 @@ int Scene1337::subC274D(int arg1) {
int Scene1337::subC2781(int arg1) {
for (int i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 25)
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 25)
return i;
}
@@ -4133,7 +4738,7 @@ void Scene1337::subC2835(int arg1) {
switch (arg1) {
case 0:
for (i = 0; i <= 3; i++) {
- if (subC27F9(_arrunkObj1337[arg1]._arr1[i]._field34) != -1) {
+ if (subC27F9(_gameBoardSide[arg1]._handCard[i]._cardId) != -1) {
found = true;
break;
}
@@ -4143,7 +4748,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (subC27B5(_arrunkObj1337[arg1]._arr1[i]._field34) != -1) {
+ if (subC27B5(_gameBoardSide[arg1]._handCard[i]._cardId) != -1) {
found = true;
break;
}
@@ -4153,7 +4758,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if ((_arrunkObj1337[arg1]._arr1[i]._field34 > 1) && (_arrunkObj1337[arg1]._arr1[i]._field34 <= 9)) {
+ if ((_gameBoardSide[arg1]._handCard[i]._cardId > 1) && (_gameBoardSide[arg1]._handCard[i]._cardId <= 9)) {
found = true;
break;
}
@@ -4163,7 +4768,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if ((_arrunkObj1337[arg1]._arr1[i]._field34 >= 26) && (_arrunkObj1337[arg1]._arr1[i]._field34 <= 33)) {
+ if ((_gameBoardSide[arg1]._handCard[i]._cardId >= 26) && (_gameBoardSide[arg1]._handCard[i]._cardId <= 33)) {
found = true;
break;
}
@@ -4173,7 +4778,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 1) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 1) {
found = true;
break;
}
@@ -4183,7 +4788,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 25) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 25) {
found = true;
break;
}
@@ -4193,7 +4798,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 13) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 13) {
found = true;
break;
}
@@ -4201,7 +4806,7 @@ void Scene1337::subC2835(int arg1) {
break;
case 1:
for (i = 0; i <= 3; i++) {
- if ((_arrunkObj1337[arg1]._arr1[i]._field34 >= 26) && (_arrunkObj1337[arg1]._arr1[i]._field34 <= 33)) {
+ if ((_gameBoardSide[arg1]._handCard[i]._cardId >= 26) && (_gameBoardSide[arg1]._handCard[i]._cardId <= 33)) {
found = true;
break;
}
@@ -4211,7 +4816,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 1) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 1) {
found = true;
break;
}
@@ -4221,7 +4826,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if ((_arrunkObj1337[arg1]._arr1[i]._field34 > 1) && (_arrunkObj1337[arg1]._arr1[i]._field34 <= 9)) {
+ if ((_gameBoardSide[arg1]._handCard[i]._cardId > 1) && (_gameBoardSide[arg1]._handCard[i]._cardId <= 9)) {
found = true;
break;
}
@@ -4231,7 +4836,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (subC27F9(_arrunkObj1337[arg1]._arr1[i]._field34) != -1) {
+ if (subC27F9(_gameBoardSide[arg1]._handCard[i]._cardId) != -1) {
found = true;
break;
}
@@ -4241,7 +4846,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (subC27B5(_arrunkObj1337[arg1]._arr1[i]._field34) != -1) {
+ if (subC27B5(_gameBoardSide[arg1]._handCard[i]._cardId) != -1) {
found = true;
break;
}
@@ -4251,7 +4856,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 25) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 25) {
found = true;
break;
}
@@ -4261,7 +4866,7 @@ void Scene1337::subC2835(int arg1) {
break;
for (i = 0; i <= 3; i++) {
- if (_arrunkObj1337[arg1]._arr1[i]._field34 == 13) {
+ if (_gameBoardSide[arg1]._handCard[i]._cardId == 13) {
found = true;
break;
}
@@ -4272,14 +4877,14 @@ void Scene1337::subC2835(int arg1) {
return;
}
- subC4A39(&_arrunkObj1337[arg1]._arr1[i]);
+ subC4A39(&_gameBoardSide[arg1]._handCard[i]);
}
bool Scene1337::subC2BF8(unkObj1337sub1 *subObj1, Common::Point pt) {
- if ((subObj1->_field36.x > pt.x) || (subObj1->_field36.x + 24 < pt.x))
+ if ((subObj1->_stationPos.x > pt.x) || (subObj1->_stationPos.x + 24 < pt.x))
return false;
- if ((subObj1->_field36.y > pt.y) || (subObj1->_field36.y + 24 < pt.y))
+ if ((subObj1->_stationPos.y > pt.y) || (subObj1->_stationPos.y + 24 < pt.y))
return false;
return true;
@@ -4288,8 +4893,8 @@ bool Scene1337::subC2BF8(unkObj1337sub1 *subObj1, Common::Point pt) {
void Scene1337::subC2C2F() {
bool found = true;
- if (_arrunkObj1337[3]._arr3[0]._field34 != 0) {
- switch (_arrunkObj1337[3]._arr3[0]._field34) {
+ if (_gameBoardSide[3]._delayPile[0]._cardId != 0) {
+ switch (_gameBoardSide[3]._delayPile[0]._cardId) {
case 10:
// No break on purpose
case 12:
@@ -4305,14 +4910,14 @@ void Scene1337::subC2C2F() {
case 20:
// No break on purpose
case 21:
- subC4A39(&_arrunkObj1337[3]._arr3[0]);
+ subC4A39(&_gameBoardSide[3]._delayPile[0]);
found = false;
break;
default:
found = false;
int i;
for (i = 0; i <= 3; i++) {
- if (subC3386(_arrunkObj1337[3]._arr3[0]._field34, _arrunkObj1337[3]._arr1[i]._field34)) {
+ if (subC3386(_gameBoardSide[3]._delayPile[0]._cardId, _gameBoardSide[3]._handCard[i]._cardId)) {
found = true;
break;
}
@@ -4320,7 +4925,7 @@ void Scene1337::subC2C2F() {
if (found) {
found = false;
- subC34A1(&_arrunkObj1337[3]._arr1[i], &_arrunkObj1337[3]._arr3[0]);
+ subC34A1(&_gameBoardSide[3]._handCard[i], &_gameBoardSide[3]._delayPile[0]);
}
break;
}
@@ -4331,12 +4936,12 @@ void Scene1337::subC2C2F() {
int randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
- if (_arrunkObj1337[3]._arr1[randIndx]._field34 == 1) {
+ if (_gameBoardSide[3]._handCard[randIndx]._cardId == 1) {
found = false;
for (int i = 0; i <= 7; i++) {
- if ((_arrunkObj1337[3]._arr2[i]._field34 == 0) && (!subC2687(_arrunkObj1337[3]._arr3[0]._field34))) {
- subC340B(&_arrunkObj1337[3]._arr1[randIndx], &_arrunkObj1337[3]._arr2[i]);
+ if ((_gameBoardSide[3]._outpostStation[i]._cardId == 0) && (!subC2687(_gameBoardSide[3]._delayPile[0]._cardId))) {
+ subC340B(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
found = true;
break;
}
@@ -4345,11 +4950,11 @@ void Scene1337::subC2C2F() {
if (found) {
return;
}
- } else if (_arrunkObj1337[3]._arr1[randIndx]._field34 <= 9) {
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId <= 9) {
found = false;
for (int i = 0; i <= 7; i++) {
- if (_arrunkObj1337[3]._arr2[i]._field34 == _arrunkObj1337[3]._arr1[randIndx]._field34) {
+ if (_gameBoardSide[3]._outpostStation[i]._cardId == _gameBoardSide[3]._handCard[randIndx]._cardId) {
found = true;
break;
}
@@ -4357,18 +4962,18 @@ void Scene1337::subC2C2F() {
if (!found) {
for (int i = 0; i <= 7; i++) {
- if ((_arrunkObj1337[3]._arr2[i]._field34 == 1) && (!subC2687(_arrunkObj1337[3]._arr3[i]._field34))) {
+ if ((_gameBoardSide[3]._outpostStation[i]._cardId == 1) && (!subC2687(_gameBoardSide[3]._delayPile[0]._cardId))) {
int tmpVal = 0;
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[3]._arr2[j]._field34 > 1) && (_arrunkObj1337[3]._arr2[j]._field34 <= 9))
+ if ((_gameBoardSide[3]._outpostStation[j]._cardId > 1) && (_gameBoardSide[3]._outpostStation[j]._cardId <= 9))
++tmpVal;
}
if (tmpVal == 7)
_field424A = 3;
- subC33C0(&_arrunkObj1337[3]._arr1[randIndx], &_arrunkObj1337[3]._arr2[i]);
+ subC33C0(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
found = true;
break;
}
@@ -4376,24 +4981,24 @@ void Scene1337::subC2C2F() {
if (found)
return;
}
- } else if (_arrunkObj1337[3]._arr1[randIndx]._field34 == 13) {
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 13) {
int tmpVal = subC331B(3);
if (tmpVal != -1) {
- subC358E(&_arrunkObj1337[3]._arr1[randIndx], tmpVal);
+ subC358E(&_gameBoardSide[3]._handCard[randIndx], tmpVal);
return;
}
- } else if (_arrunkObj1337[3]._arr1[randIndx]._field34 == 25) {
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 25) {
int tmpVal = -1;
found = false;
int tmpRandIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int i = 0; i <= 3; i++) {
if ( (tmpRandIndx != 3)
- && ( (_arrunkObj1337[tmpRandIndx]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[tmpRandIndx]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[tmpRandIndx]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[tmpRandIndx]._arr1[3]._field34 != 0) )) {
+ && ( (_gameBoardSide[tmpRandIndx]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[3]._cardId != 0) )) {
tmpVal = tmpRandIndx;
break;
}
@@ -4404,11 +5009,11 @@ void Scene1337::subC2C2F() {
}
if (tmpVal != -1) {
- subC318B(3, &_arrunkObj1337[3]._arr1[randIndx], tmpVal);
+ subC318B(3, &_gameBoardSide[3]._handCard[randIndx], tmpVal);
return;
}
} else {
- switch (_arrunkObj1337[3]._arr1[randIndx]._field34) {
+ switch (_gameBoardSide[3]._handCard[randIndx]._cardId) {
case 10:
// No break on purpose
case 11:
@@ -4441,7 +5046,7 @@ void Scene1337::subC2C2F() {
// It's understandable for 'i', which helps making sure that tmpVal is used properly,
// but it's suspect for j
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[tmpRandIndx]._arr3[0]._field34 == 0) && (subC32B1(tmpRandIndx, _arrunkObj1337[3]._arr1[randIndx]._field34))) {
+ if ((_gameBoardSide[tmpRandIndx]._delayPile[0]._cardId == 0) && (subC32B1(tmpRandIndx, _gameBoardSide[3]._handCard[randIndx]._cardId))) {
tmpVal = j;
}
}
@@ -4457,7 +5062,7 @@ void Scene1337::subC2C2F() {
if (tmpVal != -1) {
// Useless second identical check skipped
- subC3456(&_arrunkObj1337[3]._arr1[randIndx], &_arrunkObj1337[tmpVal]._arr3[0]);
+ subC3456(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[tmpVal]._delayPile[0]);
return;
}
}
@@ -4466,7 +5071,7 @@ void Scene1337::subC2C2F() {
}
}
- subC4A39(&_arrunkObj1337[3]._arr1[randIndx]);
+ subC4A39(&_gameBoardSide[3]._handCard[randIndx]);
}
void Scene1337::subC318B(int arg1, unkObj1337sub1 *subObj1, int arg3) {
@@ -4477,13 +5082,13 @@ void Scene1337::subC318B(int arg1, unkObj1337sub1 *subObj1, int arg3) {
for (;;) {
randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
- if (_arrunkObj1337[arg3]._arr1[randIndx]._field34 != 0)
+ if (_gameBoardSide[arg3]._handCard[randIndx]._cardId != 0)
break;
}
_field3EF0 = subObj1;
- _field3EF4 = &_arrunkObj1337[arg3]._arr4[0];
- _field3EF8 = &_arrunkObj1337[arg3]._arr1[randIndx];
+ _field3EF4 = &_gameBoardSide[arg3]._arr4[0];
+ _field3EF8 = &_gameBoardSide[arg3]._handCard[randIndx];
_item1.setAction(&_action11);
}
@@ -4525,9 +5130,9 @@ int Scene1337::subC3257(int arg1) {
bool Scene1337::subC32B1(int arg1, int arg2) {
for (int i = 0; i <= 7; i++) {
- if (_arrunkObj1337[arg1]._arr2[i]._field34 != 0) {
+ if (_gameBoardSide[arg1]._outpostStation[i]._cardId != 0) {
int tmpVal = subC3257(arg2);
- if (tmpVal == _arrunkObj1337[arg1]._arr2[i]._field34)
+ if (tmpVal == _gameBoardSide[arg1]._outpostStation[i]._cardId)
return false;
}
}
@@ -4540,7 +5145,7 @@ int Scene1337::subC331B(int arg1) {
for (int i = 0; i <= 3; i++) {
if (randIndx != arg1) {
for (int j = 0; j <= 7; j++) {
- if (_arrunkObj1337[randIndx]._arr2[j]._field34 != 0)
+ if (_gameBoardSide[randIndx]._outpostStation[j]._cardId != 0)
return randIndx;
}
}
@@ -4582,16 +5187,16 @@ void Scene1337::subC33C0(unkObj1337sub1 *subObj1, unkObj1337sub1 *subObj2) {
}
int Scene1337::subC3E92(int arg1) {
- if ( (_arrunkObj1337[arg1]._arr1[0]._field34 == 0)
- && (_arrunkObj1337[arg1]._arr1[1]._field34 == 0)
- && (_arrunkObj1337[arg1]._arr1[2]._field34 == 0)
- && (_arrunkObj1337[arg1]._arr1[3]._field34 == 0))
+ if ( (_gameBoardSide[arg1]._handCard[0]._cardId == 0)
+ && (_gameBoardSide[arg1]._handCard[1]._cardId == 0)
+ && (_gameBoardSide[arg1]._handCard[2]._cardId == 0)
+ && (_gameBoardSide[arg1]._handCard[3]._cardId == 0))
return -1;
int randIndx;
for (;;) {
randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
- if (_arrunkObj1337[arg1]._arr1[randIndx]._field34 == 0)
+ if (_gameBoardSide[arg1]._handCard[randIndx]._cardId == 0)
break;
}
@@ -4621,14 +5226,14 @@ void Scene1337::subC34A1(unkObj1337sub1 *subObj1, unkObj1337sub1 *subObj2) {
Scene1337::unkObj1337sub1 *Scene1337::subC34EC(int arg1) {
for (int i = 0; i <= 7; i++) {
- if (_arrunkObj1337[arg1]._arr2[i]._field34 == 1) {
- return &_arrunkObj1337[arg1]._arr2[i];
+ if (_gameBoardSide[arg1]._outpostStation[i]._cardId == 1) {
+ return &_gameBoardSide[arg1]._outpostStation[i];
}
}
for (int i = 0; i <= 7; i++) {
- if ((_arrunkObj1337[arg1]._arr2[i]._field34 != 0) && (_arrunkObj1337[arg1]._arr2[i]._field34 < 10)) {
- return &_arrunkObj1337[arg1]._arr2[i];
+ if ((_gameBoardSide[arg1]._outpostStation[i]._cardId != 0) && (_gameBoardSide[arg1]._outpostStation[i]._cardId < 10)) {
+ return &_gameBoardSide[arg1]._outpostStation[i];
}
}
@@ -4638,7 +5243,7 @@ Scene1337::unkObj1337sub1 *Scene1337::subC34EC(int arg1) {
void Scene1337::subC358E(unkObj1337sub1 *subObj1, int arg2) {
_field3EF0 = subObj1;
_field3EF4 = subC34EC(arg2);
- _field3EF8 = &_arrunkObj1337[arg2]._arr4[0];
+ _field3EF8 = &_gameBoardSide[arg2]._arr4[0];
_field4240 = arg2;
_item1.setAction(&_action10);
}
@@ -4661,7 +5266,7 @@ void Scene1337::subC4CEC() {
return;
subD18F5();
- subD1940(1);
+ subD1940(true);
}
void Scene1337::subC51A0(unkObj1337sub1 *subObj1, unkObj1337sub1 *subObj2) {
@@ -4781,148 +5386,148 @@ void Scene1337::subPostInit() {
R2_GLOBALS._scenePalette.addRotation(224, 235, 1);
- _field3E28[0] = 1;
- _field3E28[1] = 1;
- _field3E28[2] = 1;
- _field3E28[3] = 1;
- _field3E28[4] = 1;
- _field3E28[5] = 1;
- _field3E28[6] = 1;
- _field3E28[7] = 1;
- _field3E28[8] = 26;
- _field3E28[9] = 2;
- _field3E28[10] = 2;
- _field3E28[11] = 2;
- _field3E28[12] = 2;
- _field3E28[13] = 2;
- _field3E28[14] = 26;
- _field3E28[15] = 3;
- _field3E28[16] = 3;
- _field3E28[17] = 3;
- _field3E28[18] = 3;
- _field3E28[19] = 3;
- _field3E28[20] = 28;
- _field3E28[21] = 4;
- _field3E28[22] = 4;
- _field3E28[23] = 4;
- _field3E28[24] = 4;
- _field3E28[25] = 4;
- _field3E28[26] = 28;
- _field3E28[27] = 5;
- _field3E28[28] = 5;
- _field3E28[29] = 5;
- _field3E28[30] = 5;
- _field3E28[31] = 5;
- _field3E28[32] = 30;
- _field3E28[33] = 6;
- _field3E28[34] = 6;
- _field3E28[35] = 6;
- _field3E28[36] = 6;
- _field3E28[37] = 6;
- _field3E28[38] = 30;
- _field3E28[39] = 7;
- _field3E28[40] = 7;
- _field3E28[41] = 7;
- _field3E28[42] = 7;
- _field3E28[43] = 7;
- _field3E28[44] = 32;
- _field3E28[45] = 8;
- _field3E28[46] = 8;
- _field3E28[47] = 8;
- _field3E28[48] = 8;
- _field3E28[49] = 8;
- _field3E28[50] = 32;
- _field3E28[51] = 9;
- _field3E28[52] = 9;
- _field3E28[53] = 9;
- _field3E28[54] = 9;
- _field3E28[55] = 9;
- _field3E28[56] = 10;
- _field3E28[57] = 11;
- _field3E28[58] = 12;
- _field3E28[59] = 13;
- _field3E28[60] = 13;
- _field3E28[61] = 14;
- _field3E28[62] = 15;
- _field3E28[63] = 16;
- _field3E28[64] = 17;
- _field3E28[65] = 18;
- _field3E28[66] = 19;
- _field3E28[67] = 20;
- _field3E28[68] = 21;
- _field3E28[69] = 26;
- _field3E28[70] = 28;
- _field3E28[71] = 24;
- _field3E28[72] = 25;
- _field3E28[73] = 25;
- _field3E28[74] = 25;
- _field3E28[75] = 25;
- _field3E28[76] = 26;
- _field3E28[77] = 26;
- _field3E28[78] = 26;
- _field3E28[79] = 27;
- _field3E28[80] = 27;
- _field3E28[81] = 28;
- _field3E28[82] = 28;
- _field3E28[83] = 28;
- _field3E28[84] = 29;
- _field3E28[85] = 29;
- _field3E28[86] = 29;
- _field3E28[87] = 30;
- _field3E28[88] = 30;
- _field3E28[89] = 30;
- _field3E28[90] = 30;
- _field3E28[91] = 32;
- _field3E28[92] = 1;
- _field3E28[93] = 32;
- _field3E28[94] = 32;
- _field3E28[95] = 32;
- _field3E28[96] = 1;
- _field3E28[97] = 1;
- _field3E28[98] = 1;
- _field3E28[99] = 0;
-
- _field3E24 = 98;
+ _availableCardsPile[0] = 1;
+ _availableCardsPile[1] = 1;
+ _availableCardsPile[2] = 1;
+ _availableCardsPile[3] = 1;
+ _availableCardsPile[4] = 1;
+ _availableCardsPile[5] = 1;
+ _availableCardsPile[6] = 1;
+ _availableCardsPile[7] = 1;
+ _availableCardsPile[8] = 26;
+ _availableCardsPile[9] = 2;
+ _availableCardsPile[10] = 2;
+ _availableCardsPile[11] = 2;
+ _availableCardsPile[12] = 2;
+ _availableCardsPile[13] = 2;
+ _availableCardsPile[14] = 26;
+ _availableCardsPile[15] = 3;
+ _availableCardsPile[16] = 3;
+ _availableCardsPile[17] = 3;
+ _availableCardsPile[18] = 3;
+ _availableCardsPile[19] = 3;
+ _availableCardsPile[20] = 28;
+ _availableCardsPile[21] = 4;
+ _availableCardsPile[22] = 4;
+ _availableCardsPile[23] = 4;
+ _availableCardsPile[24] = 4;
+ _availableCardsPile[25] = 4;
+ _availableCardsPile[26] = 28;
+ _availableCardsPile[27] = 5;
+ _availableCardsPile[28] = 5;
+ _availableCardsPile[29] = 5;
+ _availableCardsPile[30] = 5;
+ _availableCardsPile[31] = 5;
+ _availableCardsPile[32] = 30;
+ _availableCardsPile[33] = 6;
+ _availableCardsPile[34] = 6;
+ _availableCardsPile[35] = 6;
+ _availableCardsPile[36] = 6;
+ _availableCardsPile[37] = 6;
+ _availableCardsPile[38] = 30;
+ _availableCardsPile[39] = 7;
+ _availableCardsPile[40] = 7;
+ _availableCardsPile[41] = 7;
+ _availableCardsPile[42] = 7;
+ _availableCardsPile[43] = 7;
+ _availableCardsPile[44] = 32;
+ _availableCardsPile[45] = 8;
+ _availableCardsPile[46] = 8;
+ _availableCardsPile[47] = 8;
+ _availableCardsPile[48] = 8;
+ _availableCardsPile[49] = 8;
+ _availableCardsPile[50] = 32;
+ _availableCardsPile[51] = 9;
+ _availableCardsPile[52] = 9;
+ _availableCardsPile[53] = 9;
+ _availableCardsPile[54] = 9;
+ _availableCardsPile[55] = 9;
+ _availableCardsPile[56] = 10;
+ _availableCardsPile[57] = 11;
+ _availableCardsPile[58] = 12;
+ _availableCardsPile[59] = 13;
+ _availableCardsPile[60] = 13;
+ _availableCardsPile[61] = 14;
+ _availableCardsPile[62] = 15;
+ _availableCardsPile[63] = 16;
+ _availableCardsPile[64] = 17;
+ _availableCardsPile[65] = 18;
+ _availableCardsPile[66] = 19;
+ _availableCardsPile[67] = 20;
+ _availableCardsPile[68] = 21;
+ _availableCardsPile[69] = 26;
+ _availableCardsPile[70] = 28;
+ _availableCardsPile[71] = 24;
+ _availableCardsPile[72] = 25;
+ _availableCardsPile[73] = 25;
+ _availableCardsPile[74] = 25;
+ _availableCardsPile[75] = 25;
+ _availableCardsPile[76] = 26;
+ _availableCardsPile[77] = 26;
+ _availableCardsPile[78] = 26;
+ _availableCardsPile[79] = 27;
+ _availableCardsPile[80] = 27;
+ _availableCardsPile[81] = 28;
+ _availableCardsPile[82] = 28;
+ _availableCardsPile[83] = 28;
+ _availableCardsPile[84] = 29;
+ _availableCardsPile[85] = 29;
+ _availableCardsPile[86] = 29;
+ _availableCardsPile[87] = 30;
+ _availableCardsPile[88] = 30;
+ _availableCardsPile[89] = 30;
+ _availableCardsPile[90] = 30;
+ _availableCardsPile[91] = 32;
+ _availableCardsPile[92] = 1;
+ _availableCardsPile[93] = 32;
+ _availableCardsPile[94] = 32;
+ _availableCardsPile[95] = 32;
+ _availableCardsPile[96] = 1;
+ _availableCardsPile[97] = 1;
+ _availableCardsPile[98] = 1;
+ _availableCardsPile[99] = 0;
+
+ _cardsAvailableNumb = 98;
_field3E26 = 98;
- _item7._field34 = 0;
- _item7._field36 = Common::Point(128, 95);
-
- _item8._field34 = 0;
- _item8._field36 = Common::Point(162, 95);
-
- _item6._field34 = 0;
-
- _item2._object1.postInit();
- _item2._object1.setVisage(1332);
- _item2._object1.setStrip(5);
- _item2._object1.setFrame(1);
- _item2._object1._moveDiff = Common::Point(10, 10);
- _item2._object1.fixPriority(400);
- _item2._object1.setPosition(Common::Point(128, 95), 0);
- _item2._object1.animate(ANIM_MODE_2, NULL);
- _item2._object1.hide();
-
- _object1.postInit();
- _object1.setVisage(1334);
- _object1.setStrip(1);
- _object1.setFrame(1);
- _object1._numFrames = 12;
- _object1.fixPriority(500);
- _object1.setPosition(Common::Point(174, 107), 0);
- _object1.animate(ANIM_MODE_2, NULL);
- _object1.hide();
-
- _field4244 = 1;
- _field4246 = 0;
+ _discardPile._cardId = 0;
+ _discardPile._stationPos = Common::Point(128, 95);
+
+ _item8._cardId = 0;
+ _item8._stationPos = Common::Point(162, 95);
+
+ _item6._cardId = 0;
+
+ _animatedCard._card.postInit();
+ _animatedCard._card.setVisage(1332);
+ _animatedCard._card.setStrip(5);
+ _animatedCard._card.setFrame(1);
+ _animatedCard._card._moveDiff = Common::Point(10, 10);
+ _animatedCard._card.fixPriority(400);
+ _animatedCard._card.setPosition(Common::Point(128, 95), 0);
+ _animatedCard._card.animate(ANIM_MODE_2, NULL);
+ _animatedCard._card.hide();
+
+ _currentPlayerArrow.postInit();
+ _currentPlayerArrow.setVisage(1334);
+ _currentPlayerArrow.setStrip(1);
+ _currentPlayerArrow.setFrame(1);
+ _currentPlayerArrow._numFrames = 12;
+ _currentPlayerArrow.fixPriority(500);
+ _currentPlayerArrow.setPosition(Common::Point(174, 107), 0);
+ _currentPlayerArrow.animate(ANIM_MODE_2, NULL);
+ _currentPlayerArrow.hide();
+
+ _field4244 = true;
+ _field4246 = false;
_field4248 = 0;
_field424A = -1;
_background1.setup2(9531, 1, 1, 249, 168, 155, 0);
_autoplay = false;
- _field424C = 0;
- _field424E = 0;
+ _instructionsDisplayedFl = 0;
+ _instructionsWaitCount = 0;
}
void Scene1337::suggestInstructions() {
@@ -4931,73 +5536,70 @@ void Scene1337::suggestInstructions() {
if (MessageDialog::show(NEED_INSTRUCTIONS, NO_MSG, YES_MSG) == 0) {
if (R2_GLOBALS._v57709 == 0)
subD18F5();
- subCCF26();
+ firstShuffle();
} else {
if (R2_GLOBALS._v57709 == 0)
subD18F5();
- subCB59B();
+ displayInstructions();
}
}
-void Scene1337::subCB59B() {
+void Scene1337::displayInstructions() {
_item1.setAction(&_action1);
}
void Scene1337::shuffleCards() {
R2_GLOBALS._sceneObjects->draw();
+ // Remove holes in card pile
for (int i = 0; i <= 98; i++) {
- if (_field3E28[i] == 0) {
+ if (_availableCardsPile[i] == 0) {
for (int j = i + 1; j <= 98; j ++) {
- if (_field3E28[j] != 0) {
- _field3E28[i] = _field3E28[j];
- _field3E28[j] = 0;
+ if (_availableCardsPile[j] != 0) {
+ _availableCardsPile[i] = _availableCardsPile[j];
+ _availableCardsPile[j] = 0;
break;
}
}
}
}
+ // Compute the number of available cards
for (int i = 0; i <= 99; i ++) {
- if (_field3E28[i] == 0) {
- _field3E24 = i - 1;
+ if (_availableCardsPile[i] == 0) {
+ // CHECKME: This will fail if i == 0, which shouldn't happen
+ // as we don't shuffle cards when no card is available.
+ _cardsAvailableNumb = i - 1;
_field3E26 = 98;
break;
}
}
- // tmpVal is never modified in the original. It looks weird but it works: at the end, the cards are suffled!
- int tmpVal = 0;
- int randIndx;
- int swap;
for (int i = 0; i < 2000; i ++) {
- randIndx = R2_GLOBALS._randomSource.getRandomNumber(_field3E24);
- swap = _field3E28[tmpVal];
- _field3E28[tmpVal] = _field3E28[randIndx];
- _field3E28[randIndx] = swap;
+ int randIndx = R2_GLOBALS._randomSource.getRandomNumber(_cardsAvailableNumb);
+ int swap = _availableCardsPile[0];
+ _availableCardsPile[0] = _availableCardsPile[randIndx];
+ _availableCardsPile[randIndx] = swap;
}
- _field423C = 0;
- _item2._object1.setAction(&_action2);
+ _shuffleEndedFl = false;
+ _animatedCard._card.setAction(&_action2);
- while(_field423C == 0) {
+ while(!_shuffleEndedFl && !g_vm->shouldQuit()) {
+ g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
g_globals->_scenePalette.signalListeners();
R2_GLOBALS._sceneObjects->draw();
- warning("TODO: recurse on draw() and on signalListeners()?");
g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
-
- // Hack to avoid eternal loop
- // To be removed when the recurse is working properly
- _field423C = 1;
}
}
-void Scene1337::subCCF26() {
- _item2._object1._moveDiff = Common::Point(30, 30);
+void Scene1337::firstShuffle() {
+ _animatedCard._card._moveDiff = Common::Point(30, 30);
shuffleCards();
_item1.setAction(&_action3);
}
void Scene1337::subCD193() {
+ // Display menu with "Auto Play", "New Game", "Quit" and "Continue"
warning("STUBBED: subCD193()");
}
@@ -5008,10 +5610,10 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
if (arg1 == 3) {
int i;
for (i = 0; i <= 7; i++) {
- if ( (subC2BF8(&_arrunkObj1337[2]._arr2[i], pt))
- || (subC2BF8(&_arrunkObj1337[0]._arr2[i], pt))
- || (subC2BF8(&_arrunkObj1337[1]._arr2[i], pt))
- || (subC2BF8(&_arrunkObj1337[3]._arr2[i], pt)) ) {
+ if ( (subC2BF8(&_gameBoardSide[2]._outpostStation[i], pt))
+ || (subC2BF8(&_gameBoardSide[0]._outpostStation[i], pt))
+ || (subC2BF8(&_gameBoardSide[1]._outpostStation[i], pt))
+ || (subC2BF8(&_gameBoardSide[3]._outpostStation[i], pt)) ) {
found = true;
break;
}
@@ -5020,26 +5622,26 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
if (found) {
switch (curReg) {
case 5:
- if (_arrunkObj1337[2]._arr2[i]._field34 != 0)
- displayDialog(_arrunkObj1337[2]._arr2[i]._field34);
+ if (_gameBoardSide[2]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[2]._outpostStation[i]._cardId);
else
actionDisplay(1330, 20, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 10:
- if (_arrunkObj1337[3]._arr2[i]._field34 != 0)
- displayDialog(_arrunkObj1337[3]._arr2[i]._field34);
+ if (_gameBoardSide[3]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[3]._outpostStation[i]._cardId);
else
actionDisplay(1330, 22, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 15:
- if (_arrunkObj1337[0]._arr2[i]._field34 != 0)
- displayDialog(_arrunkObj1337[0]._arr2[i]._field34);
+ if (_gameBoardSide[0]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[0]._outpostStation[i]._cardId);
else
actionDisplay(1330, 21, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 20:
- if (_arrunkObj1337[1]._arr2[i]._field34 != 0)
- displayDialog(_arrunkObj1337[1]._arr2[i]._field34);
+ if (_gameBoardSide[1]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[1]._outpostStation[i]._cardId);
else
actionDisplay(1330, 23, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -5047,36 +5649,36 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
break;
}
} else {
- if ( (subC2BF8(&_arrunkObj1337[2]._arr3[0], pt))
- || (subC2BF8(&_arrunkObj1337[0]._arr3[0], pt))
- || (subC2BF8(&_arrunkObj1337[1]._arr3[0], pt))
- || (subC2BF8(&_arrunkObj1337[3]._arr3[0], pt)) ) {
+ if ( (subC2BF8(&_gameBoardSide[2]._delayPile[0], pt))
+ || (subC2BF8(&_gameBoardSide[0]._delayPile[0], pt))
+ || (subC2BF8(&_gameBoardSide[1]._delayPile[0], pt))
+ || (subC2BF8(&_gameBoardSide[3]._delayPile[0], pt)) ) {
found = true;
}
if (found) {
switch (curReg) {
case 5:
- if (_arrunkObj1337[2]._arr3[0]._field34 != 0)
- displayDialog(_arrunkObj1337[2]._arr3[0]._field34);
+ if (_gameBoardSide[2]._delayPile[0]._cardId != 0)
+ displayDialog(_gameBoardSide[2]._delayPile[0]._cardId);
else
actionDisplay(1330, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 10:
- if (_arrunkObj1337[3]._arr3[0]._field34 != 0)
- displayDialog(_arrunkObj1337[3]._arr3[0]._field34);
+ if (_gameBoardSide[3]._delayPile[0]._cardId != 0)
+ displayDialog(_gameBoardSide[3]._delayPile[0]._cardId);
else
actionDisplay(1330, 16, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 15:
- if (_arrunkObj1337[0]._arr3[0]._field34 != 0)
- displayDialog(_arrunkObj1337[3]._arr3[0]._field34);
+ if (_gameBoardSide[0]._delayPile[0]._cardId != 0)
+ displayDialog(_gameBoardSide[3]._delayPile[0]._cardId);
else
actionDisplay(1330, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
case 20:
- if (_arrunkObj1337[1]._arr3[0]._field34 != 0)
- displayDialog(_arrunkObj1337[1]._arr3[0]._field34);
+ if (_gameBoardSide[1]._delayPile[0]._cardId != 0)
+ displayDialog(_gameBoardSide[1]._delayPile[0]._cardId);
else
actionDisplay(1330, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -5084,29 +5686,29 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
break;
}
} else {
- if (subC2BF8(&_item7, pt)) {
- if (_item7._field34 != 0)
- displayDialog(_item7._field34);
+ if (subC2BF8(&_discardPile, pt)) {
+ if (_discardPile._cardId != 0)
+ displayDialog(_discardPile._cardId);
else
actionDisplay(1330, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else if (_background1._bounds.contains(pt)) {
actionDisplay(1330, 43, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else if (subC2BF8(&_item8, pt)) {
actionDisplay(1330, 4, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if ( (subC2BF8(&_arrunkObj1337[2]._arr4[0], pt))
- || (subC2BF8(&_arrunkObj1337[3]._arr4[0], pt))
- || (subC2BF8(&_arrunkObj1337[0]._arr4[0], pt))
- || (subC2BF8(&_arrunkObj1337[1]._arr4[0], pt)) ) {
+ } else if ( (subC2BF8(&_gameBoardSide[2]._arr4[0], pt))
+ || (subC2BF8(&_gameBoardSide[3]._arr4[0], pt))
+ || (subC2BF8(&_gameBoardSide[0]._arr4[0], pt))
+ || (subC2BF8(&_gameBoardSide[1]._arr4[0], pt)) ) {
actionDisplay(1330, 32, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else {
- if (subC2BF8(&_arrunkObj1337[2]._arr1[0], pt))
- displayDialog(_arrunkObj1337[2]._arr1[0]._field34);
- else if (subC2BF8(&_arrunkObj1337[2]._arr1[1], pt))
- displayDialog(_arrunkObj1337[2]._arr1[1]._field34);
- else if (subC2BF8(&_arrunkObj1337[2]._arr1[2], pt))
- displayDialog(_arrunkObj1337[2]._arr1[2]._field34);
- else if (subC2BF8(&_arrunkObj1337[2]._arr1[3], pt))
- displayDialog(_arrunkObj1337[2]._arr1[3]._field34);
+ if (subC2BF8(&_gameBoardSide[2]._handCard[0], pt))
+ displayDialog(_gameBoardSide[2]._handCard[0]._cardId);
+ else if (subC2BF8(&_gameBoardSide[2]._handCard[1], pt))
+ displayDialog(_gameBoardSide[2]._handCard[1]._cardId);
+ else if (subC2BF8(&_gameBoardSide[2]._handCard[2], pt))
+ displayDialog(_gameBoardSide[2]._handCard[2]._cardId);
+ else if (subC2BF8(&_gameBoardSide[2]._handCard[3], pt))
+ displayDialog(_gameBoardSide[2]._handCard[3]._cardId);
else if ((curReg >= 6) && (curReg <= 9))
actionDisplay(1330, 29, 159, 10, 1, 200, 0, 7, 0, 154, 154);
else if ((curReg >= 11) && (curReg <= 14))
@@ -5146,8 +5748,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
return;
for (int i = 0; i <= 7; i++) {
- if (subC2BF8(&_arrunkObj1337[2]._arr2[i], pt)) {
- switch (_arrunkObj1337[2]._arr2[i]._field34) {
+ if (subC2BF8(&_gameBoardSide[2]._outpostStation[i], pt)) {
+ switch (_gameBoardSide[2]._outpostStation[i]._cardId) {
case 0:
actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -5160,8 +5762,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
}
found = true;
break;
- } else if (subC2BF8(&_arrunkObj1337[0]._arr2[i], pt)) {
- switch (_arrunkObj1337[0]._arr2[i]._field34) {
+ } else if (subC2BF8(&_gameBoardSide[0]._outpostStation[i], pt)) {
+ switch (_gameBoardSide[0]._outpostStation[i]._cardId) {
case 0:
actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -5171,8 +5773,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
}
found = true;
break;
- } else if (subC2BF8(&_arrunkObj1337[1]._arr2[i], pt)) {
- switch (_arrunkObj1337[1]._arr2[i]._field34) {
+ } else if (subC2BF8(&_gameBoardSide[1]._outpostStation[i], pt)) {
+ switch (_gameBoardSide[1]._outpostStation[i]._cardId) {
case 0:
actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
break;
@@ -5182,8 +5784,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
}
found = true;
break;
- } else if (subC2BF8(&_arrunkObj1337[3]._arr2[i], pt)) {
- switch (_arrunkObj1337[3]._arr2[i]._field34) {
+ } else if (subC2BF8(&_gameBoardSide[3]._outpostStation[i], pt)) {
+ switch (_gameBoardSide[3]._outpostStation[i]._cardId) {
case 0:
actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
break;
@@ -5196,8 +5798,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
}
}
- if (subC2BF8(&_arrunkObj1337[2]._arr3[0], pt)) {
- if (_arrunkObj1337[0]._arr3[0]._field34 != 0) {
+ if (subC2BF8(&_gameBoardSide[2]._delayPile[0], pt)) {
+ if (_gameBoardSide[0]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 39, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else {
actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
@@ -5205,8 +5807,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
found = true;
}
- if (subC2BF8(&_arrunkObj1337[3]._arr3[0], pt)) {
- if (_arrunkObj1337[3]._arr3[0]._field34 != 0) {
+ if (subC2BF8(&_gameBoardSide[3]._delayPile[0], pt)) {
+ if (_gameBoardSide[3]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
} else {
actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
@@ -5214,8 +5816,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
found = true;
}
- if (subC2BF8(&_arrunkObj1337[1]._arr3[0], pt)) {
- if (_arrunkObj1337[1]._arr3[0]._field34 != 0) {
+ if (subC2BF8(&_gameBoardSide[1]._delayPile[0], pt)) {
+ if (_gameBoardSide[1]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
} else {
actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
@@ -5223,8 +5825,8 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
found = true;
}
- if (subC2BF8(&_arrunkObj1337[0]._arr3[0], pt)) {
- if (_arrunkObj1337[0]._arr3[0]._field34 != 0) {
+ if (subC2BF8(&_gameBoardSide[0]._delayPile[0], pt)) {
+ if (_gameBoardSide[0]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else {
actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
@@ -5232,17 +5834,17 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
found = true;
}
- if (subC2BF8(&_arrunkObj1337[3]._arr4[0], pt)) {
+ if (subC2BF8(&_gameBoardSide[3]._arr4[0], pt)) {
actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
found = true;
}
- if (subC2BF8(&_arrunkObj1337[1]._arr4[0], pt)) {
+ if (subC2BF8(&_gameBoardSide[1]._arr4[0], pt)) {
actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
found = true;
}
- if (subC2BF8(&_arrunkObj1337[0]._arr4[0], pt)) {
+ if (subC2BF8(&_gameBoardSide[0]._arr4[0], pt)) {
actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
found = true;
}
@@ -5255,7 +5857,7 @@ void Scene1337::subCDB90(int arg1, Common::Point pt) {
return;
}
- if (subC2BF8(&_item7, pt))
+ if (subC2BF8(&_discardPile, pt))
actionDisplay(1330, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
else if (subC2BF8(&_item8, pt))
actionDisplay(1330, 5, 159, 10, 1, 200, 0, 7, 0, 154, 154);
@@ -5309,8 +5911,8 @@ void Scene1337::subCF31D() {
bool found;
int count;
- if (this->_arrunkObj1337[1]._arr3[0]._field34 != 0) {
- switch (_arrunkObj1337[1]._arr3[0]._field34) {
+ if (this->_gameBoardSide[1]._delayPile[0]._cardId != 0) {
+ switch (_gameBoardSide[1]._delayPile[0]._cardId) {
case 10:
// No break on purpose
case 12:
@@ -5327,13 +5929,13 @@ void Scene1337::subCF31D() {
// No break on purpose
case 21:
tmpVal = 0;
- subC4A39(&_arrunkObj1337[1]._arr3[0]);
+ subC4A39(&_gameBoardSide[1]._delayPile[0]);
break;
default:
found = false;
int i;
for (i = 0; i <= 3; i++) {
- if (subC3386(_arrunkObj1337[1]._arr3[0]._field34, _arrunkObj1337[1]._arr1[i]._field34)) {
+ if (subC3386(_gameBoardSide[1]._delayPile[0]._cardId, _gameBoardSide[1]._handCard[i]._cardId)) {
found = true;
break;
}
@@ -5341,7 +5943,7 @@ void Scene1337::subCF31D() {
if (found) {
tmpVal = 0;
- subC34A1(&_arrunkObj1337[1]._arr1[i], &_arrunkObj1337[1]._arr3[0]);
+ subC34A1(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[1]._delayPile[0]);
}
}
}
@@ -5357,7 +5959,7 @@ void Scene1337::subCF31D() {
tmpVal = 0;
for (int j = 0; j <= 7; j++) {
- if (_arrunkObj1337[1]._arr2[j]._field34 == _arrunkObj1337[1]._arr1[tmpIndx]._field34) {
+ if (_gameBoardSide[1]._outpostStation[j]._cardId == _gameBoardSide[1]._handCard[tmpIndx]._cardId) {
tmpVal = 1;
break;
}
@@ -5367,18 +5969,18 @@ void Scene1337::subCF31D() {
break;
for (int j = 0; j <= 7; j++) {
- if (_arrunkObj1337[1]._arr2[j]._field34 == 1) {
- if (!subC2687(_arrunkObj1337[1]._arr3[0]._field34)) {
+ if (_gameBoardSide[1]._outpostStation[j]._cardId == 1) {
+ if (!subC2687(_gameBoardSide[1]._delayPile[0]._cardId)) {
count = 0;
for (int k = 0; k <= 7; k++) {
- if ((_arrunkObj1337[1]._arr2[k]._field34 > 1) && (_arrunkObj1337[1]._arr2[k]._field34 <= 9))
+ if ((_gameBoardSide[1]._outpostStation[k]._cardId > 1) && (_gameBoardSide[1]._outpostStation[k]._cardId <= 9))
++count;
}
if (count == 7)
_field424A = 1;
- subC33C0(&_arrunkObj1337[1]._arr1[tmpIndx], &_arrunkObj1337[1]._arr2[j]);
+ subC33C0(&_gameBoardSide[1]._handCard[tmpIndx], &_gameBoardSide[1]._outpostStation[j]);
found = true;
break;
}
@@ -5392,9 +5994,10 @@ void Scene1337::subCF31D() {
tmpVal = subC2719(1);
if (tmpVal != -1) {
for (int i = 0; i <= 7; i++) {
- if ((_arrunkObj1337[1]._arr2[i]._field34 == 0) && (!subC2687(_arrunkObj1337[1]._arr3[0]._field34))) {
- subC340B(&_arrunkObj1337[1]._arr1[tmpVal], &_arrunkObj1337[1]._arr2[i]);
+ if ((_gameBoardSide[1]._outpostStation[i]._cardId == 0) && (!subC2687(_gameBoardSide[1]._delayPile[0]._cardId))) {
+ subC340B(&_gameBoardSide[1]._handCard[tmpVal], &_gameBoardSide[1]._outpostStation[i]);
found = true;
+ break;
}
}
}
@@ -5405,8 +6008,10 @@ void Scene1337::subCF31D() {
tmpVal = subC274D(1);
int tmpVal2 = subC331B(1);
- if ((tmpVal != -1) && ( tmpVal2 != -1))
- subC358E(&_arrunkObj1337[1]._arr1[tmpVal], tmpVal2);
+ if ((tmpVal != -1) && ( tmpVal2 != -1)) {
+ subC358E(&_gameBoardSide[1]._handCard[tmpVal], tmpVal2);
+ found = true;
+ }
if (found)
return;
@@ -5417,14 +6022,14 @@ void Scene1337::subCF31D() {
int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int i = 0; i <= 3; i++) {
if (rndVal != 1) {
- if ( (_arrunkObj1337[rndVal]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[rndVal]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[rndVal]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[rndVal]._arr1[3]._field34 == 0)) {
+ if ( (_gameBoardSide[rndVal]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[3]._cardId == 0)) {
count = rndVal;
break;
}
-
+ // CHECKME: inside the check on rndVal?
rndVal--;
if (rndVal < 0)
rndVal = 3;
@@ -5432,7 +6037,7 @@ void Scene1337::subCF31D() {
}
if (count != -1) {
- subC318B(1, &_arrunkObj1337[1]._arr1[tmpVal], count);
+ subC318B(1, &_gameBoardSide[1]._handCard[tmpVal], count);
found = true;
}
}
@@ -5443,16 +6048,17 @@ void Scene1337::subCF31D() {
count = -1;
int i;
for (i = 0; i <= 3; i++) {
- tmpVal = subC27B5(_arrunkObj1337[1]._arr1[i]._field34);
+ tmpVal = subC27B5(_gameBoardSide[1]._handCard[i]._cardId);
if (tmpVal != -1) {
int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int j = 0; j <= 3; j++) {
+ //CHECKME: tmpVal or rndVal?
if (tmpVal != 1) {
for (int k = 0; k <= 7; k++) {
- // 'k' is not used in that loop.
+ // CHECKME: 'k' is not used in that loop.
// It looks suspicious.
- if ((_arrunkObj1337[tmpVal]._arr3[0]._field34 == 0) && (subC32B1(tmpVal, _arrunkObj1337[1]._arr1[i]._field34))) {
+ if ((_gameBoardSide[tmpVal]._delayPile[0]._cardId == 0) && (subC32B1(tmpVal, _gameBoardSide[1]._handCard[i]._cardId))) {
count = tmpVal;
break;
}
@@ -5474,22 +6080,19 @@ void Scene1337::subCF31D() {
}
}
- if (found) {
- if (count == -1)
- return;
-
- subC3456(&_arrunkObj1337[1]._arr1[i], &_arrunkObj1337[count]._arr3[0]);
- } else {
+ if (found)
+ subC3456(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[count]._delayPile[0]);
+ else {
int j;
for (j = 0; j <= 3; j++) {
- if (subC27F9(_arrunkObj1337[1]._arr1[j]._field34) != -1) {
+ if (subC27F9(_gameBoardSide[1]._handCard[j]._cardId) != -1) {
count = -1;
int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int l = 0; l <= 3; l++) {
if (rndVal != 1) {
for (int m = 0; m <= 7; m++) {
// 'm' is not used in that loop. It looks suspicious.
- if ((_arrunkObj1337[rndVal]._arr3[0]._field34 == 0) && (_arrunkObj1337[1]._arr1[j]._field34 == 1)) {
+ if ((_gameBoardSide[rndVal]._delayPile[0]._cardId == 0) && (_gameBoardSide[1]._handCard[j]._cardId == 1)) {
count = rndVal;
break;
}
@@ -5509,14 +6112,10 @@ void Scene1337::subCF31D() {
}
}
- if (found) {
- if (count == -1)
- return;
-
- subC3456(&_arrunkObj1337[1]._arr1[j], &_arrunkObj1337[count]._arr3[0]);
- } else {
+ if (found)
+ subC3456(&_gameBoardSide[1]._handCard[j], &_gameBoardSide[count]._delayPile[0]);
+ else
subC2835(1);
- }
}
}
@@ -5524,8 +6123,8 @@ void Scene1337::subCF31D() {
void Scene1337::subCF979() {
bool found = true;
- if (_arrunkObj1337[0]._arr3[0]._field34 != 0) {
- switch (_arrunkObj1337[0]._arr3[0]._field34) {
+ if (_gameBoardSide[0]._delayPile[0]._cardId != 0) {
+ switch (_gameBoardSide[0]._delayPile[0]._cardId) {
case 10:
//No break on purpose
case 12:
@@ -5541,7 +6140,7 @@ void Scene1337::subCF979() {
case 20:
//No break on purpose
case 21:
- subC4A39(&_arrunkObj1337[0]._arr3[0]);
+ subC4A39(&_gameBoardSide[0]._delayPile[0]);
found = false;
break;
default:
@@ -5549,7 +6148,7 @@ void Scene1337::subCF979() {
found = false;
for (i = 0; i <= 3; i++) {
- if (subC3386(_arrunkObj1337[0]._arr3[0]._field34, _arrunkObj1337[0]._arr1[i]._field34)) {
+ if (subC3386(_gameBoardSide[0]._delayPile[0]._cardId, _gameBoardSide[0]._handCard[i]._cardId)) {
found = true;
break;
}
@@ -5557,7 +6156,7 @@ void Scene1337::subCF979() {
if (found) {
found = false;
- subC34A1(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[0]._arr3[0]);
+ subC34A1(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[0]._delayPile[0]);
}
break;
}
@@ -5574,7 +6173,7 @@ void Scene1337::subCF979() {
if (tmpVal != -1) {
bool flag = false;
for (int j = 0; j <= 7; j++) {
- if (_arrunkObj1337[0]._arr2[j]._field34 == _arrunkObj1337[0]._arr1[tmpVal]._field34) {
+ if (_gameBoardSide[0]._outpostStation[j]._cardId == _gameBoardSide[0]._handCard[tmpVal]._cardId) {
flag = true;
break;
}
@@ -5582,10 +6181,10 @@ void Scene1337::subCF979() {
if (!flag) {
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[0]._arr2[j]._field34 == 1) && (!subC2687(_arrunkObj1337[0]._arr3[0]._field34))) {
+ if ((_gameBoardSide[0]._outpostStation[j]._cardId == 1) && (!subC2687(_gameBoardSide[0]._delayPile[0]._cardId))) {
int count = 0;
for (int k = 0; k <= 7; k++) {
- if ((_arrunkObj1337[0]._arr2[k]._field34 > 1) && (_arrunkObj1337[0]._arr2[k]._field34 <= 9)) {
+ if ((_gameBoardSide[0]._outpostStation[k]._cardId > 1) && (_gameBoardSide[0]._outpostStation[k]._cardId <= 9)) {
++count;
}
}
@@ -5593,7 +6192,7 @@ void Scene1337::subCF979() {
if (count == 7)
_field424A = 0;
- subC33C0(&_arrunkObj1337[0]._arr1[tmpVal], &_arrunkObj1337[0]._arr2[j]);
+ subC33C0(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[j]);
found = true;
}
}
@@ -5612,8 +6211,8 @@ void Scene1337::subCF979() {
if (tmpVal != -1) {
for (int i = 0; i <= 7; i++) {
- if ((_arrunkObj1337[0]._arr2[i]._field34 == 0) && (!subC2687(_arrunkObj1337[0]._arr3[0]._field34))) {
- subC340B(&_arrunkObj1337[0]._arr1[tmpVal], &_arrunkObj1337[0]._arr2[i]);
+ if ((_gameBoardSide[0]._outpostStation[i]._cardId == 0) && (!subC2687(_gameBoardSide[0]._delayPile[0]._cardId))) {
+ subC340B(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[i]);
found = true;
break;
}
@@ -5626,8 +6225,8 @@ void Scene1337::subCF979() {
tmpVal = subC274D(0);
if (tmpVal != -1) {
for (int i = 0; i <= 7; i++) {
- if (_arrunkObj1337[2]._arr2[i]._field34 != 0) {
- subC358E(&_arrunkObj1337[0]._arr1[tmpVal], 2);
+ if (_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
+ subC358E(&_gameBoardSide[0]._handCard[tmpVal], 2);
found = true;
break;
}
@@ -5639,11 +6238,11 @@ void Scene1337::subCF979() {
tmpVal = subC2781(0);
if (tmpVal != -1) {
- if ( (_arrunkObj1337[2]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[2]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[2]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[2]._arr1[3]._field34 != 0) ) {
- subC318B(0, &_arrunkObj1337[0]._arr1[tmpVal], 2);
+ if ( (_gameBoardSide[2]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[3]._cardId != 0) ) {
+ subC318B(0, &_gameBoardSide[0]._handCard[tmpVal], 2);
found = true;
}
}
@@ -5652,11 +6251,11 @@ void Scene1337::subCF979() {
return;
for (int i = 0; i <= 3; i++) {
- if (subC27B5(_arrunkObj1337[0]._arr1[i]._field34) != -1) {
+ if (subC27B5(_gameBoardSide[0]._handCard[i]._cardId) != -1) {
// The variable 'j' is not used in the inner code of the loop. It's suspect
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[2]._arr3[0]._field34 == 0) && (subC32B1(2, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[2]._arr3[0]);
+ if ((_gameBoardSide[2]._delayPile[0]._cardId == 0) && (subC32B1(2, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayPile[0]);
found = true;
break;
}
@@ -5671,11 +6270,11 @@ void Scene1337::subCF979() {
return;
for (int i = 0; i <= 3; i++) {
- if (subC27F9(_arrunkObj1337[0]._arr1[i]._field34) != -1) {
+ if (subC27F9(_gameBoardSide[0]._handCard[i]._cardId) != -1) {
// The variable 'j' is not used in the inner code of the loop. It's suspect
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[2]._arr3[0]._field34 == 0) && (subC32B1(2, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[2]._arr3[0]);
+ if ((_gameBoardSide[2]._delayPile[0]._cardId == 0) && (subC32B1(2, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayPile[0]);
found = true;
}
}
@@ -5692,7 +6291,7 @@ void Scene1337::subCF979() {
int tmpVal2 = subC331B(0);
if ((tmpVal != -1) && (tmpVal2 != -1)) {
- subC358E(&_arrunkObj1337[0]._arr1[tmpVal], tmpVal2);
+ subC358E(&_gameBoardSide[0]._handCard[tmpVal], tmpVal2);
found = true;
}
@@ -5701,11 +6300,11 @@ void Scene1337::subCF979() {
tmpVal = subC2781(0);
if (tmpVal != -1) {
- if ( (_arrunkObj1337[1]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[3]._field34 != 0) ) {
- subC318B(0, &_arrunkObj1337[0]._arr1[tmpVal], 1);
+ if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
+ subC318B(0, &_gameBoardSide[0]._handCard[tmpVal], 1);
found = true;
}
}
@@ -5714,12 +6313,12 @@ void Scene1337::subCF979() {
return;
for (int i = 0; i <= 3; i++) {
- tmpVal = subC27F9(_arrunkObj1337[0]._arr1[i]._field34);
+ tmpVal = subC27F9(_gameBoardSide[0]._handCard[i]._cardId);
if (tmpVal != -1) {
// The variable 'j' is not used in the inner code of the loop. It's suspect.
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[1]._arr3[0]._field34 == 0) && (subC32B1(1, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[1]._arr3[0]);
+ if ((_gameBoardSide[1]._delayPile[0]._cardId == 0) && (subC32B1(1, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayPile[0]);
found = true;
}
}
@@ -5727,8 +6326,8 @@ void Scene1337::subCF979() {
if (!found) {
// The variable 'j' is not used in the inner code of the loop. It's suspect.
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[3]._arr3[0]._field34 == 0) && (subC32B1(3, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[3]._arr3[0]);
+ if ((_gameBoardSide[3]._delayPile[0]._cardId == 0) && (subC32B1(3, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayPile[0]);
found = true;
}
}
@@ -5743,12 +6342,12 @@ void Scene1337::subCF979() {
return;
for (int i = 0; i <= 3; i++) {
- tmpVal = subC27B5(_arrunkObj1337[0]._arr1[i]._field34);
+ tmpVal = subC27B5(_gameBoardSide[0]._handCard[i]._cardId);
if (tmpVal != -1) {
// The variable 'j' is not used in the inner code of the loop. It's suspect.
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[1]._arr3[0]._field34 == 0) && (subC32B1(1, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[1]._arr3[0]);
+ if ((_gameBoardSide[1]._delayPile[0]._cardId == 0) && (subC32B1(1, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayPile[0]);
found = true;
}
}
@@ -5756,8 +6355,8 @@ void Scene1337::subCF979() {
if (!found) {
// The variable 'j' is not used in the inner code of the loop. It's suspect.
for (int j = 0; j <= 7; j++) {
- if ((_arrunkObj1337[3]._arr3[0]._field34 == 0) && (subC32B1(3, _arrunkObj1337[0]._arr1[i]._field34))) {
- subC3456(&_arrunkObj1337[0]._arr1[i], &_arrunkObj1337[3]._arr3[0]);
+ if ((_gameBoardSide[3]._delayPile[0]._cardId == 0) && (subC32B1(3, _gameBoardSide[0]._handCard[i]._cardId))) {
+ subC3456(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayPile[0]);
found = true;
}
}
@@ -5779,83 +6378,83 @@ void Scene1337::subD026D() {
}
void Scene1337::subD0281() {
- if (subC27F9(this->_arrunkObj1337[2]._arr3[0]._field34) == -1)
+ if (subC27F9(this->_gameBoardSide[2]._delayPile[0]._cardId) == -1)
_unkFctPtr412 = &Scene1337::subD026D;
else
- subC4A39(&_arrunkObj1337[2]._arr3[0]);
+ subC4A39(&_gameBoardSide[2]._delayPile[0]);
}
void Scene1337::subD02CA() {
- _item6._field36 = g_globals->_events._mousePos;
+ _item6._stationPos = g_globals->_events._mousePos;
if (R2_GLOBALS._v57810 == 200) {
int di;
for (di = 0; di < 4; di++) {
- if ((subC2BF8(&_arrunkObj1337[2]._arr1[di], _item6._field36) != 0) && (_arrunkObj1337[2]._arr1[di]._field34 != 0)) {
- _item6._field34 = _arrunkObj1337[2]._arr1[di]._field34;
- _item6._field36 = _arrunkObj1337[2]._arr1[di]._field36;
+ if ((subC2BF8(&_gameBoardSide[2]._handCard[di], _item6._stationPos) != 0) && (_gameBoardSide[2]._handCard[di]._cardId != 0)) {
+ _item6._cardId = _gameBoardSide[2]._handCard[di]._cardId;
+ _item6._stationPos = _gameBoardSide[2]._handCard[di]._stationPos;
// _item6._actorName = _arrunkObj1337[2]._arr1[di]._actorName;
- _item6._fieldE = _arrunkObj1337[2]._arr1[di]._fieldE;
- _item6._field10 = _arrunkObj1337[2]._arr1[di]._field10;
+ _item6._fieldE = _gameBoardSide[2]._handCard[di]._fieldE;
+ _item6._field10 = _gameBoardSide[2]._handCard[di]._field10;
warning("_item6._field12 = _arrunkObj1337[2]._arr1[di]._field12;");
warning("_item6._field14 = _arrunkObj1337[2]._arr1[di]._field14;");
warning("_item6._field16 = _arrunkObj1337[2]._arr1[di]._field16;");
- _item6._sceneRegionId = _arrunkObj1337[2]._arr1[di]._sceneRegionId;
- _item6._position = _arrunkObj1337[2]._arr1[di]._position;
- _item6._yDiff = _arrunkObj1337[2]._arr1[di]._yDiff;
- _item6._bounds = _arrunkObj1337[2]._arr1[di]._bounds;
- _item6._resNum = _arrunkObj1337[2]._arr1[di]._resNum;
- _item6._lookLineNum = _arrunkObj1337[2]._arr1[di]._lookLineNum;
- _item6._talkLineNum = _arrunkObj1337[2]._arr1[di]._talkLineNum;
- _item6._useLineNum = _arrunkObj1337[2]._arr1[di]._useLineNum;
- _item6._action = _arrunkObj1337[2]._arr1[di]._action;
+ _item6._sceneRegionId = _gameBoardSide[2]._handCard[di]._sceneRegionId;
+ _item6._position = _gameBoardSide[2]._handCard[di]._position;
+ _item6._yDiff = _gameBoardSide[2]._handCard[di]._yDiff;
+ _item6._bounds = _gameBoardSide[2]._handCard[di]._bounds;
+ _item6._resNum = _gameBoardSide[2]._handCard[di]._resNum;
+ _item6._lookLineNum = _gameBoardSide[2]._handCard[di]._lookLineNum;
+ _item6._talkLineNum = _gameBoardSide[2]._handCard[di]._talkLineNum;
+ _item6._useLineNum = _gameBoardSide[2]._handCard[di]._useLineNum;
+ _item6._action = _gameBoardSide[2]._handCard[di]._action;
warning("_item6._field0 = _arrunkObj1337[2]._arr1[di]._field0;");
- _item6._object1._updateStartFrame = _arrunkObj1337[2]._arr1[di]._object1._updateStartFrame;
- _item6._object1._walkStartFrame = _arrunkObj1337[2]._arr1[di]._object1._walkStartFrame;
+ _item6._card._updateStartFrame = _gameBoardSide[2]._handCard[di]._card._updateStartFrame;
+ _item6._card._walkStartFrame = _gameBoardSide[2]._handCard[di]._card._walkStartFrame;
// _field2E is named _field3C in R2R
- _item6._object1._field2E = _arrunkObj1337[2]._arr1[di]._object1._field2E;
- _item6._object1._percent = _arrunkObj1337[2]._arr1[di]._object1._percent;
- _item6._object1._priority = _arrunkObj1337[2]._arr1[di]._object1._priority;
- _item6._object1._angle = _arrunkObj1337[2]._arr1[di]._object1._angle;
- _item6._object1._flags = _arrunkObj1337[2]._arr1[di]._object1._flags;
- _item6._object1._xe = _arrunkObj1337[2]._arr1[di]._object1._xe;
- _item6._object1._xs = _arrunkObj1337[2]._arr1[di]._object1._xs;
- _item6._object1._paneRects[0] = _arrunkObj1337[2]._arr1[di]._object1._paneRects[0];
- _item6._object1._paneRects[1] = _arrunkObj1337[2]._arr1[di]._object1._paneRects[1];
- _item6._object1._visage = _arrunkObj1337[2]._arr1[di]._object1._visage;
- _item6._object1._objectWrapper = _arrunkObj1337[2]._arr1[di]._object1._objectWrapper;
- _item6._object1._strip = _arrunkObj1337[2]._arr1[di]._object1._strip;
- _item6._object1._animateMode = _arrunkObj1337[2]._arr1[di]._object1._animateMode;
- _item6._object1._frame = _arrunkObj1337[2]._arr1[di]._object1._frame;
- _item6._object1._endFrame = _arrunkObj1337[2]._arr1[di]._object1._endFrame;
+ _item6._card._field2E = _gameBoardSide[2]._handCard[di]._card._field2E;
+ _item6._card._percent = _gameBoardSide[2]._handCard[di]._card._percent;
+ _item6._card._priority = _gameBoardSide[2]._handCard[di]._card._priority;
+ _item6._card._angle = _gameBoardSide[2]._handCard[di]._card._angle;
+ _item6._card._flags = _gameBoardSide[2]._handCard[di]._card._flags;
+ _item6._card._xe = _gameBoardSide[2]._handCard[di]._card._xe;
+ _item6._card._xs = _gameBoardSide[2]._handCard[di]._card._xs;
+ _item6._card._paneRects[0] = _gameBoardSide[2]._handCard[di]._card._paneRects[0];
+ _item6._card._paneRects[1] = _gameBoardSide[2]._handCard[di]._card._paneRects[1];
+ _item6._card._visage = _gameBoardSide[2]._handCard[di]._card._visage;
+ _item6._card._objectWrapper = _gameBoardSide[2]._handCard[di]._card._objectWrapper;
+ _item6._card._strip = _gameBoardSide[2]._handCard[di]._card._strip;
+ _item6._card._animateMode = _gameBoardSide[2]._handCard[di]._card._animateMode;
+ _item6._card._frame = _gameBoardSide[2]._handCard[di]._card._frame;
+ _item6._card._endFrame = _gameBoardSide[2]._handCard[di]._card._endFrame;
// _field68 is named _field76 in R2R
- _item6._object1._field68 = _arrunkObj1337[2]._arr1[di]._object1._field68;
- _item6._object1._frameChange = _arrunkObj1337[2]._arr1[di]._object1._frameChange;
- _item6._object1._numFrames = _arrunkObj1337[2]._arr1[di]._object1._numFrames;
- _item6._object1._regionIndex = _arrunkObj1337[2]._arr1[di]._object1._regionIndex;
- _item6._object1._mover = _arrunkObj1337[2]._arr1[di]._object1._mover;
- _item6._object1._moveDiff = _arrunkObj1337[2]._arr1[di]._object1._moveDiff;
- _item6._object1._moveRate = _arrunkObj1337[2]._arr1[di]._object1._moveRate;
- _item6._object1._field8A = _arrunkObj1337[2]._arr1[di]._object1._field8A;
- _item6._object1._endAction = _arrunkObj1337[2]._arr1[di]._object1._endAction;
- _item6._object1._regionBitList = _arrunkObj1337[2]._arr1[di]._object1._regionBitList;
+ _item6._card._field68 = _gameBoardSide[2]._handCard[di]._card._field68;
+ _item6._card._frameChange = _gameBoardSide[2]._handCard[di]._card._frameChange;
+ _item6._card._numFrames = _gameBoardSide[2]._handCard[di]._card._numFrames;
+ _item6._card._regionIndex = _gameBoardSide[2]._handCard[di]._card._regionIndex;
+ _item6._card._mover = _gameBoardSide[2]._handCard[di]._card._mover;
+ _item6._card._moveDiff = _gameBoardSide[2]._handCard[di]._card._moveDiff;
+ _item6._card._moveRate = _gameBoardSide[2]._handCard[di]._card._moveRate;
+ _item6._card._actorDestPos = _gameBoardSide[2]._handCard[di]._card._actorDestPos;
+ _item6._card._endAction = _gameBoardSide[2]._handCard[di]._card._endAction;
+ _item6._card._regionBitList = _gameBoardSide[2]._handCard[di]._card._regionBitList;
// _item6._object1._actorName = _arrunkObj1337[2]._arr1[di]._object1._actorName;
- _item6._object1._fieldE = _arrunkObj1337[2]._arr1[di]._object1._fieldE;
- _item6._object1._field10 = _arrunkObj1337[2]._arr1[di]._object1._field10;
+ _item6._card._fieldE = _gameBoardSide[2]._handCard[di]._card._fieldE;
+ _item6._card._field10 = _gameBoardSide[2]._handCard[di]._card._field10;
warning("_item6._object1._field12 = _arrunkObj1337[2]._arr1[di]._object1._field12;");
warning("_item6._object1._field14 = _arrunkObj1337[2]._arr1[di]._object1._field14;");
warning("_item6._object1._field16 = _arrunkObj1337[2]._arr1[di]._object1._field16;");
- _item6._object1 = _arrunkObj1337[2]._arr1[di]._object1;
+ _item6._card = _gameBoardSide[2]._handCard[di]._card;
}
}
if (di == 4) {
- subCDB90(1, _item6._field36);
+ subCDB90(1, _item6._stationPos);
subD0281();
return;
}
} else if (R2_GLOBALS._v57810 == 300) {
- subCDB90(3, _item6._field36);
+ subCDB90(3, _item6._stationPos);
subD0281();
return;
} else {
@@ -5865,7 +6464,7 @@ void Scene1337::subD02CA() {
}
// That continues the block when R2_GLOBALS._v57810 == 200 and di != 4
- subD18B5(1332, _item6._object1._strip, _item6._object1._frame);
+ setCursorData(1332, _item6._card._strip, _item6._card._frame);
R2_GLOBALS._sceneObjects->draw();
Event event;
bool found = false;
@@ -5873,23 +6472,23 @@ void Scene1337::subD02CA() {
for (;;) {
if ( ((g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN)) && (event.btnState == BTNSHIFT_RIGHT))
|| (g_globals->_events.getEvent(event, EVENT_KEYPRESS)) ){
- _item6._field36 = g_globals->_events._mousePos;
+ _item6._stationPos = g_globals->_events._mousePos;
found_di = false;
for (int i = 0; i <= 3; i ++) {
- if (subC2BF8(&_arrunkObj1337[2]._arr1[i], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if (_arrunkObj1337[2]._arr1[i]._field34 == 0) {
- _arrunkObj1337[2]._arr1[i]._field34 = _item6._field34;
- _arrunkObj1337[2]._arr1[i]._object1.postInit();
- _arrunkObj1337[2]._arr1[i]._object1.hide();
- _arrunkObj1337[2]._arr1[i]._object1.setVisage(1332);
- _arrunkObj1337[2]._arr1[i]._object1.setPosition(_arrunkObj1337[2]._arr1[i]._field36, 0);
- _arrunkObj1337[2]._arr1[i]._object1.fixPriority(170);
- setAnimationInfo(&_arrunkObj1337[2]._arr1[i]);
- subD18B5(5, 1, 4);
+ if (subC2BF8(&_gameBoardSide[2]._handCard[i], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if (_gameBoardSide[2]._handCard[i]._cardId == 0) {
+ _gameBoardSide[2]._handCard[i]._cardId = _item6._cardId;
+ _gameBoardSide[2]._handCard[i]._card.postInit();
+ _gameBoardSide[2]._handCard[i]._card.hide();
+ _gameBoardSide[2]._handCard[i]._card.setVisage(1332);
+ _gameBoardSide[2]._handCard[i]._card.setPosition(_gameBoardSide[2]._handCard[i]._stationPos, 0);
+ _gameBoardSide[2]._handCard[i]._card.fixPriority(170);
+ setAnimationInfo(&_gameBoardSide[2]._handCard[i]);
+ setCursorData(5, 1, 4);
found = true;
- _field423E--;
- _field4244 = 0;
+ _currentPlayerNumb--;
+ _field4244 = false;
subC20F9();
} else {
actionDisplay(1330, 127, 159, 10, 1, 200, 0, 7, 0, 154, 154);
@@ -5900,68 +6499,68 @@ void Scene1337::subD02CA() {
}
if ((!found) && (!found_di)) {
- if (subC2BF8(&_item7, Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ if (subC2BF8(&_discardPile, Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
subC4A39(&_item6);
} else if (!found) {
bool foundVar4;
int i;
- if (_item6._field34 == 1) {
+ if (_item6._cardId == 1) {
foundVar4 = false;
for (i = 0; i <= 7; i++) {
- if (subC2BF8(&_arrunkObj1337[2]._arr2[i], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ if (subC2BF8(&_gameBoardSide[2]._outpostStation[i], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
foundVar4 = true;
break;
}
}
- if ((foundVar4) && (_arrunkObj1337[2]._arr2[i]._field34 == 0)) {
- if (subC27B5(_arrunkObj1337[2]._arr3[0]._field34) != -1) {
+ if ((foundVar4) && (_gameBoardSide[2]._outpostStation[i]._cardId == 0)) {
+ if (subC27B5(_gameBoardSide[2]._delayPile[0]._cardId) != -1) {
actionDisplay(1330, 55, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else {
- subC340B(&_item6, &_arrunkObj1337[2]._arr2[i]);
+ subC340B(&_item6, &_gameBoardSide[2]._outpostStation[i]);
return;
}
} else {
actionDisplay(1330, 56, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
- } else if (_item6._field34 <= 9) {
+ } else if (_item6._cardId <= 9) {
foundVar4 = false;
for (i = 0; i <= 7; i++) {
- if (subC2BF8(&_arrunkObj1337[2]._arr2[i], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ if (subC2BF8(&_gameBoardSide[2]._outpostStation[i], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
foundVar4 = true;
break;
}
}
- if ((foundVar4) && (_arrunkObj1337[2]._arr2[i]._field34 == 1)) {
+ if ((foundVar4) && (_gameBoardSide[2]._outpostStation[i]._cardId == 1)) {
foundVar4 = false;
int j;
for (j = 0; j <= 7; j++) {
- if (_item6._field34 == _arrunkObj1337[2]._arr2[j]._field34) {
+ if (_item6._cardId == _gameBoardSide[2]._outpostStation[j]._cardId) {
foundVar4 = true;
break;
}
}
if (foundVar4) {
actionDisplay(1330, 34, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (subC27B5(_arrunkObj1337[2]._arr3[0]._field34) != -1) {
+ } else if (subC27B5(_gameBoardSide[2]._delayPile[0]._cardId) != -1) {
actionDisplay(1330, 35, 159, 10, 1, 200, 0, 7, 0, 154, 154);
} else {
if (j == 7)
_field424A = 2;
- subC33C0(&_item6, &_arrunkObj1337[2]._arr2[i]);
+ subC33C0(&_item6, &_gameBoardSide[2]._outpostStation[i]);
return;
}
} else {
actionDisplay(1330, 37, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
} else {
- if ((_item6._field34 == 26) || (_item6._field34 == 30) ||(_item6._field34 == 32) || (_item6._field34 == 28)) {
- if (subC2BF8(&_arrunkObj1337[2]._arr3[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ if ((_item6._cardId == 26) || (_item6._cardId == 30) ||(_item6._cardId == 32) || (_item6._cardId == 28)) {
+ if (subC2BF8(&_gameBoardSide[2]._delayPile[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
actionDisplay(1330, 42, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!subC3386(_arrunkObj1337[2]._arr3[0]._field34, _item6._field34)) {
- if (_arrunkObj1337[2]._arr3[0]._field34 != 0) {
- switch (_arrunkObj1337[2]._arr3[0]._field34) {
+ } else if (!subC3386(_gameBoardSide[2]._delayPile[0]._cardId, _item6._cardId)) {
+ if (_gameBoardSide[2]._delayPile[0]._cardId != 0) {
+ switch (_gameBoardSide[2]._delayPile[0]._cardId) {
case 11:
actionDisplay(1330, 68, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -5981,15 +6580,15 @@ void Scene1337::subD02CA() {
actionDisplay(1330, 41, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
} else {
- subC34A1(&_item6, &_arrunkObj1337[2]._arr3[0]);
+ subC34A1(&_item6, &_gameBoardSide[2]._delayPile[0]);
return;
}
} else {
- if ((subC27F9(_item6._field34) == -1) && (subC27B5(_item6._field34) == -1)) {
- if (_item6._field34 == 13) {
- if (subC2BF8(&_arrunkObj1337[0]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ if ((subC27F9(_item6._cardId) == -1) && (subC27B5(_item6._cardId) == -1)) {
+ if (_item6._cardId == 13) {
+ if (subC2BF8(&_gameBoardSide[0]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
for (int k = 0; k <= 7; k++) {
- if (_arrunkObj1337[0]._arr2[k]._field34 != 0) {
+ if (_gameBoardSide[0]._outpostStation[k]._cardId != 0) {
found = true;
subC358E(&_item6, 0);
}
@@ -5997,18 +6596,18 @@ void Scene1337::subD02CA() {
if (!found)
actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (subC2BF8(&_arrunkObj1337[3]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ } else if (subC2BF8(&_gameBoardSide[3]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
for (int k = 0; k <= 7; k++) {
- if (_arrunkObj1337[3]._arr2[k]._field34 != 0) {
+ if (_gameBoardSide[3]._outpostStation[k]._cardId != 0) {
found = true;
subC358E(&_item6, 3);
}
}
if (!found)
actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (subC2BF8(&_arrunkObj1337[1]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
+ } else if (subC2BF8(&_gameBoardSide[1]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
for (int k = 0; k <= 7; k++) {
- if (_arrunkObj1337[1]._arr2[k]._field34 == 0) {
+ if (_gameBoardSide[1]._outpostStation[k]._cardId == 0) {
found = true;
subC358E(&_item6, 1);
}
@@ -6018,48 +6617,48 @@ void Scene1337::subD02CA() {
} else {
actionDisplay(1330, 128, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
- } else if (_item6._field34 == 25) {
+ } else if (_item6._cardId == 25) {
int k;
- if (subC2BF8(&_arrunkObj1337[0]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if ( (_arrunkObj1337[0]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[0]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[0]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[0]._arr1[3]._field34 != 0) ) {
+ if (subC2BF8(&_gameBoardSide[0]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if ( (_gameBoardSide[0]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[3]._cardId != 0) ) {
for (k = 0; k <= 3; k++){
- if (_arrunkObj1337[2]._arr1[k]._field34 == 0)
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
break;
}
- subC318B(2, &_arrunkObj1337[2]._arr1[k], 0);
+ subC318B(2, &_gameBoardSide[2]._handCard[k], 0);
return;
} else {
actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
- } else if (subC2BF8(&_arrunkObj1337[1]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if ( (_arrunkObj1337[1]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[1]._arr1[3]._field34 != 0) ) {
+ } else if (subC2BF8(&_gameBoardSide[1]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
for (k = 0; k <= 3; k++){
- if (_arrunkObj1337[2]._arr1[k]._field34 == 0)
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
break;
}
- subC318B(2, &_arrunkObj1337[2]._arr1[k], 1);
+ subC318B(2, &_gameBoardSide[2]._handCard[k], 1);
return;
} else {
actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
}
- if (subC2BF8(&_arrunkObj1337[3]._arr4[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if ( (_arrunkObj1337[3]._arr1[0]._field34 != 0)
- || (_arrunkObj1337[3]._arr1[1]._field34 != 0)
- || (_arrunkObj1337[3]._arr1[2]._field34 != 0)
- || (_arrunkObj1337[3]._arr1[3]._field34 != 0) ) {
+ if (subC2BF8(&_gameBoardSide[3]._arr4[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if ( (_gameBoardSide[3]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[3]._cardId != 0) ) {
for (k = 0; k <= 3; k++){
- if (_arrunkObj1337[2]._arr1[k]._field34 == 0)
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
break;
}
- subC318B(2, &_arrunkObj1337[2]._arr1[k], 3);
+ subC318B(2, &_gameBoardSide[2]._handCard[k], 3);
return;
} else {
actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
@@ -6067,17 +6666,17 @@ void Scene1337::subD02CA() {
} else {
actionDisplay(1330, 129, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
- } else if (_item6._field34 == 29) {
+ } else if (_item6._cardId == 29) {
actionDisplay(1330, 136, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (_item6._field34 == 27) {
+ } else if (_item6._cardId == 27) {
actionDisplay(1330, 137, 159, 10, 1, 200, 0, 7, 0, 154, 154);
}
} else {
- if (subC2BF8(&_arrunkObj1337[0]._arr3[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if (_arrunkObj1337[0]._arr3[0]._field34 != 0) {
+ if (subC2BF8(&_gameBoardSide[0]._delayPile[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if (_gameBoardSide[0]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!subC32B1(0, _item6._field34)) {
- switch (_item6._field34) {
+ } else if (!subC32B1(0, _item6._cardId)) {
+ switch (_item6._cardId) {
case 10:
actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -6106,14 +6705,14 @@ void Scene1337::subD02CA() {
break;
}
} else {
- subC3456(&_item6, &_arrunkObj1337[0]._arr3[0]);
+ subC3456(&_item6, &_gameBoardSide[0]._delayPile[0]);
found = true;
}
- } else if (subC2BF8(&_arrunkObj1337[3]._arr3[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if (_arrunkObj1337[3]._arr3[0]._field34 != 0) {
+ } else if (subC2BF8(&_gameBoardSide[3]._delayPile[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if (_gameBoardSide[3]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!subC32B1(3, _item6._field34)) {
- switch (_item6._field34) {
+ } else if (!subC32B1(3, _item6._cardId)) {
+ switch (_item6._cardId) {
case 10:
actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -6142,14 +6741,14 @@ void Scene1337::subD02CA() {
break;
}
} else {
- subC3456(&_item6, &_arrunkObj1337[3]._arr3[0]);
+ subC3456(&_item6, &_gameBoardSide[3]._delayPile[0]);
found = true;
}
- } else if (subC2BF8(&_arrunkObj1337[1]._arr3[0], Common::Point(_item6._field36.x + 12, _item6._field36.y + 12)) != 0) {
- if (_arrunkObj1337[1]._arr3[0]._field34 != 0) {
+ } else if (subC2BF8(&_gameBoardSide[1]._delayPile[0], Common::Point(_item6._stationPos.x + 12, _item6._stationPos.y + 12)) != 0) {
+ if (_gameBoardSide[1]._delayPile[0]._cardId != 0) {
actionDisplay(1330, 19, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!subC32B1(1, _item6._field34)) {
- switch (_item6._field34) {
+ } else if (!subC32B1(1, _item6._cardId)) {
+ switch (_item6._cardId) {
case 10:
actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -6178,7 +6777,7 @@ void Scene1337::subD02CA() {
break;
}
} else {
- subC3456(&_item6, &_arrunkObj1337[1]._arr3[0]);
+ subC3456(&_item6, &_gameBoardSide[1]._delayPile[0]);
found = true;
}
} else {
@@ -6226,42 +6825,48 @@ void Scene1337::subD183F(int arg1, int arg2) {
}
}
-void Scene1337::subD18B5(int resNum, int rlbNum, int arg3) {
- warning("STUBBED lvl3 Scene1337::subD18B5()");
+void Scene1337::setCursorData(int resNum, int rlbNum, int frameNum) {
+ // Change the mouse cursor and set it to the desired frame (if different than 0)
+ if (!frameNum)
+ return;
+
+ uint size;
+ byte *cursor = g_resourceManager->getSubResource(resNum, rlbNum, frameNum, &size);
+ // Decode the cursor
+ GfxSurface s = surfaceFromRes(cursor);
+
+ Graphics::Surface surface = s.lockSurface();
+ const byte *cursorData = (const byte *)surface.getPixels();
+ CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
+ s.unlockSurface();
}
-int Scene1337::subD18F5() {
+void Scene1337::subD18F5() {
if (R2_GLOBALS._v57709 == 0)
// The cursor looks... very dummy
// To be checked
warning("TODO: CursorManager.setData(R2_GLOBALS.off_57705)");
++R2_GLOBALS._v57709;
-
- return R2_GLOBALS._v57709;
}
-int Scene1337::subD1917() {
+void Scene1337::subD1917() {
if (R2_GLOBALS._v57709 != 0) {
R2_GLOBALS._v57709--;
if (R2_GLOBALS._v57709 != 0)
warning("FIXME: subD195F(_width, _data);");
}
-
- return R2_GLOBALS._v57709;
}
-int Scene1337::subD1940(bool flag) {
+void Scene1337::subD1940(bool flag) {
if (flag)
++R2_GLOBALS._v5780C;
else if (R2_GLOBALS._v5780C != 0)
--R2_GLOBALS._v5780C;
-
- return R2_GLOBALS._v5780C;
}
void Scene1337::subD195F(int arg1, int arg2) {
- subD18B5(5, arg1, arg2);
+ setCursorData(5, arg1, arg2);
}
void Scene1337::subD1975(int arg1, int arg2) {
@@ -6293,62 +6898,63 @@ void Scene1337::subD1A48(int arg1) {
* Scene 1500 - Cutscene: Ship landing
*
*--------------------------------------------------------------------------*/
+
void Scene1500::postInit(SceneObjectList *OwnerList) {
loadScene(1500);
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E.top = 0;
- R2_GLOBALS._v5589E.bottom = 200;
setZoomPercents(170, 13, 240, 100);
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
scalePalette(65, 65, 65);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor2.postInit();
- _actor2.setup(1401, 1, 1);
- _actor2._effect = 5;
- _actor2.fixPriority(10);
- _actor2._field9C = _field312;
+ _starshipShadow.postInit();
+ _starshipShadow.setup(1401, 1, 1);
+ _starshipShadow._effect = EFFECT_SHADOW_MAP;
+ _starshipShadow.fixPriority(10);
+ _starshipShadow._shadowMap = _shadowPaletteMap;
- _actor1.postInit();
- _actor1.setup(1400, 1, 1);
- _actor1._moveDiff = Common::Point(1, 1);
- _actor1._linkedActor = &_actor2;
+ _starship.postInit();
+ _starship.setup(1400, 1, 1);
+ _starship._moveDiff = Common::Point(1, 1);
+ _starship._linkedActor = &_starshipShadow;
if (R2_GLOBALS._sceneManager._previousScene != 1010) {
- _actor4.postInit();
- _actor4.setup(1401, 2, 1);
- _actor4._effect = 5;
- _actor4.fixPriority(10);
- _actor4._field9C = _field312;
+ _smallShipShadow.postInit();
+ _smallShipShadow.setup(1401, 2, 1);
+ _smallShipShadow._effect = EFFECT_SHADOW_MAP;
+ _smallShipShadow.fixPriority(10);
+ _smallShipShadow._shadowMap = _shadowPaletteMap;
- _actor3.postInit();
- _actor3._moveRate = 30;
- _actor3._moveDiff = Common::Point(1, 1);
- _actor3._linkedActor = &_actor4;
+ _smallShip.postInit();
+ _smallShip._moveRate = 30;
+ _smallShip._moveDiff = Common::Point(1, 1);
+ _smallShip._linkedActor = &_smallShipShadow;
}
if (R2_GLOBALS._sceneManager._previousScene == 300) {
- _actor1.setPosition(Common::Point(189, 139), 5);
+ _starship.setPosition(Common::Point(189, 139), 5);
- _actor3.setup(1400, 1, 2);
- _actor3.setPosition(Common::Point(148, 108), 0);
+ _smallShip.setup(1400, 1, 2);
+ _smallShip.setPosition(Common::Point(148, 108), 0);
_sceneMode = 20;
R2_GLOBALS._sound1.play(110);
} else if (R2_GLOBALS._sceneManager._previousScene == 1550) {
- _actor1.setPosition(Common::Point(189, 139), 5);
+ _starship.setPosition(Common::Point(189, 139), 5);
- _actor3.setup(1400, 2, 1);
- _actor3.changeZoom(-1);
- _actor3.setPosition(Common::Point(298, 258), 5);
+ _smallShip.setup(1400, 2, 1);
+ _smallShip.changeZoom(-1);
+ _smallShip.setPosition(Common::Point(298, 258), 5);
_sceneMode = 10;
R2_GLOBALS._sound1.play(106);
} else {
- _actor1.setPosition(Common::Point(289, 239), -30);
+ _starship.setPosition(Common::Point(289, 239), -30);
_sceneMode = 0;
R2_GLOBALS._sound1.play(102);
}
@@ -6356,9 +6962,8 @@ void Scene1500::postInit(SceneObjectList *OwnerList) {
}
void Scene1500::remove() {
- R2_GLOBALS._v5589E.top = 3;
- R2_GLOBALS._v5589E.bottom = 168;
R2_GLOBALS._uiElements._active = true;
+ R2_GLOBALS._uiElements._visible = true;
SceneExt::remove();
}
@@ -6370,8 +6975,8 @@ void Scene1500::signal() {
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
// No break on purpose
case 1:
- if (_actor1._yDiff < 50) {
- _actor1.setPosition(Common::Point(289, 239), _actor1._yDiff + 1);
+ if (_starship._yDiff < 50) {
+ _starship.setPosition(Common::Point(289, 239), _starship._yDiff + 1);
_sceneMode = 1;
}
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
@@ -6379,12 +6984,12 @@ void Scene1500::signal() {
case 2: {
Common::Point pt(189, 139);
NpcMover *mover = new NpcMover();
- _actor1.addMover(mover, &pt, this);
+ _starship.addMover(mover, &pt, this);
}
break;
case 3:
- if (_actor1._yDiff > 5) {
- _actor1.setPosition(Common::Point(189, 139), _actor1._yDiff - 1);
+ if (_starship._yDiff > 5) {
+ _starship.setPosition(Common::Point(189, 139), _starship._yDiff - 1);
_sceneMode = 3;
}
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
@@ -6403,7 +7008,7 @@ void Scene1500::signal() {
case 11: {
Common::Point pt(148, 108);
NpcMover *mover = new NpcMover();
- _actor3.addMover(mover, &pt, this);
+ _smallShip.addMover(mover, &pt, this);
}
break;
case 12:
@@ -6412,13 +7017,13 @@ void Scene1500::signal() {
case 21: {
Common::Point pt(-2, -42);
NpcMover *mover = new NpcMover();
- _actor3.addMover(mover, &pt, NULL);
+ _smallShip.addMover(mover, &pt, NULL);
signal();
}
break;
case 22:
- if (_actor1._yDiff < 50) {
- _actor1.setPosition(Common::Point(189, 139), _actor1._yDiff + 1);
+ if (_starship._yDiff < 50) {
+ _starship.setPosition(Common::Point(189, 139), _starship._yDiff + 1);
_sceneMode = 22;
}
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
@@ -6426,11 +7031,11 @@ void Scene1500::signal() {
case 23: {
Common::Point pt(-13, -61);
NpcMover *mover = new NpcMover();
- _actor1.addMover(mover, &pt, this);
+ _starship.addMover(mover, &pt, this);
}
break;
case 24:
- R2_GLOBALS._sceneManager.changeScene(300);
+ R2_GLOBALS._sceneManager.changeScene(1550);
break;
default:
break;
@@ -6439,9 +7044,9 @@ void Scene1500::signal() {
void Scene1500::dispatch() {
if (_sceneMode > 10) {
- float yDiff = sqrt((float) (_actor3._position.x * _actor3._position.x) + (_actor3._position.y * _actor3._position.y));
+ float yDiff = sqrt((float) (_smallShip._position.x * _smallShip._position.x) + (_smallShip._position.y * _smallShip._position.y));
if (yDiff > 6)
- _actor3.setPosition(_actor3._position, (int) yDiff);
+ _smallShip.setPosition(_smallShip._position, (int) yDiff);
}
Scene::dispatch();
@@ -6451,6 +7056,7 @@ void Scene1500::dispatch() {
* Scene 1525 - Cutscene - Ship
*
*--------------------------------------------------------------------------*/
+
void Scene1525::postInit(SceneObjectList *OwnerList) {
loadScene(1525);
R2_GLOBALS._uiElements._active = false;
@@ -6490,9 +7096,10 @@ void Scene1525::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1530 - Cutscene - Elevator
+ * Scene 1530 - Cutscene - Crashing on Rimwall
*
*--------------------------------------------------------------------------*/
+
void Scene1530::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene == 1000)
loadScene(1650);
@@ -6503,6 +7110,7 @@ void Scene1530::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._uiElements._active = false;
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
@@ -6526,15 +7134,15 @@ void Scene1530::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveRate = 30;
R2_GLOBALS._player._moveDiff = Common::Point(4, 1);
- _actor2.postInit();
- _actor2.setup(1516, 7, 1);
- _actor2.setPosition(Common::Point(121, 41));
- _actor2.animate(ANIM_MODE_2, NULL);
+ _leftReactor.postInit();
+ _leftReactor.setup(1516, 7, 1);
+ _leftReactor.setPosition(Common::Point(121, 41));
+ _leftReactor.animate(ANIM_MODE_2, NULL);
- _actor3.postInit();
- _actor3.setup(1516, 8, 1);
- _actor3.setPosition(Common::Point(107, 116));
- _actor3.animate(ANIM_MODE_2, NULL);
+ _rightReactor.postInit();
+ _rightReactor.setup(1516, 8, 1);
+ _rightReactor.setPosition(Common::Point(107, 116));
+ _rightReactor.animate(ANIM_MODE_2, NULL);
R2_GLOBALS._player.disableControl();
Common::Point pt(480, 75);
@@ -6544,14 +7152,14 @@ void Scene1530::postInit(SceneObjectList *OwnerList) {
_sceneMode = 1;
} else {
- _actor1.postInit();
- _actor1._effect = 1;
+ _seeker.postInit();
+ _seeker._effect = EFFECT_SHADED;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- setAction(&_sequenceManager, this, 1530, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 1530, &R2_GLOBALS._player, &_seeker, NULL);
_sceneMode = 2;
}
@@ -6584,28 +7192,28 @@ void Scene1530::dispatch() {
int16 x = R2_GLOBALS._player._position.x;
int16 y = R2_GLOBALS._player._position.y;
- _actor2.setPosition(Common::Point(x - 39, y - 85));
- _actor3.setPosition(Common::Point(x - 53, y - 9));
+ _leftReactor.setPosition(Common::Point(x - 39, y - 85));
+ _rightReactor.setPosition(Common::Point(x - 53, y - 9));
Scene::dispatch();
}
/*--------------------------------------------------------------------------
- * Scene 1550 -
+ * Scene 1550 - Spaceport
*
*--------------------------------------------------------------------------*/
-Scene1550::UnkObj15501::UnkObj15501() {
- _fieldA4 = _fieldA6 = 0;
+
+Scene1550::Junk::Junk() {
+ _junkNumber = 0;
}
-void Scene1550::UnkObj15501::synchronize(Serializer &s) {
+void Scene1550::Junk::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
+ s.syncAsSint16LE(_junkNumber);
}
-bool Scene1550::UnkObj15501::startAction(CursorType action, Event &event) {
+bool Scene1550::Junk::startAction(CursorType action, Event &event) {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -6624,13 +7232,13 @@ bool Scene1550::UnkObj15501::startAction(CursorType action, Event &event) {
if (_visage == 1561) {
switch (_frame) {
case 2:
- SceneItem::display(1550, 23, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 23, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
case 3:
- SceneItem::display(1550, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
case 4:
- SceneItem::display(1550, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
default:
break;
@@ -6638,13 +7246,13 @@ bool Scene1550::UnkObj15501::startAction(CursorType action, Event &event) {
} else {
switch ((((_strip - 1) * 5) + _frame) % 3) {
case 0:
- SceneItem::display(1550, 62, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 62, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
case 1:
- SceneItem::display(1550, 53, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 53, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
case 2:
- SceneItem::display(1550, 76, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 76, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
default:
break;
@@ -6658,131 +7266,131 @@ bool Scene1550::UnkObj15501::startAction(CursorType action, Event &event) {
}
}
-Scene1550::UnkObj15502::UnkObj15502() {
- _fieldA4 = 0;
+Scene1550::ShipComponent::ShipComponent() {
+ _componentId = 0;
}
-void Scene1550::UnkObj15502::synchronize(Serializer &s) {
+void Scene1550::ShipComponent::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
+ s.syncAsSint16LE(_componentId);
}
-bool Scene1550::UnkObj15502::startAction(CursorType action, Event &event) {
+bool Scene1550::ShipComponent::startAction(CursorType action, Event &event) {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if (_fieldA4 == 8) {
- scene->_field412 = 1;
+ if (_componentId == 8) {
+ scene->_dontExit = true;
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1576;
else
scene->_sceneMode = 1584;
- // strcpy(scene->_arrUnkObj15502[7]._actorName, 'hatch');
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[7], NULL);
+ // strcpy(scene->_shipComponents[7]._actorName, 'hatch');
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[7], NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case CURSOR_LOOK:
- if (_fieldA4 == 8)
- SceneItem::display(1550, 75, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ if (_componentId == 8)
+ SceneItem::display(1550, 75, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
else if (_frame == 1)
- SceneItem::display(1550, 70, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 70, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
else
- SceneItem::display(1550, 71, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 71, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
case R2_FUEL_CELL:
- scene->_field412 = 1;
- if (_fieldA4 == 6) {
+ scene->_dontExit = true;
+ if (_componentId == 6) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_wreckage2.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1574;
else
scene->_sceneMode = 1582;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[5], &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[5], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_GYROSCOPE:
- scene->_field412 = 1;
- if (_fieldA4 == 3) {
+ scene->_dontExit = true;
+ if (_componentId == 3) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_wreckage2.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1571;
else
scene->_sceneMode = 1581;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[2], &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[2], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_GUIDANCE_MODULE:
- scene->_field412 = 1;
- if (_fieldA4 == 1) {
+ scene->_dontExit = true;
+ if (_componentId == 1) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_wreckage2.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1569;
else
scene->_sceneMode = 1579;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[0], &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[0], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_THRUSTER_VALVE:
- scene->_field412 = 1;
- if (_fieldA4 == 4) {
+ scene->_dontExit = true;
+ if (_componentId == 4) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1572;
- scene->_actor1.postInit();
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[3], &scene->_actor1, NULL);
+ scene->_wreckage2.postInit();
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[3], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_RADAR_MECHANISM:
- scene->_field412 = 1;
- if (_fieldA4 == 2) {
+ scene->_dontExit = true;
+ if (_componentId == 2) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_wreckage2.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1570;
else
scene->_sceneMode = 1580;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[1], &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[1], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_IGNITOR:
- scene->_field412 = 1;
- if (_fieldA4 == 5) {
+ scene->_dontExit = true;
+ if (_componentId == 5) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1573;
- scene->_actor1.postInit();
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[4], &scene->_actor1, NULL);
+ scene->_wreckage2.postInit();
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[4], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
break;
case R2_BATTERY:
- scene->_field412 = 1;
- if (_fieldA4 == 7) {
+ scene->_dontExit = true;
+ if (_componentId == 7) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_wreckage2.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1575;
else
scene->_sceneMode = 1583;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[6], &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_shipComponents[6], &scene->_wreckage2, NULL);
return true;
}
return SceneActor::startAction(action, event);
@@ -6793,47 +7401,48 @@ bool Scene1550::UnkObj15502::startAction(CursorType action, Event &event) {
}
}
-void Scene1550::UnkObj15502::subA5CDF(int strip) {
- _fieldA4 = strip;
+void Scene1550::ShipComponent::setupShipComponent(int componentId) {
+ _componentId = componentId;
postInit();
- setup(1517, _fieldA4, 1);
- switch (_fieldA4 - 1) {
- case 0:
+ setup(1517, _componentId, 1);
+
+ switch (_componentId) {
+ case 1:
if (R2_INVENTORY.getObjectScene(R2_GUIDANCE_MODULE) == 0)
setFrame(5);
setPosition(Common::Point(287, 85));
break;
- case 1:
+ case 2:
if (R2_INVENTORY.getObjectScene(R2_RADAR_MECHANISM) == 0)
setFrame(5);
setPosition(Common::Point(248, 100));
break;
- case 2:
- if (R2_INVENTORY.getObjectScene(R2_DIAGNOSTICS_DISPLAY) == 0)
+ case 3:
+ if (R2_INVENTORY.getObjectScene(R2_GYROSCOPE) == 0)
setFrame(5);
setPosition(Common::Point(217, 85));
break;
- case 3:
- if (R2_INVENTORY.getObjectScene(R2_THRUSTER_VALVE))
+ case 4:
+ if (R2_INVENTORY.getObjectScene(R2_THRUSTER_VALVE) == 0)
setFrame(5);
setPosition(Common::Point(161, 121));
break;
- case 4:
- if (R2_INVENTORY.getObjectScene(R2_IGNITOR))
+ case 5:
+ if (R2_INVENTORY.getObjectScene(R2_IGNITOR) == 0)
setFrame(5);
setPosition(Common::Point(117, 121));
break;
- case 5:
- if (R2_INVENTORY.getObjectScene(R2_FUEL_CELL))
+ case 6:
+ if (R2_INVENTORY.getObjectScene(R2_FUEL_CELL) == 0)
setFrame(5);
setPosition(Common::Point(111, 85));
break;
- case 6:
- if (R2_INVENTORY.getObjectScene(R2_BATTERY))
+ case 7:
+ if (R2_INVENTORY.getObjectScene(R2_BATTERY) == 0)
setFrame(5);
setPosition(Common::Point(95, 84));
break;
- case 7: {
+ case 8: {
setup(1516, 1, 1);
setPosition(Common::Point(201, 45));
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
@@ -6846,47 +7455,53 @@ void Scene1550::UnkObj15502::subA5CDF(int strip) {
default:
break;
}
+
+ fixPriority(92);
+ setDetails(1550, 70, -1, -1, 2, (SceneItem *)NULL);
}
-Scene1550::UnkObj15503::UnkObj15503() {
- _fieldA4 = 0;
+Scene1550::DishControlsWindow::DishControl::DishControl() {
+ _controlId = 0;
}
-void Scene1550::UnkObj15503::synchronize(Serializer &s) {
+void Scene1550::DishControlsWindow::DishControl::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
+ s.syncAsSint16LE(_controlId);
}
-bool Scene1550::UnkObj15503::startAction(CursorType action, Event &event) {
- Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1550::DishControlsWindow::DishControl::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- switch (_fieldA4) {
+
+ Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_controlId) {
case 1:
- if (scene->_actor13._frame == 5) {
+ // Button control
+ if (scene->_dish._frame == 5) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 25;
- if (scene->_actor4._frame == 1) {
- scene->setAction(&scene->_sequenceManager1, scene, 1560, &scene->_actor4, NULL);
+ if (scene->_walkway._frame == 1) {
+ scene->setAction(&scene->_sequenceManager1, scene, 1560, &scene->_walkway, NULL);
R2_GLOBALS.setFlag(20);
setFrame(2);
} else {
- scene->setAction(&scene->_sequenceManager1, scene, 1561, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1561, &scene->_walkway, NULL);
R2_GLOBALS.clearFlag(20);
setFrame(1);
}
- scene->_unkArea1.remove();
+ scene->_dishControlsWindow.remove();
}
break;
case 2:
+ // Lever control
R2_GLOBALS._player.disableControl();
- if (scene->_actor13._frame == 1) {
+ if (scene->_dish._frame == 1) {
scene->_sceneMode = 23;
scene->setAction(&scene->_sequenceManager1, scene, 1560, this, NULL);
} else {
- if (scene->_actor4._frame == 1)
+ if (scene->_walkway._frame == 1)
scene->_sceneMode = 24;
else
scene->_sceneMode = 22;
@@ -6899,22 +7514,19 @@ bool Scene1550::UnkObj15503::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1550::UnkArea1550::remove() {
+void Scene1550::DishControlsWindow::remove() {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
- _unkObj155031.remove();
- _unkObj155032.remove();
- // sub201EA is a common part with UnkArea1200
- R2_GLOBALS._sceneItems.remove((SceneItem *)this);
- _areaActor.remove();
- SceneArea::remove();
- R2_GLOBALS._insetUp--;
- //
+ _button.remove();
+ _lever.remove();
+
+ ModalWindow::remove();
+
if ((scene->_sceneMode >= 20) && (scene->_sceneMode <= 29))
return;
R2_GLOBALS._player.disableControl();
- if (scene->_actor4._frame == 1) {
+ if (scene->_walkway._frame == 1) {
scene->_sceneMode = 1559;
scene->setAction(&scene->_sequenceManager1, scene, 1559, &R2_GLOBALS._player, NULL);
} else {
@@ -6923,95 +7535,45 @@ void Scene1550::UnkArea1550::remove() {
}
}
-void Scene1550::UnkArea1550::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
- if (_field20 != R2_GLOBALS._insetUp)
- return;
-
- CursorType cursor = R2_GLOBALS._events.getCursor();
-
- if (_areaActor._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 Scene1550::DishControlsWindow::setup2(int visage, int stripFrameNum, int frameNum,
+ int posX, int posY) {
+ // Call inherited setup
+ ModalWindow::setup2(visage, stripFrameNum, frameNum, posX, posY);
-void Scene1550::UnkArea1550::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
- // UnkArea1200::proc12();
+ // Further setup
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
-
- _areaActor.postInit();
- _areaActor.setup(visage, stripFrameNum, frameNum);
- _areaActor.setPosition(Common::Point(posX, posY));
- _areaActor.fixPriority(250);
- _cursorNum = CURSOR_INVALID;
- scene->_sceneAreas.push_front(this);
- ++R2_GLOBALS._insetUp;
- _field20 = R2_GLOBALS._insetUp;
- //
-
- proc13(1550, 67, -1, -1);
- _unkObj155031.postInit();
- _unkObj155031._fieldA4 = 1;
- if (scene->_actor4._frame == 1)
- _unkObj155031.setup(1559, 3, 1);
+ setup3(1550, 67, -1, -1);
+ _button.postInit();
+ _button._controlId = 1;
+ if (scene->_walkway._frame == 1)
+ _button.setup(1559, 3, 1);
else
- _unkObj155031.setup(1559, 3, 2);
- _unkObj155031.setPosition(Common::Point(142, 79));
- _unkObj155031.fixPriority(251);
- _unkObj155031.setDetails(1550, 68, -1, -1, 2, (SceneItem *) NULL);
-
- _unkObj155032.postInit();
- _unkObj155032._numFrames = 5;
- _unkObj155032._fieldA4 = 2;
- if (scene->_actor13._frame == 1)
- _unkObj155032.setup(1559, 2, 1);
+ _button.setup(1559, 3, 2);
+ _button.setPosition(Common::Point(142, 79));
+ _button.fixPriority(251);
+ _button.setDetails(1550, 68, -1, -1, 2, (SceneItem *) NULL);
+
+ _lever.postInit();
+ _lever._numFrames = 5;
+ _lever._controlId = 2;
+ if (scene->_dish._frame == 1)
+ _lever.setup(1559, 2, 1);
else
- _unkObj155032.setup(1559, 2, 2);
- _unkObj155032.setPosition(Common::Point(156, 103));
- _unkObj155032.fixPriority(251);
- _unkObj155032.setDetails(1550, 69, -1, -1, 2, (SceneItem *) NULL);
+ _lever.setup(1559, 2, 2);
+ _lever.setPosition(Common::Point(156, 103));
+ _lever.fixPriority(251);
+ _lever.setDetails(1550, 69, -1, -1, 2, (SceneItem *) NULL);
}
-void Scene1550::UnkArea1550::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13
- _areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
-}
-
-bool Scene1550::Hotspot1::startAction(CursorType action, Event &event) {
- return SceneHotspot::startAction(action, event);
-}
-
-bool Scene1550::Hotspot3::startAction(CursorType action, Event &event) {
- // Arrays related to this scene are all hacky in the origina: they are based on the impossibility to use Miranda
- assert ((R2_GLOBALS._player._characterIndex == 1) || (R2_GLOBALS._player._characterIndex == 2));
- // The original contains a debug message when CURSOR_TALK is used.
- // This part is totally useless, we could remove it (and the entire function as well)
- if (action == CURSOR_TALK)
- warning("Location: %d/%d - %d", R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex], R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2], k5A4D6[(R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] * 30)] + R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]);
-
+bool Scene1550::WorkingShip::startAction(CursorType action, Event &event) {
return SceneHotspot::startAction(action, event);
}
-bool Scene1550::Actor6::startAction(CursorType action, Event &event) {
+bool Scene1550::Wreckage::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene1550::Actor7::startAction(CursorType action, Event &event) {
+bool Scene1550::Companion::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
@@ -7022,23 +7584,23 @@ bool Scene1550::Actor7::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1550::Actor8::startAction(CursorType action, Event &event) {
+bool Scene1550::AirBag::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
R2_GLOBALS._player.disableControl();
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
- scene->_field412 = 1;
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_dontExit = true;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1552;
else
scene->_sceneMode = 1588;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor8, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_airbag, NULL);
return true;
}
-bool Scene1550::Actor9::startAction(CursorType action, Event &event) {
+bool Scene1550::Joystick::startAction(CursorType action, Event &event) {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -7046,14 +7608,14 @@ bool Scene1550::Actor9::startAction(CursorType action, Event &event) {
scene->_sceneMode = 50;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_stripManager.start(518, scene);
else
scene->_stripManager.start(520, scene);
return true;
break;
case CURSOR_LOOK:
- SceneItem::display(1550, 41, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 41, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
default:
@@ -7061,53 +7623,55 @@ bool Scene1550::Actor9::startAction(CursorType action, Event &event) {
}
}
-bool Scene1550::Actor10::startAction(CursorType action, Event &event) {
+bool Scene1550::Gyroscope::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1555;
else
scene->_sceneMode = 1589;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor10, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player,
+ &scene->_gyroscope, NULL);
return true;
}
-bool Scene1550::Actor11::startAction(CursorType action, Event &event) {
+bool Scene1550::DiagnosticsDisplay::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- scene->_field412 = 1;
- if (R2_GLOBALS._player._characterIndex == 1)
+ scene->_dontExit = true;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 1586;
else
scene->_sceneMode = 1587;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor11, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player,
+ &scene->_diagnosticsDisplay, NULL);
return true;
}
-bool Scene1550::Actor12::startAction(CursorType action, Event &event) {
+bool Scene1550::DishTower::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1585;
scene->setAction(&scene->_sequenceManager1, scene, 1585, &R2_GLOBALS._player, NULL);
} else {
R2_GLOBALS._player.disableControl();
- switch(scene->_field415) {
+ switch(scene->_dishMode) {
case 0:
- scene->_actor13.fixPriority(168);
- scene->_actor4.fixPriority(125);
+ scene->_dish.fixPriority(168);
+ scene->_walkway.fixPriority(125);
scene->_sceneMode = 1558;
scene->setAction(&scene->_sequenceManager1, scene, 1558, &R2_GLOBALS._player, NULL);
break;
@@ -7115,9 +7679,9 @@ bool Scene1550::Actor12::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
break;
case 2:
- scene->_field415 = 1;
+ scene->_dishMode = 1;
scene->_sceneMode = 1563;
- scene->setAction(&scene->_sequenceManager1, scene, 1563, &R2_GLOBALS._player, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1563, &R2_GLOBALS._player, &scene->_walkway, NULL);
break;
default:
break;
@@ -7127,12 +7691,12 @@ bool Scene1550::Actor12::startAction(CursorType action, Event &event) {
}
-bool Scene1550::Actor13::startAction(CursorType action, Event &event) {
+bool Scene1550::Dish::startAction(CursorType action, Event &event) {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if (scene->_field415 != 2)
+ if (scene->_dishMode != 2)
return SceneActor::startAction(action, event);
if (R2_INVENTORY.getObjectScene(R2_BATTERY) == 1550) {
@@ -7140,17 +7704,17 @@ bool Scene1550::Actor13::startAction(CursorType action, Event &event) {
scene->_sceneMode = 1564;
scene->setAction(&scene->_sequenceManager1, scene, 1564, &R2_GLOBALS._player, NULL);
} else
- SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
case CURSOR_LOOK:
- if (scene->_field415 != 2)
+ if (scene->_dishMode != 2)
return SceneActor::startAction(action, event);
if (R2_INVENTORY.getObjectScene(R2_BATTERY) == 1550) {
- SceneItem::display(1550, 74, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 74, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
} else
- SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
default:
@@ -7159,42 +7723,47 @@ bool Scene1550::Actor13::startAction(CursorType action, Event &event) {
}
}
+/*--------------------------------------------------------------------------*/
+
Scene1550::Scene1550() {
- _field412 = 0;
- _field414 = 0;
- _field415 = 0;
- _field417 = 0;
- _field419 = 0;
+ _dontExit = false;
+ _wallType = 0;
+ _dishMode = 0;
+ _sceneResourceId = 0;
+ _walkRegionsId = 0;
}
void Scene1550::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsByte(_field414);
- s.syncAsSint16LE(_field415);
- s.syncAsSint16LE(_field417);
- s.syncAsSint16LE(_field419);
+ s.syncAsSint16LE(_dontExit);
+ s.syncAsByte(_wallType);
+ s.syncAsSint16LE(_dishMode);
+ s.syncAsSint16LE(_sceneResourceId);
+ s.syncAsSint16LE(_walkRegionsId);
}
void Scene1550::postInit(SceneObjectList *OwnerList) {
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11))
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 9) &&
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11))
+ // Exiting the intact spaceship
loadScene(1234);
else
+ // Normal scene entry
loadScene(1550);
+ SceneExt::postInit();
scalePalette(65, 65, 65);
setZoomPercents(30, 75, 170, 100);
- _field417 = 1550;
- _field419 = 0;
- SceneExt::postInit();
+ _sceneResourceId = 1550;
+ _walkRegionsId = 0;
if (R2_GLOBALS._sceneManager._previousScene == -1)
- R2_GLOBALS.setFlag(R2_ATTRACTOR_CABLE_HARNESS);
+ R2_GLOBALS.setFlag(16);
- if ((R2_GLOBALS._player._characterScene[1] != 1550) && (R2_GLOBALS._player._characterScene[1] != 1580)) {
- R2_GLOBALS._player._characterScene[1] = 1550;
- R2_GLOBALS._player._characterScene[2] = 1550;
+ if ((R2_GLOBALS._player._characterScene[R2_QUINN] != 1550) && (R2_GLOBALS._player._characterScene[R2_QUINN] != 1580)) {
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1550;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1550;
}
_stripManager.setColors(60, 255);
@@ -7203,16 +7772,17 @@ void Scene1550::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_seekerSpeaker);
R2_GLOBALS._player.postInit();
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
R2_GLOBALS._player.setup(1500, 3, 1);
else
R2_GLOBALS._player.setup(1505, 3, 1);
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11))
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 9) &&
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11))
R2_GLOBALS._player.setPosition(Common::Point(157, 135));
else
R2_GLOBALS._player.setPosition(Common::Point(160, 100));
@@ -7220,13 +7790,13 @@ void Scene1550::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _field414 = 0;
- _actor7.changeZoom(-1);
+ _wallType = 0;
+ _companion.changeZoom(-1);
R2_GLOBALS._player.changeZoom(-1);
switch (R2_GLOBALS._sceneManager._previousScene) {
case 1530:
- R2_GLOBALS._v565AE = 0;
+ R2_GLOBALS._stripModifier = 0;
// No break on purpose
case 300:
// No break on purpose
@@ -7236,21 +7806,22 @@ void Scene1550::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(105);
break;
case 1580:
+ // Leaving intact ship
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1580) {
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL);
- _field412 = 1;
+ _dontExit = true;
- _actor1.postInit();
- _arrUnkObj15502[7].subA5CDF(8);
- _arrUnkObj15502[7].hide();
- if (R2_GLOBALS._player._characterIndex == 1)
+ _wreckage2.postInit();
+ _shipComponents[7].setupShipComponent(8);
+ _shipComponents[7].hide();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 1577;
else
_sceneMode = 1578;
- setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor1, &_arrUnkObj15502[7], NULL);
+ setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_wreckage2, &_shipComponents[7], NULL);
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 1550;
} else {
R2_GLOBALS._player.enableControl();
@@ -7260,29 +7831,29 @@ void Scene1550::postInit(SceneObjectList *OwnerList) {
break;
}
- subA2B2F();
+ enterArea();
- _item1.setDetails(16, 1550, 10, -1, -1);
- _item2.setDetails(24, 1550, 10, -1, -1);
- _item3.setDetails(Rect(0, 0, 320, 200), 1550, 0, 1, -1, 1, NULL);
+ _intactHull1.setDetails(16, 1550, 10, -1, -1);
+ _intactHull2.setDetails(24, 1550, 10, -1, -1);
+ _background.setDetails(Rect(0, 0, 320, 200), 1550, 0, 1, -1, 1, NULL);
if ((R2_GLOBALS._sceneManager._previousScene == 1500) && (R2_GLOBALS.getFlag(16))) {
_sceneMode = 70;
- if (!R2_GLOBALS._sceneObjects->contains(&_actor7))
- _actor7.postInit();
+ if (!R2_GLOBALS._sceneObjects->contains(&_companion))
+ _companion.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
- _actor7.setVisage(1505);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _companion.setVisage(1505);
else
- _actor7.setVisage(1500);
+ _companion.setVisage(1500);
- _actor7.changeZoom(77);
- _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
+ _companion.changeZoom(77);
+ _companion.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
- assert(_field419 >= 1550);
- R2_GLOBALS._walkRegions.enableRegion(k5A750[_field419 - 1550]);
+ assert(_walkRegionsId >= 1550);
+ R2_GLOBALS._walkRegions.disableRegion(k5A750[_walkRegionsId - 1550]);
- setAction(&_sequenceManager1, this, 1590, &_actor7, NULL);
+ setAction(&_sequenceManager1, this, 1590, &_companion, NULL);
} else if ((_sceneMode != 1577) && (_sceneMode != 1578))
R2_GLOBALS._player.enableControl();
}
@@ -7296,9 +7867,8 @@ void Scene1550::signal() {
case 5:
// No break on purpose
case 7:
- _field412 = 0;
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ _dontExit = false;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 20:
// No break on purpose
@@ -7307,27 +7877,28 @@ void Scene1550::signal() {
case 25:
// No break on purpose
case 1563:
+ // Show the communication dish controls window
R2_GLOBALS.clearFlag(20);
- _unkArea1.proc12(1559, 1, 1, 160, 125);
+ _dishControlsWindow.setup2(1559, 1, 1, 160, 125);
R2_GLOBALS._player.enableControl();
_sceneMode = 0;
break;
case 22:
- _unkArea1.remove();
+ _dishControlsWindow.remove();
_sceneMode = 24;
- setAction(&_sequenceManager1, this, 1561, &_actor4, NULL);
+ setAction(&_sequenceManager1, this, 1561, &_walkway, NULL);
R2_GLOBALS.clearFlag(20);
break;
case 23:
- _unkArea1.remove();
+ _dishControlsWindow.remove();
_sceneMode = 20;
- setAction(&_sequenceManager1, this, 1566, &_actor13, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1566, &_dish, &_dishTowerShadow, NULL);
R2_GLOBALS.setFlag(21);
break;
case 24:
- _unkArea1.remove();
+ _dishControlsWindow.remove();
_sceneMode = 21;
- setAction(&_sequenceManager1, this, 1567, &_actor13, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1567, &_dish, &_dishTowerShadow, NULL);
R2_GLOBALS.clearFlag(19);
break;
case 30:
@@ -7339,14 +7910,14 @@ void Scene1550::signal() {
break;
case 40: {
_sceneMode = 41;
- Common::Point pt(_arrUnkObj15501[0]._position.x, _arrUnkObj15501[0]._position.y + 20);
+ Common::Point pt(_junk[0]._position.x, _junk[0]._position.y + 20);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 41:
_sceneMode = 42;
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(1502, 8, 1);
} else {
R2_GLOBALS._player.changeZoom(R2_GLOBALS._player._percent + 14);
@@ -7354,37 +7925,42 @@ void Scene1550::signal() {
}
R2_GLOBALS._player.animate(ANIM_MODE_5, this);
break;
- case 42:
+
+ case 42: {
_sceneMode = 43;
- warning("TODO: unknown use of arrUnkObj15501[0]._fieldA6");
- switch (_arrUnkObj15501[0]._frame - 1) {
- case 0:
- R2_INVENTORY.setObjectScene(26, R2_GLOBALS._player._characterIndex);
- break;
+ int junkRegionIndex = R2_GLOBALS._scene1550JunkLocations[_junk[0]._junkNumber + 3];
+ R2_GLOBALS._walkRegions.enableRegion(scene1550JunkRegions[junkRegionIndex]);
+
+ switch (_junk[0]._frame) {
case 1:
- R2_INVENTORY.setObjectScene(17, R2_GLOBALS._player._characterIndex);
+ R2_INVENTORY.setObjectScene(R2_JOYSTICK, R2_GLOBALS._player._characterIndex);
break;
case 2:
- R2_INVENTORY.setObjectScene(22, R2_GLOBALS._player._characterIndex);
+ R2_INVENTORY.setObjectScene(R2_FUEL_CELL, R2_GLOBALS._player._characterIndex);
break;
case 3:
- R2_INVENTORY.setObjectScene(25, R2_GLOBALS._player._characterIndex);
+ R2_INVENTORY.setObjectScene(R2_GUIDANCE_MODULE, R2_GLOBALS._player._characterIndex);
break;
case 4:
- R2_INVENTORY.setObjectScene(45, R2_GLOBALS._player._characterIndex);
+ R2_INVENTORY.setObjectScene(R2_RADAR_MECHANISM, R2_GLOBALS._player._characterIndex);
break;
case 5:
- R2_INVENTORY.setObjectScene(28, R2_GLOBALS._player._characterIndex);
+ R2_INVENTORY.setObjectScene(R2_BATTERY, R2_GLOBALS._player._characterIndex);
+ break;
+ case 6:
+ R2_INVENTORY.setObjectScene(R2_DIAGNOSTICS_DISPLAY, R2_GLOBALS._player._characterIndex);
break;
default:
break;
}
- _arrUnkObj15501[0].remove();
+
+ _junk[0].remove();
R2_GLOBALS._player.animate(ANIM_MODE_6, this);
break;
+ }
case 43:
- warning("TODO: unknown use of arrUnkObj15501[0]._fieldA6");
- if (R2_GLOBALS._player._characterIndex == 1)
+ R2_GLOBALS._scene1550JunkLocations[_junk[0]._junkNumber + 2] = 0;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
R2_GLOBALS._player.setVisage(1500);
else {
R2_GLOBALS._player.changeZoom(-1);
@@ -7395,49 +7971,50 @@ void Scene1550::signal() {
R2_GLOBALS._player.enableControl();
break;
case 50:
- warning("STUB: sub_1D227()");
+ // Removed (useless ?) call to sub_1D227
++_sceneMode;
setAction(&_sequenceManager1, this, 1591, &R2_GLOBALS._player, NULL);
- if (g_globals->_sceneObjects->contains(&_actor7))
+ if (g_globals->_sceneObjects->contains(&_companion))
signal();
else {
- _actor7.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
- _actor7.setVisage(1505);
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _companion.setVisage(1505);
else
- _actor7.setVisage(1500);
- _actor7.changeZoom(77);
- _actor7.setAction(&_sequenceManager2, this, 1590, &_actor7, NULL);
- _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
+ _companion.setVisage(1500);
+ _companion.changeZoom(77);
+ _companion.setAction(&_sequenceManager2, this, 1590, &_companion, NULL);
+ _companion.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
}
break;
case 51:
++_sceneMode;
break;
case 52:
- _actor7.changeZoom(-1);
+ _companion.changeZoom(-1);
_sceneMode = 1592;
- if (R2_GLOBALS._player._characterIndex == 1)
- setAction(&_sequenceManager1, this, 1592, &R2_GLOBALS._player, &_actor7, &_arrUnkObj15501[0], &_actor9, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ setAction(&_sequenceManager1, this, 1592, &R2_GLOBALS._player, &_companion,
+ &_junk[0], &_joystick, NULL);
else
- setAction(&_sequenceManager1, this, 1593, &R2_GLOBALS._player, &_actor7, &_arrUnkObj15501[0], &_actor9, NULL);
+ setAction(&_sequenceManager1, this, 1593, &R2_GLOBALS._player, &_companion,
+ &_junk[0], &_joystick, NULL);
break;
case 61:
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- _field415 = 2;
+ _dishMode = 2;
break;
case 62:
R2_GLOBALS._player.enableControl(CURSOR_TALK);
- if (_field415 == 2) {
+ if (_dishMode == 2) {
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
}
break;
case 70:
- R2_GLOBALS._v565EC[2] = R2_GLOBALS._v565EC[1];
- R2_GLOBALS._v565EC[4] = R2_GLOBALS._v565EC[3];
- R2_GLOBALS._v565EC[0] = 1;
+ R2_GLOBALS._s1550PlayerArea[R2_SEEKER] = R2_GLOBALS._s1550PlayerArea[R2_QUINN];
+ //R2_GLOBALS._s1550PlayerAreas[0] = 1;
_sceneMode = 60;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(500, this);
@@ -7447,33 +8024,33 @@ void Scene1550::signal() {
_sceneMode = 60;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._v565AE >= 3) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._stripModifier >= 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_stripManager.start(572, this);
else
_stripManager.start(573, this);
} else {
- ++R2_GLOBALS._v565AE;
- if (R2_GLOBALS._player._characterIndex == 1)
- _stripManager.start(499 + R2_GLOBALS._v565AE, this);
+ ++R2_GLOBALS._stripModifier;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _stripManager.start(499 + R2_GLOBALS._stripModifier, this);
else
- _stripManager.start(502 + R2_GLOBALS._v565AE, this);
+ _stripManager.start(502 + R2_GLOBALS._stripModifier, this);
}
} else {
_sceneMode = 60;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._v565AE >= 4) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._stripModifier >= 4) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_stripManager.start(572, this);
else
_stripManager.start(573, this);
} else {
- ++R2_GLOBALS._v565AE;
- if (R2_GLOBALS._player._characterIndex == 1)
- _stripManager.start(563 + R2_GLOBALS._v565AE, this);
+ ++R2_GLOBALS._stripModifier;
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _stripManager.start(563 + R2_GLOBALS._stripModifier, this);
else
- _stripManager.start(567 + R2_GLOBALS._v565AE, this);
+ _stripManager.start(567 + R2_GLOBALS._stripModifier, this);
}
}
break;
@@ -7484,8 +8061,8 @@ void Scene1550::signal() {
// No break on purpose
case 1588:
R2_INVENTORY.setObjectScene(R2_AIRBAG, R2_GLOBALS._player._characterIndex);
- _actor8.remove();
- _field412 = 0;
+ _airbag.remove();
+ _dontExit = false;
R2_GLOBALS._player.enableControl();
break;
case 1553:
@@ -7493,33 +8070,33 @@ void Scene1550::signal() {
break;
case 1554:
R2_GLOBALS._player.enableControl();
- _field412 = 0;
+ _dontExit = false;
break;
case 1555:
// No break on purpose
case 1589:
R2_INVENTORY.setObjectScene(R2_GYROSCOPE, R2_GLOBALS._player._characterIndex);
- _actor10.remove();
+ _gyroscope.remove();
R2_GLOBALS._player.enableControl();
break;
case 1558:
- _actor13.fixPriority(124);
- _field415 = 1;
- _unkArea1.proc12(1559, 1, 1, 160, 125);
+ _dish.fixPriority(124);
+ _dishMode = 1;
+ _dishControlsWindow.setup2(1559, 1, 1, 160, 125);
R2_GLOBALS._player.enableControl();
break;
case 1559:
- _actor13.fixPriority(168);
- _actor4.fixPriority(169);
+ _dish.fixPriority(168);
+ _walkway.fixPriority(169);
R2_GLOBALS._player.fixPriority(-1);
R2_GLOBALS._player.changeZoom(-1);
- _field415 = 0;
+ _dishMode = 0;
R2_GLOBALS._player.enableControl();
break;
case 1562:
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- _field415 = 2;
+ _dishMode = 2;
break;
case 1564:
R2_INVENTORY.setObjectScene(R2_BATTERY, 1);
@@ -7533,52 +8110,52 @@ void Scene1550::signal() {
case 1569:
// No break on purpose
case 1579:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_GUIDANCE_MODULE, 0);
R2_GLOBALS._player.enableControl();
break;
case 1570:
// No break on purpose
case 1580:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_RADAR_MECHANISM, 0);
R2_GLOBALS._player.enableControl();
break;
case 1571:
// No break on purpose
case 1581:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_GYROSCOPE, 0);
R2_GLOBALS._player.enableControl();
break;
case 1572:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_THRUSTER_VALVE, 0);
R2_GLOBALS._player.enableControl();
break;
case 1573:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_IGNITOR, 0);
R2_GLOBALS._player.enableControl();
break;
case 1574:
// No break on purpose
case 1582:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_FUEL_CELL, 0);
R2_GLOBALS._player.enableControl();
break;
case 1575:
// No break on purpose
case 1583:
- _field412 = 0;
- _actor1.remove();
+ _dontExit = false;
+ _wreckage2.remove();
R2_INVENTORY.setObjectScene(R2_BATTERY, 0);
R2_GLOBALS._player.enableControl();
break;
@@ -7592,34 +8169,32 @@ void Scene1550::signal() {
// No break on purpose
case 1578:
_sceneMode = 0;
- _actor1.remove();
- _field412 = 0;
+ _wreckage2.remove();
+ _dontExit = false;
R2_GLOBALS._player.fixPriority(-1);
R2_GLOBALS._player.enableControl();
break;
case 1585:
- SceneItem::display(1550, 66, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1550, 66, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
R2_GLOBALS._player.enableControl();
break;
case 1586:
// No break on purpose
case 1587:
R2_INVENTORY.setObjectScene(R2_DIAGNOSTICS_DISPLAY, R2_GLOBALS._player._characterIndex);
- _actor1.remove();
- _field412 = 0;
+ _diagnosticsDisplay.remove();
+ _dontExit = false;
R2_GLOBALS._player.enableControl();
break;
case 1592:
- _actor9.remove();
+ _joystick.remove();
R2_INVENTORY.setObjectScene(R2_JOYSTICK, 1);
- if (R2_GLOBALS._player._characterIndex == 1) {
- R2_GLOBALS._v565EC[2] = R2_GLOBALS._v565EC[1];
- R2_GLOBALS._v565EC[4] = R2_GLOBALS._v565EC[3];
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ R2_GLOBALS._s1550PlayerArea[R2_SEEKER] = R2_GLOBALS._s1550PlayerArea[R2_QUINN];
} else {
- R2_GLOBALS._v565EC[1] = R2_GLOBALS._v565EC[2];
- R2_GLOBALS._v565EC[3] = R2_GLOBALS._v565EC[4];
+ R2_GLOBALS._s1550PlayerArea[R2_QUINN] = R2_GLOBALS._s1550PlayerArea[R2_SEEKER];
}
- R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
default:
_sceneMode = 62;
@@ -7632,14 +8207,14 @@ void Scene1550::process(Event &event) {
if ((!R2_GLOBALS._player._canWalk) && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN) && (event.eventType == EVENT_BUTTON_DOWN) && (this->_screenNumber == 1234)) {
int curReg = R2_GLOBALS._sceneRegions.indexOf(event.mousePos);
if (curReg == 0)
- _field412 = 1;
+ _dontExit = true;
else if (((R2_GLOBALS._player._position.y < 90) && (event.mousePos.y > 90)) || ((R2_GLOBALS._player._position.y > 90) && (event.mousePos.y < 90)))
- _field412 = 1;
+ _dontExit = true;
else
- _field412 = 0;
+ _dontExit = false;
if ((curReg == 13) || (curReg == 14))
- _field412 = 0;
+ _dontExit = false;
}
Scene::process(event);
@@ -7649,24 +8224,27 @@ void Scene1550::dispatch() {
Scene::dispatch();
// Arrays related to this scene are all hacky in the origina: they are based on the impossibility to use Miranda
- assert ((R2_GLOBALS._player._characterIndex == 1) || (R2_GLOBALS._player._characterIndex == 2));
+ assert ((R2_GLOBALS._player._characterIndex == R2_QUINN) || (R2_GLOBALS._player._characterIndex == R2_SEEKER));
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 15) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 16)) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 15) && (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 16)) {
R2_GLOBALS._player._shade = 0;
- // Original game contains a switch based on an uninitialised variable.
- // Until we understand what should really happen there, this code is unused on purpose
+
+ // NOTE: Original game contains a switch based on an uninitialized variable.
+ // We're leaving this code here, but ifdef'ed out, in case we can ever figure out
+ // what the original programmers intended the value to come from
+#if 0
int missingVariable = 0;
switch (missingVariable) {
case 144:
// No break on purpose
case 146:
- _actor13._frame = 5;
+ _dish._frame = 5;
R2_GLOBALS._player._shade = 3;
break;
case 148:
// No break on purpose
case 149:
- _actor13._frame = 1;
+ _dish._frame = 1;
// No break on purpose
case 147:
// No break on purpose
@@ -7676,21 +8254,23 @@ void Scene1550::dispatch() {
default:
break;
}
+#endif
}
- if (_field412 != 0)
+ if (_dontExit)
return;
switch (R2_GLOBALS._player.getRegionIndex() - 11) {
case 0:
// No break on purpose
case 5:
+ // Exiting the top of the screen
R2_GLOBALS._player.disableControl();
_sceneMode = 1;
- _field412 = 1;
- --R2_GLOBALS._v565EC[2 + R2_GLOBALS._player._characterIndex];
+ _dontExit = true;
+ --R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y;
- subA2B2F();
+ enterArea();
R2_GLOBALS._player.setPosition(Common::Point( 160 - (((((160 - R2_GLOBALS._player._position.x) * 100) / 108) * 172) / 100), 145));
if (R2_GLOBALS._player._position.x < 160) {
@@ -7708,12 +8288,13 @@ void Scene1550::dispatch() {
}
break;
case 1:
+ // Exiting the bottom of the screen
R2_GLOBALS._player.disableControl();
_sceneMode = 3;
- _field412 = 1;
- ++R2_GLOBALS._v565EC[2 + R2_GLOBALS._player._characterIndex];
+ _dontExit = true;
+ ++R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y;
- subA2B2F();
+ enterArea();
R2_GLOBALS._player.setPosition(Common::Point( 160 - (((((160 - R2_GLOBALS._player._position.x) * 100) / 172) * 108) / 100), 19));
if (R2_GLOBALS._player._position.x < 160) {
@@ -7731,14 +8312,15 @@ void Scene1550::dispatch() {
}
break;
case 2:
+ // Exiting the right of the screen
R2_GLOBALS._player.disableControl();
_sceneMode = 5;
- _field412 = 1;
- ++R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex];
+ _dontExit = true;
+ ++R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x;
- subA2B2F();
+ enterArea();
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 9) && (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) {
if (R2_GLOBALS._player._position.y >= 85) {
R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 10));
Common::Point pt(R2_GLOBALS._player._position.x + 30, R2_GLOBALS._player._position.y + 20);
@@ -7758,16 +8340,20 @@ void Scene1550::dispatch() {
}
break;
case 3:
+ // Exiting to the left of the screen
R2_GLOBALS._player.disableControl();
_sceneMode = 7;
- _field412 = 1;
- --R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex];
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 24) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11)) {
+ _dontExit = true;
+ --R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x;
+
+ enterArea();
+
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 24) && (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11)) {
R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y / 2));
Common::Point pt(265, 29);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
- } else if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) {
+ } else if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 9) && (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) {
if (R2_GLOBALS._player._position.y >= 85) {
R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 10));
Common::Point pt(R2_GLOBALS._player._position.x - 30, R2_GLOBALS._player._position.y + 20);
@@ -7792,17 +8378,17 @@ void Scene1550::dispatch() {
}
void Scene1550::saveCharacter(int characterIndex) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
R2_GLOBALS._sound1.fadeOut2(NULL);
SceneExt::saveCharacter(characterIndex);
}
-void Scene1550::SceneActor1550::subA4D14(int frameNumber, int strip) {
+void Scene1550::Wall::setupWall(int frameNumber, int strip) {
Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene;
postInit();
- if (scene->_field414 == 2)
+ if (scene->_wallType == 2)
setup(1551, strip, frameNumber);
else
setup(1554, strip, frameNumber);
@@ -7913,7 +8499,7 @@ void Scene1550::SceneActor1550::subA4D14(int frameNumber, int strip) {
switch (frameNumber) {
case 2:
fixPriority(2);
- if (scene->_field414 == 2)
+ if (scene->_wallType == 2)
setup(1553, 2, 1);
else
setup(1556, 2, 1);
@@ -7938,7 +8524,7 @@ void Scene1550::SceneActor1550::subA4D14(int frameNumber, int strip) {
case 4:
if (frameNumber == 2) {
fixPriority(250);
- if (scene->_field414 == 2)
+ if (scene->_wallType == 2)
setup(1553, 1, 1);
else
setup(1556, 1, 1);
@@ -7982,54 +8568,52 @@ void Scene1550::SceneActor1550::subA4D14(int frameNumber, int strip) {
}
-void Scene1550::subA2B2F() {
- Rect tmpRect;
- _field419 = 0;
- _field415 = 0;
-
- tmpRect = R2_GLOBALS._v5589E;
+void Scene1550::enterArea() {
+ _walkRegionsId = 0;
+ _dishMode = 0;
- _actor14.remove();
- _actor17.remove();
- _actor15.remove();
- _actor19.remove();
- _actor16.remove();
- _actor18.remove();
+ _wallCorner1.remove();
+ _westWall.remove();
+ _northWall.remove();
+ _southWall.remove();
+ _wallCorner2.remove();
+ _eastWall.remove();
for (int i = 0; i < 8; ++i)
- _arrUnkObj15501[i].remove();
+ _junk[i].remove();
- _actor6.remove();
+ _wreckage.remove();
for (int i = 0; i < 8; ++i)
- _arrUnkObj15502[i].remove();
+ _shipComponents[i].remove();
- _actor8.remove();
- _actor9.remove();
- _actor10.remove();
- _actor3.remove();
- _actor11.remove();
+ _airbag.remove();
+ _joystick.remove();
+ _gyroscope.remove();
+ _wreckage4.remove();
+ _diagnosticsDisplay.remove();
if ((_sceneMode != 1577) && (_sceneMode != 1578))
- _actor1.remove();
+ _wreckage2.remove();
- _actor2.remove();
- _actor7.remove();
- _actor13.remove();
- _actor5.remove();
- _actor12.remove();
- _actor4.remove();
+ _wreckage3.remove();
+ _companion.remove();
+ _dish.remove();
+ _dishTowerShadow.remove();
+ _dishTower.remove();
+ _walkway.remove();
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2]) {
+ // Set up of special walk regions for certain areas
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y) {
case 0:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x) {
case 3:
R2_GLOBALS._walkRegions.load(1554);
- _field419 = 1554;
+ _walkRegionsId = 1554;
break;
case 4:
R2_GLOBALS._walkRegions.load(1553);
- _field419 = 1553;
+ _walkRegionsId = 1553;
break;
default:
break;
@@ -8038,54 +8622,54 @@ void Scene1550::subA2B2F() {
case 3:
// No break on purpose
case 4:
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 23) || (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex])) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 23) || (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x)) {
if (!R2_GLOBALS.getFlag(16)) {
R2_GLOBALS._walkRegions.load(1559);
- _field419 = 1559;
+ _walkRegionsId = 1559;
}
}
break;
case 7:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x) {
case 10:
R2_GLOBALS._walkRegions.load(1555);
- _field419 = 1555;
+ _walkRegionsId = 1555;
break;
case 11:
R2_GLOBALS._walkRegions.load(1556);
- _field419 = 1556;
+ _walkRegionsId = 1556;
break;
default:
break;
}
break;
case 11:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x) {
case 24:
R2_GLOBALS._walkRegions.load(1558);
- _field419 = 1558;
+ _walkRegionsId = 1558;
break;
case 25:
R2_GLOBALS._walkRegions.load(1557);
- _field419 = 1557;
+ _walkRegionsId = 1557;
break;
default:
break;
}
break;
case 16:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x) {
case 2:
R2_GLOBALS._walkRegions.load(1552);
- _field419 = 1552;
+ _walkRegionsId = 1552;
break;
case 3:
R2_GLOBALS._walkRegions.load(1551);
- _field419 = 1551;
+ _walkRegionsId = 1551;
break;
case 15:
R2_GLOBALS._walkRegions.load(1575);
- _field419 = 1575;
+ _walkRegionsId = 1575;
default:
break;
}
@@ -8096,13 +8680,15 @@ void Scene1550::subA2B2F() {
int varA = 0;
+ // This section handles checks if the ARM spacecraft have not yet seized
+ // control of Lance of Truth.
if (!R2_GLOBALS.getFlag(16)) {
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] - 2) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y - 2) {
case 0:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] - 22) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x - 22) {
case 0:
varA = 1553;
- _actor15.subA4D14(6, 0);
+ _northWall.setupWall(6, 0);
break;
case 1:
// No break on purpose
@@ -8115,7 +8701,7 @@ void Scene1550::subA2B2F() {
break;
case 5:
varA = 1553;
- _actor15.subA4D14(6, 0);
+ _northWall.setupWall(6, 0);
break;
default:
break;
@@ -8124,14 +8710,14 @@ void Scene1550::subA2B2F() {
case 1:
// No break on purpose
case 2:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] - 21) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x - 21) {
case 0:
varA = 1550;
- _actor15.subA4D14(9, 0);
+ _northWall.setupWall(9, 0);
break;
case 1:
varA = 1552;
- _actor15.subA4D14(10, 0);
+ _northWall.setupWall(10, 0);
break;
case 2:
// No break on purpose
@@ -8144,25 +8730,25 @@ void Scene1550::subA2B2F() {
break;
case 6:
varA = 1552;
- _actor15.subA4D14(7, 0);
+ _northWall.setupWall(7, 0);
break;
case 7:
varA = 1550;
- _actor15.subA4D14(8, 0);
+ _northWall.setupWall(8, 0);
break;
default:
break;
}
break;
case 3:
- switch (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] - 21) {
+ switch (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x - 21) {
case 0:
varA = 1550;
- _actor15.subA4D14(4, 0);
+ _northWall.setupWall(4, 0);
break;
case 1:
varA = 1550;
- _actor15.subA4D14(3, 0);
+ _northWall.setupWall(3, 0);
break;
case 2:
// No break on purpose
@@ -8175,11 +8761,11 @@ void Scene1550::subA2B2F() {
break;
case 6:
varA = 1550;
- _actor15.subA4D14(2, 0);
+ _northWall.setupWall(2, 0);
break;
case 7:
varA = 1550;
- _actor15.subA4D14(1, 0);
+ _northWall.setupWall(1, 0);
break;
default:
break;
@@ -8188,40 +8774,46 @@ void Scene1550::subA2B2F() {
default:
break;
}
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] > 0) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] <= 29) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] >= 20) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] > 7)) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y > 0) &&
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x <= 29) &&
+ ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x < 20) ||
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y > 7))) {
+ // In an area where the cutscene can be triggered, so start it
R2_GLOBALS.setFlag(16);
R2_GLOBALS._sceneManager.changeScene(1500);
}
}
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11)) {
- if (R2_GLOBALS._sceneManager._sceneNumber != 1234) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == 9) &&
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 11)) {
+ if (_screenNumber != 1234) {
R2_GLOBALS._sceneManager._fadeMode = FADEMODE_IMMEDIATE;
loadScene(1234);
R2_GLOBALS._sceneManager._hasPalette = false;
- _field414 = 0;
+ _wallType = 0;
}
} else {
- if (R2_GLOBALS._sceneManager._sceneNumber == 1234) {
+ if (_screenNumber == 1234) {
R2_GLOBALS._sceneManager._fadeMode = FADEMODE_IMMEDIATE;
loadScene(1550);
R2_GLOBALS._sceneManager._hasPalette = false;
}
}
- if (R2_GLOBALS._sceneManager._sceneNumber == 1234)
- _field419 = 1576;
+ if (_screenNumber == 1234)
+ _walkRegionsId = 1576;
- if (_field414 == 0) {
- _field414 = 1;
+ if (_wallType == 0) {
+ _wallType = 1;
} else {
- if (_field414 == 2) {
- _field414 = 3;
+ if (_wallType == 2) {
+ _wallType = 3;
} else {
- _field414 = 2;
+ _wallType = 2;
}
if (R2_GLOBALS._sceneManager._sceneNumber == 1550){
+#if 0
warning("Mouse_hideIfNeeded()");
warning("gfx_set_pane_p");
for (int i = 3; i != 168; ++i) {
@@ -8231,10 +8823,11 @@ void Scene1550::subA2B2F() {
}
warning("Missing sub2957D()");
warning("gfx_set_pane_p()");
+#endif
R2_GLOBALS._sceneManager._fadeMode = FADEMODE_IMMEDIATE;
if (varA == 0) {
- if (_field417 != 1550) {
+ if (_sceneResourceId != 1550) {
g_globals->_scenePalette.loadPalette(1550);
R2_GLOBALS._sceneManager._hasPalette = true;
}
@@ -8244,137 +8837,142 @@ void Scene1550::subA2B2F() {
}
if (R2_GLOBALS._sceneManager._hasPalette)
- _field417 = varA;
+ _sceneResourceId = varA;
- warning("sub_2C429()");
+// warning("sub_2C429()");
}
}
- switch (k5A4D6[(R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] * 30)] + R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]) {
+ // Scene setup dependent on the type of cell specified in the scene map
+ switch (scene1550AreaMap[(R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y * 30) +
+ R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x]) {
case 0:
- if (_field419 == 0) {
+ // Standard cell
+ if (_walkRegionsId == 0) {
R2_GLOBALS._walkRegions.load(1550);
- _field419 = 1550;
+ _walkRegionsId = 1550;
}
break;
case 1:
- if (_field419 == 0) {
+ // North end of the spaceport
+ if (_walkRegionsId == 0) {
R2_GLOBALS._walkRegions.load(1560);
- _field419 = 1560;
+ _walkRegionsId = 1560;
}
- _actor14.subA4D14(2, 1);
- _actor15.subA4D14(1, 3);
- _actor16.subA4D14(2, 5);
+ _wallCorner1.setupWall(2, 1);
+ _northWall.setupWall(1, 3);
+ _wallCorner2.setupWall(2, 5);
break;
case 2:
R2_GLOBALS._walkRegions.load(1561);
- _field419 = 1561;
- _actor14.subA4D14(2, 1);
- _actor17.subA4D14(2, 2);
- _actor15.subA4D14(1, 3);
- _actor16.subA4D14(2, 5);
+ _walkRegionsId = 1561;
+ _wallCorner1.setupWall(2, 1);
+ _westWall.setupWall(2, 2);
+ _northWall.setupWall(1, 3);
+ _wallCorner2.setupWall(2, 5);
break;
case 3:
R2_GLOBALS._walkRegions.load(1562);
- _field419 = 1562;
- _actor14.subA4D14(2, 1);
- _actor15.subA4D14(1, 3);
- _actor16.subA4D14(2, 5);
- _actor18.subA4D14(2, 6);
+ _walkRegionsId = 1562;
+ _wallCorner1.setupWall(2, 1);
+ _northWall.setupWall(1, 3);
+ _wallCorner2.setupWall(2, 5);
+ _eastWall.setupWall(2, 6);
break;
case 4:
R2_GLOBALS._walkRegions.load(1563);
- _field419 = 1563;
- _actor15.subA4D14(2, 3);
+ _walkRegionsId = 1563;
+ _northWall.setupWall(2, 3);
break;
case 5:
R2_GLOBALS._walkRegions.load(1564);
- _field419 = 1564;
- _actor19.subA4D14(2, 4);
+ _walkRegionsId = 1564;
+ _southWall.setupWall(2, 4);
break;
case 6:
R2_GLOBALS._walkRegions.load(1565);
- _field419 = 1565;
- _actor14.subA4D14(1, 1);
- _actor17.subA4D14(1, 2);
- _actor15.subA4D14(3, 3);
+ _walkRegionsId = 1565;
+ _wallCorner1.setupWall(1, 1);
+ _westWall.setupWall(1, 2);
+ _northWall.setupWall(3, 3);
break;
case 7:
R2_GLOBALS._walkRegions.load(1566);
- _field419 = 1566;
- _actor14.subA4D14(1, 1);
- _actor17.subA4D14(1, 2);
- _actor15.subA4D14(2, 4);
+ _walkRegionsId = 1566;
+ _wallCorner1.setupWall(1, 1);
+ _westWall.setupWall(1, 2);
+ _northWall.setupWall(2, 4);
break;
case 8:
R2_GLOBALS._walkRegions.load(1567);
- _field419 = 1567;
- _actor17.subA4D14(5, 2);
+ _walkRegionsId = 1567;
+ _westWall.setupWall(5, 2);
break;
case 9:
R2_GLOBALS._walkRegions.load(1568);
- _field419 = 1568;
- _actor17.subA4D14(4, 2);
+ _walkRegionsId = 1568;
+ _westWall.setupWall(4, 2);
break;
case 10:
R2_GLOBALS._walkRegions.load(1569);
- _field419 = 1569;
- _actor14.subA4D14(3, 1);
+ _walkRegionsId = 1569;
+ _wallCorner1.setupWall(3, 1);
break;
case 11:
R2_GLOBALS._walkRegions.load(1570);
- _field419 = 1570;
- _actor14.subA4D14(1, 1);
- _actor17.subA4D14(1, 2);
+ _walkRegionsId = 1570;
+ _wallCorner1.setupWall(1, 1);
+ _westWall.setupWall(1, 2);
break;
case 12:
R2_GLOBALS._walkRegions.load(1571);
- _field419 = 1571;
- _actor16.subA4D14(1, 5);
- _actor18.subA4D14(1, 6);
+ _walkRegionsId = 1571;
+ _wallCorner2.setupWall(1, 5);
+ _eastWall.setupWall(1, 6);
break;
case 13:
R2_GLOBALS._walkRegions.load(1572);
- _field419 = 1572;
- _actor14.subA4D14(1, 1);
- _actor17.subA4D14(1, 2);
- _actor19.subA4D14(1, 4);
+ _walkRegionsId = 1572;
+ _wallCorner1.setupWall(1, 1);
+ _westWall.setupWall(1, 2);
+ _southWall.setupWall(1, 4);
break;
case 14:
R2_GLOBALS._walkRegions.load(1573);
- _field419 = 1573;
- _actor19.subA4D14(1, 4);
- _actor16.subA4D14(1, 5);
- _actor18.subA4D14(1, 6);
+ _walkRegionsId = 1573;
+ _southWall.setupWall(1, 4);
+ _wallCorner2.setupWall(1, 5);
+ _eastWall.setupWall(1, 6);
break;
case 15:
+ // South wall
R2_GLOBALS._walkRegions.load(1574);
- _field419 = 1574;
- _actor19.subA4D14(1, 4);
+ _walkRegionsId = 1574;
+ _southWall.setupWall(1, 4);
break;
case 16:
R2_GLOBALS._walkRegions.load(1570);
- _field419 = 1570;
- _actor14.subA4D14(2, 1);
- _actor17.subA4D14(2, 2);
+ _walkRegionsId = 1570;
+ _wallCorner1.setupWall(2, 1);
+ _westWall.setupWall(2, 2);
break;
case 17:
R2_GLOBALS._walkRegions.load(1570);
- _field419 = 1570;
- _actor14.subA4D14(2, 1);
- _actor17.subA4D14(3, 2);
+ _walkRegionsId = 1570;
+ _wallCorner1.setupWall(2, 1);
+ _westWall.setupWall(3, 2);
break;
case 18:
R2_GLOBALS._walkRegions.load(1571);
- _field419 = 1571;
- _actor16.subA4D14(2, 5);
- _actor18.subA4D14(2, 6);
+ _walkRegionsId = 1571;
+ _wallCorner2.setupWall(2, 5);
+ _eastWall.setupWall(2, 6);
break;
case 19:
R2_GLOBALS._walkRegions.load(1571);
- _field419 = 1571;
- _actor16.subA4D14(2, 5);
- _actor18.subA4D14(3, 6);
+ _walkRegionsId = 1571;
+ _wallCorner2.setupWall(2, 5);
+ _eastWall.setupWall(3, 6);
break;
default:
break;
@@ -8382,278 +8980,284 @@ void Scene1550::subA2B2F() {
int di = 0;
int tmpIdx = 0;
- // Original game was checking "i < 129" but it was clearly a bug as it's out of bounds
- for (int i = 0; i < 129 * 4; i += 4) {
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == k562CC[i]) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == k562CC[i + 1]) && (k562CC[i + 2] != 0)) {
- tmpIdx = k562CC[i + 3];
- _arrUnkObj15501[di].postInit();
- _arrUnkObj15501[di]._effect = 6;
- _arrUnkObj15501[di]._shade = 0;
- _arrUnkObj15501[di]._fieldA4 = tmpIdx;
- _arrUnkObj15501[di]._fieldA6 = i;
- _arrUnkObj15501[di].setDetails(1550, 62, -1, 63, 2, (SceneItem *) NULL);
- if (k562CC[i + 2] == 41) {
- _arrUnkObj15501[di].changeZoom(-1);
- _arrUnkObj15501[di].setPosition(Common::Point(150, 70));
- _arrUnkObj15501[di].setup(1562, 1, 1);
- R2_GLOBALS._walkRegions.enableRegion(k5A78C);
- R2_GLOBALS._walkRegions.enableRegion(k5A78D);
- R2_GLOBALS._walkRegions.enableRegion(k5A790);
- R2_GLOBALS._walkRegions.enableRegion(k5A791);
+ for (int i = 0; i < 127 * 4; i += 4) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == R2_GLOBALS._scene1550JunkLocations[i]) &&
+ (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == R2_GLOBALS._scene1550JunkLocations[i + 1]) &&
+ (R2_GLOBALS._scene1550JunkLocations[i + 2] != 0)) {
+ tmpIdx = R2_GLOBALS._scene1550JunkLocations[i + 3];
+ _junk[di].postInit();
+ _junk[di]._effect = EFFECT_SHADED2;
+ _junk[di]._shade = 0;
+ //_junk[di]._junkState = tmpIdx;
+ _junk[di]._junkNumber = i;
+ _junk[di].setDetails(1550, 62, -1, 63, 2, (SceneItem *) NULL);
+ if (R2_GLOBALS._scene1550JunkLocations[i + 2] == 41) {
+ _junk[di].changeZoom(-1);
+ _junk[di].setPosition(Common::Point(150, 70));
+ _junk[di].setup(1562, 1, 1);
+
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[2]);
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[3]);
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[6]);
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[7]);
+
if (R2_INVENTORY.getObjectScene(R2_JOYSTICK) == 1550) {
- _actor9.postInit();
- _actor9.setup(1562, 3, 1);
- _actor9.setPosition(Common::Point(150, 70));
- _actor9.fixPriority(10);
- _actor9.setDetails(1550, 41, -1, 42, 2, (SceneItem *) NULL);
+ _joystick.postInit();
+ _joystick.setup(1562, 3, 1);
+ _joystick.setPosition(Common::Point(150, 70));
+ _joystick.fixPriority(10);
+ _joystick.setDetails(1550, 41, -1, 42, 2, (SceneItem *) NULL);
}
} else {
- if (k562CC[i + 2] > 40) {
- _arrUnkObj15501[di].changeZoom(100);
- _arrUnkObj15501[di].setup(1561, 1, k562CC[i + 2] - 40);
+ if (R2_GLOBALS._scene1550JunkLocations[i + 2] > 40) {
+ _junk[di].changeZoom(100);
+ _junk[di].setup(1561, 1, R2_GLOBALS._scene1550JunkLocations[i + 2] - 40);
} else {
- _arrUnkObj15501[di].changeZoom(-1);
- _arrUnkObj15501[di].setup(1552, ((k562CC[i + 2] - 1) / 5) + 1, ((k562CC[i + 2] - 1) % 5) + 1);
+ _junk[di].changeZoom(-1);
+ _junk[di].setup(1552, ((R2_GLOBALS._scene1550JunkLocations[i + 2] - 1) / 5) + 1, ((R2_GLOBALS._scene1550JunkLocations[i + 2] - 1) % 5) + 1);
}
- _arrUnkObj15501[di].setPosition(Common::Point(k5A72E[tmpIdx], k5A73F[tmpIdx]));
- if (k5A78A[tmpIdx] != 0)
- R2_GLOBALS._walkRegions.enableRegion(k5A78A[tmpIdx]);
+ _junk[di].setPosition(Common::Point(scene1550JunkX[tmpIdx], scene1550JunkY[tmpIdx]));
+ if (scene1550JunkRegions[tmpIdx] != 0)
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[tmpIdx]);
di++;
}
}
}
- for (int i = 0; i < 15 * 3; i++) {
- if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == k5A79B[i]) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == k5A79B[i + 1])) {
- tmpIdx = k5A79B[i + 2];
- switch (tmpIdx - 1) {
- case 0:
+ // Loop for detecting and setting up certain special areas within the map
+ for (int i = 0; i < 15 * 3; i += 3) {
+ if ((R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].x == scene1550SpecialAreas[i])
+ && (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == scene1550SpecialAreas[i + 1])) {
+ int areaType = scene1550SpecialAreas[i + 2];
+ switch (areaType) {
+ case 1:
if (!R2_GLOBALS.getFlag(16)) {
- _actor1.postInit();
- if (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 3)
- _actor1.setup(1555, 2, 1);
+ _wreckage2.postInit();
+ if (R2_GLOBALS._s1550PlayerArea[R2_GLOBALS._player._characterIndex].y == 3)
+ _wreckage2.setup(1555, 2, 1);
else
- _actor1.setup(1555, 1, 1);
- _actor1.setPosition(Common::Point(150, 100));
- _actor1.fixPriority(92);
- _actor1.setDetails(1550, 73, -1, -1, 2, (SceneItem *) NULL);
+ _wreckage2.setup(1555, 1, 1);
+ _wreckage2.setPosition(Common::Point(150, 100));
+ _wreckage2.fixPriority(92);
+ _wreckage2.setDetails(1550, 73, -1, -1, 2, (SceneItem *) NULL);
}
break;
- case 1:
- _actor13.postInit();
- warning("_actor13._actorName = \"dish\";");
+ case 2:
+ _dish.postInit();
if (R2_GLOBALS.getFlag(19))
- _actor13.setup(1556, 3, 5);
+ _dish.setup(1556, 3, 5);
else
- _actor13.setup(1556, 3, 1);
- _actor13.changeZoom(95);
- _actor13.setPosition(Common::Point(165, 83));
- _actor13.fixPriority(168);
- _actor13.setDetails(1550, 17, -1, 19, 2, (SceneItem *) NULL);
-
- _actor12.postInit();
- _actor12.setup(1556, 4, 1);
- _actor12.setPosition(Common::Point(191, 123));
- _actor12.changeZoom(95);
- _actor12.setDetails(1550, 65, -1, 66, 2, (SceneItem *) NULL);
-
- _actor5.postInit();
- _actor5._numFrames = 5;
+ _dish.setup(1556, 3, 1);
+ _dish.changeZoom(95);
+ _dish.setPosition(Common::Point(165, 83));
+ _dish.fixPriority(168);
+ _dish.setDetails(1550, 17, -1, 19, 2, (SceneItem *) NULL);
+
+ _dishTower.postInit();
+ _dishTower.setup(1556, 4, 1);
+ _dishTower.setPosition(Common::Point(191, 123));
+ _dishTower.changeZoom(95);
+ _dishTower.setDetails(1550, 65, -1, 66, 2, (SceneItem *) NULL);
+
+ _dishTowerShadow.postInit();
+ _dishTowerShadow._numFrames = 5;
if (R2_GLOBALS.getFlag(19))
- _actor5.setup(1556, 8, 5);
+ _dishTowerShadow.setup(1556, 8, 5);
else
- _actor5.setup(1556, 8, 1);
+ _dishTowerShadow.setup(1556, 8, 1);
- _actor5.setPosition(Common::Point(156, 151));
- _actor5.fixPriority(10);
+ _dishTowerShadow.setPosition(Common::Point(156, 151));
+ _dishTowerShadow.fixPriority(10);
- _actor4.postInit();
+ _walkway.postInit();
if (R2_GLOBALS.getFlag(20))
- _actor4.setup(1558, 3, 10);
+ _walkway.setup(1558, 3, 10);
else
- _actor4.setup(1558, 3, 1);
+ _walkway.setup(1558, 3, 1);
- _actor4.setPosition(Common::Point(172, 48));
- _actor4.fixPriority(169);
- R2_GLOBALS._walkRegions.enableRegion(k5A78A[15]);
+ _walkway.setPosition(Common::Point(172, 48));
+ _walkway.fixPriority(169);
+ R2_GLOBALS._walkRegions.disableRegion(scene1550JunkRegions[15]);
break;
- case 2:
- _actor6.postInit();
- _actor6.setup(1550, 1, 1);
- _actor6.setPosition(Common::Point(259, 55));
- _actor6.fixPriority(133);
- _actor6.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 1, 2);
- _actor1.setPosition(Common::Point(259, 133));
- _actor1.fixPriority(105);
- _actor1.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+ case 3:
+ _wreckage.postInit();
+ _wreckage.setup(1550, 1, 1);
+ _wreckage.setPosition(Common::Point(259, 55));
+ _wreckage.fixPriority(133);
+ _wreckage.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 1, 2);
+ _wreckage2.setPosition(Common::Point(259, 133));
+ _wreckage2.fixPriority(105);
+ _wreckage2.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
if (R2_INVENTORY.getObjectScene(R2_GYROSCOPE) == 1550) {
- _actor10.postInit();
- _actor10.setup(1550, 7, 2);
- _actor10.setPosition(Common::Point(227, 30));
- _actor10.fixPriority(130);
- _actor10.setDetails(1550, 29, -1, 63, 2, (SceneItem *) NULL);
+ _gyroscope.postInit();
+ _gyroscope.setup(1550, 7, 2);
+ _gyroscope.setPosition(Common::Point(227, 30));
+ _gyroscope.fixPriority(130);
+ _gyroscope.setDetails(1550, 29, -1, 63, 2, (SceneItem *) NULL);
}
break;
- case 3:
- _actor6.postInit();
- _actor6.setup(1550, 1, 4);
- _actor6.setPosition(Common::Point(76, 131));
- _actor6.fixPriority(10);
- _actor6.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 1, 3);
- _actor1.setPosition(Common::Point(76, 64));
- _actor1.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+ case 4:
+ _wreckage.postInit();
+ _wreckage.setup(1550, 1, 4);
+ _wreckage.setPosition(Common::Point(76, 131));
+ _wreckage.fixPriority(10);
+ _wreckage.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 1, 3);
+ _wreckage2.setPosition(Common::Point(76, 64));
+ _wreckage2.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
if (R2_INVENTORY.getObjectScene(R2_DIAGNOSTICS_DISPLAY) == 1550) {
- _actor11.postInit();
- _actor11.setup(1504, 4, 1);
- _actor11.setPosition(Common::Point(49, 35));
- _actor11.animate(ANIM_MODE_2, NULL);
- _actor11._numFrames = 4;
- _actor11.fixPriority(65);
- _actor11.setDetails(1550, 14, 15, 63, 2, (SceneItem *) NULL);
+ _diagnosticsDisplay.postInit();
+ _diagnosticsDisplay.setup(1504, 4, 1);
+ _diagnosticsDisplay.setPosition(Common::Point(49, 35));
+ _diagnosticsDisplay.animate(ANIM_MODE_2, NULL);
+ _diagnosticsDisplay._numFrames = 4;
+ _diagnosticsDisplay.fixPriority(65);
+ _diagnosticsDisplay.setDetails(1550, 14, 15, 63, 2, (SceneItem *) NULL);
}
if (R2_INVENTORY.getObjectScene(R2_AIRBAG) == 1550) {
- _actor8.postInit();
- _actor8.setup(1550, 7, 1);
- _actor8.setPosition(Common::Point(45, 44));
- _actor8.fixPriority(150);
- _actor8.setDetails(1550, 44, -1, 63, 2, (SceneItem *) NULL);
+ _airbag.postInit();
+ _airbag.setup(1550, 7, 1);
+ _airbag.setPosition(Common::Point(45, 44));
+ _airbag.fixPriority(150);
+ _airbag.setDetails(1550, 44, -1, 63, 2, (SceneItem *) NULL);
}
break;
- case 4:
- _actor6.postInit();
- _actor6.setup(1550, 2, 4);
- _actor6.setPosition(Common::Point(243, 131));
- _actor6.fixPriority(10);
- _actor6.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 2, 3);
- _actor1.setPosition(Common::Point(243, 64));
- _actor1.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
- break;
case 5:
- _actor6.postInit();
- _actor6.setup(1550, 2, 1);
- _actor6.setPosition(Common::Point(60, 55));
- _actor6.fixPriority(133);
- _actor6.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 2, 2);
- _actor1.setPosition(Common::Point(60, 133));
- _actor1.fixPriority(106);
- _actor1.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+ _wreckage.postInit();
+ _wreckage.setup(1550, 2, 4);
+ _wreckage.setPosition(Common::Point(243, 131));
+ _wreckage.fixPriority(10);
+ _wreckage.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 2, 3);
+ _wreckage2.setPosition(Common::Point(243, 64));
+ _wreckage2.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
break;
case 6:
- _actor6.postInit();
- _actor6.setup(1550, 3, 1);
- _actor6.setPosition(Common::Point(281, 132));
- _actor6.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+ _wreckage.postInit();
+ _wreckage.setup(1550, 2, 1);
+ _wreckage.setPosition(Common::Point(60, 55));
+ _wreckage.fixPriority(133);
+ _wreckage.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 2, 2);
+ _wreckage2.setPosition(Common::Point(60, 133));
+ _wreckage2.fixPriority(106);
+ _wreckage2.setDetails(1550, 9, -1, -1, 2, (SceneItem *) NULL);
break;
case 7:
- _actor6.postInit();
- _actor6.setup(1550, 3, 2);
- _actor6.setPosition(Common::Point(57, 96));
- _actor6.fixPriority(70);
- _actor6.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 3, 3);
- _actor1.setPosition(Common::Point(145, 88));
- _actor1.fixPriority(55);
- _actor1.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor2.postInit();
- _actor2.setup(1550, 3, 4);
- _actor2.setPosition(Common::Point(64, 137));
- _actor2.fixPriority(115);
- _actor2.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor3.postInit();
- _actor3.setup(1550, 5, 1);
- _actor3.setPosition(Common::Point(60, 90));
- _actor3.fixPriority(45);
+ _wreckage.postInit();
+ _wreckage.setup(1550, 3, 1);
+ _wreckage.setPosition(Common::Point(281, 132));
+ _wreckage.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
break;
case 8:
- _actor6.postInit();
- _actor6.setup(1550, 4, 2);
- _actor6.setPosition(Common::Point(262, 96));
- _actor6.fixPriority(70);
- _actor6.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1550, 4, 3);
- _actor1.setPosition(Common::Point(174, 88));
- _actor1.fixPriority(55);
- _actor1.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor2.postInit();
- _actor2.setup(1550, 4, 4);
- _actor2.setPosition(Common::Point(255, 137));
- _actor2.fixPriority(115);
- _actor2.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
-
- _actor3.postInit();
- _actor3.setup(1550, 6, 1);
- _actor3.setPosition(Common::Point(259, 90));
- _actor3.fixPriority(45);
+ _wreckage.postInit();
+ _wreckage.setup(1550, 3, 2);
+ _wreckage.setPosition(Common::Point(57, 96));
+ _wreckage.fixPriority(70);
+ _wreckage.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 3, 3);
+ _wreckage2.setPosition(Common::Point(145, 88));
+ _wreckage2.fixPriority(55);
+ _wreckage2.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage3.postInit();
+ _wreckage3.setup(1550, 3, 4);
+ _wreckage3.setPosition(Common::Point(64, 137));
+ _wreckage3.fixPriority(115);
+ _wreckage3.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage4.postInit();
+ _wreckage4.setup(1550, 5, 1);
+ _wreckage4.setPosition(Common::Point(60, 90));
+ _wreckage4.fixPriority(45);
break;
case 9:
- _actor6.postInit();
- _actor6.setup(1550, 4, 1);
- _actor6.setPosition(Common::Point(38, 132));
- _actor6.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+ _wreckage.postInit();
+ _wreckage.setup(1550, 4, 2);
+ _wreckage.setPosition(Common::Point(262, 96));
+ _wreckage.fixPriority(70);
+ _wreckage.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage2.postInit();
+ _wreckage2.setup(1550, 4, 3);
+ _wreckage2.setPosition(Common::Point(174, 88));
+ _wreckage2.fixPriority(55);
+ _wreckage2.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage3.postInit();
+ _wreckage3.setup(1550, 4, 4);
+ _wreckage3.setPosition(Common::Point(255, 137));
+ _wreckage3.fixPriority(115);
+ _wreckage3.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+
+ _wreckage4.postInit();
+ _wreckage4.setup(1550, 6, 1);
+ _wreckage4.setPosition(Common::Point(259, 90));
+ _wreckage4.fixPriority(45);
+ break;
+ case 10:
+ _wreckage.postInit();
+ _wreckage.setup(1550, 4, 1);
+ _wreckage.setPosition(Common::Point(38, 132));
+ _wreckage.setDetails(1550, 56, -1, -1, 2, (SceneItem *) NULL);
+ break;
+ case 12:
+ // Intact ship
+ _shipComponents[7].setupShipComponent(8);
+ _shipComponents[0].setupShipComponent(1);
+ _shipComponents[1].setupShipComponent(2);
+ _shipComponents[2].setupShipComponent(3);
+ _shipComponents[3].setupShipComponent(4);
+ _shipComponents[4].setupShipComponent(5);
+ _shipComponents[5].setupShipComponent(6);
+ _shipComponents[6].setupShipComponent(7);
break;
- case 11:
- _arrUnkObj15502[7].subA5CDF(8);
- _arrUnkObj15502[0].subA5CDF(1);
- _arrUnkObj15502[1].subA5CDF(2);
- _arrUnkObj15502[2].subA5CDF(3);
- _arrUnkObj15502[3].subA5CDF(4);
- _arrUnkObj15502[4].subA5CDF(5);
- _arrUnkObj15502[5].subA5CDF(6);
- _arrUnkObj15502[6].subA5CDF(7);
default:
break;
}
}
}
- if ((R2_GLOBALS._v565EC[1] == R2_GLOBALS._v565EC[2]) && (R2_GLOBALS._v565EC[3] == R2_GLOBALS._v565EC[4])) {
- _actor7.postInit();
- _actor7._effect = 7;
- _actor7.changeZoom(-1);
+ if (R2_GLOBALS._s1550PlayerArea[R2_QUINN] == R2_GLOBALS._s1550PlayerArea[R2_SEEKER]) {
+ _companion.postInit();
+ _companion._effect = EFFECT_SHADED2;
+ _companion.changeZoom(-1);
- assert((_field419 >= 1550) && (_field419 <= 2008));
- R2_GLOBALS._walkRegions.enableRegion(k5A750[_field419 - 1550]);
- _actor7.setPosition(Common::Point(k5A72E[k5A76D[_field419 - 1550]], k5A73F[k5A76D[_field419 - 1550]] + 8));
- if (R2_GLOBALS._player._characterIndex == 1) {
- if (R2_GLOBALS._player._characterScene[2] == 1580) {
- _actor7.setup(1516, 3, 17);
- _actor7.setPosition(Common::Point(272, 94));
- _actor7.fixPriority(91);
- _actor7.changeZoom(100);
- _actor7.setDetails(1550, -1, -1, -1, 5, &_arrUnkObj15502[7]);
+ assert((_walkRegionsId >= 1550) && (_walkRegionsId <= 2008));
+ R2_GLOBALS._walkRegions.disableRegion(k5A750[_walkRegionsId - 1550]);
+ _companion.setPosition(Common::Point(scene1550JunkX[k5A76D[_walkRegionsId - 1550]], scene1550JunkY[k5A76D[_walkRegionsId - 1550]] + 8));
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ if (R2_GLOBALS._player._characterScene[R2_SEEKER] == 1580) {
+ _companion.setup(1516, 3, 17);
+ _companion.setPosition(Common::Point(272, 94));
+ _companion.fixPriority(91);
+ _companion.changeZoom(100);
+ _companion.setDetails(1550, -1, -1, -1, 5, &_shipComponents[7]);
} else {
- _actor7.setup(1505, 6, 1);
- _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
+ _companion.setup(1505, 6, 1);
+ _companion.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
}
} else {
- if (R2_GLOBALS._player._characterScene[1] == 1580) {
- _actor7.setup(1516, 2, 14);
- _actor7.setPosition(Common::Point(276, 97));
- _actor7.fixPriority(91);
- _actor7.changeZoom(100);
- _actor7.setDetails(1550, -1, -1, -1, 5, &_arrUnkObj15502[7]);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == 1580) {
+ _companion.setup(1516, 2, 14);
+ _companion.setPosition(Common::Point(276, 97));
+ _companion.fixPriority(91);
+ _companion.changeZoom(100);
+ _companion.setDetails(1550, -1, -1, -1, 5, &_shipComponents[7]);
} else {
- _actor7.setup(1500, 6, 1);
- _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
+ _companion.setup(1500, 6, 1);
+ _companion.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL);
}
}
}
@@ -8661,177 +9265,206 @@ void Scene1550::subA2B2F() {
}
/*--------------------------------------------------------------------------
- * Scene 1575 -
+ * Scene 1575 - Spaceport - unused ship scene
*
*--------------------------------------------------------------------------*/
-Scene1575::Scene1575() {
- _field412 = 0;
- _field414 = 0;
- _field416 = 0;
- _field418 = 0;
- _field41A = 0;
-}
-
-void Scene1575::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
-
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
- s.syncAsSint16LE(_field418);
- s.syncAsSint16LE(_field41A);
-}
-Scene1575::Hotspot1::Hotspot1() {
- _field34 = 0;
- _field36 = 0;
+Scene1575::Button::Button() {
+ _buttonId = 0;
+ _pressed = false;
}
-void Scene1575::Hotspot1::synchronize(Serializer &s) {
+void Scene1575::Button::synchronize(Serializer &s) {
NamedHotspot::synchronize(s);
- s.syncAsSint16LE(_field34);
- s.syncAsSint16LE(_field36);
+ s.syncAsSint16LE(_buttonId);
+ s.syncAsSint16LE(_pressed);
}
-void Scene1575::Hotspot1::process(Event &event) {
- if ((event.eventType != EVENT_BUTTON_DOWN) || (R2_GLOBALS._events.getCursor() != R2_STEPPING_DISKS) || (!_bounds.contains(event.mousePos))) {
- if (_field36 == 0)
- return;
- if ((_field34 == 1) || (event.eventType == EVENT_BUTTON_UP) || (!_bounds.contains(event.mousePos))) {
- _field36 = 0;
- return;
- }
- }
- _field36 = 1;
+void Scene1575::Button::process(Event &event) {
Scene1575 *scene = (Scene1575 *)R2_GLOBALS._sceneManager._scene;
+ bool isInBounds = _bounds.contains(event.mousePos);
+ CursorType cursor = R2_GLOBALS._events.getCursor();
- event.handled = true;
- if (R2_GLOBALS.getFlag(18) && (_field34 > 1) && (_field34 < 6)) {
- warning("sub1A03B(\"Better not move the laser while it\'s firing!\", 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);");
- return;
- }
- int di = scene->_actor1._position.x;
+ if ((event.eventType == EVENT_BUTTON_DOWN && cursor == CURSOR_USE && isInBounds) ||
+ (_pressed && _buttonId != 1 && event.eventType == EVENT_BUTTON_UP && isInBounds)) {
+ // Button pressed
+ _pressed = true;
+ Common::Point pos = scene->_actor1._position;
+ event.handled = true;
- switch (_field34 - 1) {
- case 0:
- if (R2_GLOBALS.getFlag(18)) {
- scene->_actor14.hide();
- scene->_actor15.hide();
- R2_GLOBALS.clearFlag(18);
- } else if ((scene->_actor12._position.x == 85) && (scene->_actor12._position.y == 123)) {
- scene->_actor14.show();
- scene->_actor15.show();
- R2_GLOBALS.setFlag(18);
+ if (!R2_GLOBALS.getFlag(18) || _buttonId <= 1 || _buttonId >= 6) {
+ switch (_buttonId) {
+ case 1:
+ if (R2_GLOBALS.getFlag(18)) {
+ scene->_actor14.hide();
+ scene->_actor15.hide();
+ R2_GLOBALS.clearFlag(18);
+ } else if ((scene->_actor12._position.x == 85) && (scene->_actor12._position.y == 123)) {
+ scene->_actor14.show();
+ scene->_actor15.show();
+ R2_GLOBALS.setFlag(18);
+ } else {
+ SceneItem::display("That's probably not a good thing, ya know!");
+ }
+ break;
+ case 2:
+ if (scene->_field41A < 780) {
+ if (pos.x > 54)
+ pos.x -= 65;
+ pos.x += 2;
+ scene->_field41A += 2;
+
+ 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));
+ scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x + 2, scene->_actor12._position.y));
+ scene->_actor1.setPosition(Common::Point(pos.x, pos.y));
+ scene->_actor2.setPosition(Common::Point(pos.x + 65, pos.y));
+ scene->_actor3.setPosition(Common::Point(pos.x + 130, pos.y));
+ }
+ break;
+ case 3:
+ if (scene->_field41A > 0) {
+ if (pos.x < -8)
+ pos.x += 65;
+
+ pos.x -= 2;
+ scene->_field41A -= 2;
+ 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));
+ scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x - 2, scene->_actor12._position.y));
+ scene->_actor1.setPosition(Common::Point(pos.x, pos.y));
+ scene->_actor2.setPosition(Common::Point(pos.x + 65, pos.y));
+ scene->_actor3.setPosition(Common::Point(pos.x + 130, pos.y));
+ }
+ break;
+ case 4: {
+ if (pos.y < 176) {
+ ++pos.y;
+ for (int i = 0; i < 17; ++i)
+ scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x, scene->_arrActor[i]._position.y + 1));
+
+ scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x, scene->_actor13._position.y + 1));
+ scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x, scene->_actor12._position.y + 1));
+ scene->_actor1.setPosition(Common::Point(pos.x, pos.y));
+ scene->_actor2.setPosition(Common::Point(pos.x + 65, pos.y));
+ scene->_actor3.setPosition(Common::Point(pos.x + 130, pos.y));
+ }
+ }
+ break;
+ case 5: {
+ if (pos.y > 145) {
+ --pos.y;
+ for (int i = 0; i < 17; ++i)
+ scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x, scene->_arrActor[i]._position.y - 1));
+
+ scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x, scene->_actor13._position.y - 1));
+ scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x, scene->_actor12._position.y - 1));
+ scene->_actor1.setPosition(Common::Point(pos.x, pos.y));
+ scene->_actor2.setPosition(Common::Point(pos.x + 65, pos.y));
+ scene->_actor3.setPosition(Common::Point(pos.x + 130, pos.y));
+ }
+ }
+ break;
+ case 6:
+ R2_GLOBALS._sceneManager.changeScene(1550);
+ break;
+ default:
+ break;
+ }
+
+ int j = 0;
+ for (int i = 0; i < 17; i++) {
+ if (scene->_arrActor[i]._bounds.contains(85, 116))
+ j = i;
+ }
+
+ if (scene->_actor13._bounds.contains(85, 116))
+ j = 18;
+
+ if (scene->_actor12._bounds.contains(85, 116))
+ j = 19;
+
+ if (j)
+ scene->_actor11.show();
+ else
+ scene->_actor11.hide();
} else {
- warning("sub1A03B(\"That\'s probably not a good thing, ya know!\", 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);");
+ SceneItem::display("Better not move the laser while it's firing!");
}
- break;
- case 1:
- if (scene->_field41A < 780) {
- if (di > 54)
- di -= 65;
- di += 2;
- scene->_field41A += 2;
+ } else {
+ _pressed = false;
+ }
+}
+
+bool Scene1575::Button::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE)
+ return false;
+ return SceneHotspot::startAction(action, event);
+}
- for (int i = 0; i < 17; i++)
- scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x + 2, scene->_arrActor[i]._position.y));
+void Scene1575::Button::initButton(int buttonId) {
+ _buttonId = buttonId;
+ _pressed = false;
+ EventHandler::postInit();
- scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x + 2, scene->_actor13._position.y));
- scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x + 2, scene->_actor12._position.y));
- scene->_actor1.setPosition(Common::Point(di, scene->_actor1._position.y));
- scene->_actor2.setPosition(Common::Point(di + 65, scene->_actor1._position.y));
- scene->_actor3.setPosition(Common::Point(di + 130, scene->_actor1._position.y));
- }
+ switch (_buttonId) {
+ case 1:
+ setDetails(Rect(53, 165, 117, 190), -1, -1, -1, 2, 1, NULL);
break;
case 2:
- if (scene->_field41A > 0) {
- if (di < -8)
- di += 65;
-
- di -= 2;
- scene->_field41A -= 2;
- for (int i = 0; i < 178; 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));
- scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x - 2, scene->_actor12._position.y));
- scene->_actor1.setPosition(Common::Point(di, scene->_actor1._position.y));
- scene->_actor2.setPosition(Common::Point(di + 65, scene->_actor1._position.y));
- scene->_actor3.setPosition(Common::Point(di + 130, scene->_actor1._position.y));
- }
+ setDetails(Rect(151, 142, 189, 161), -1, -1, -1, 2, 1, NULL);
break;
- case 3: {
- int tmpPosY = scene->_actor1._position.y;
- if (tmpPosY < 176) {
- ++tmpPosY;
- for (int i = 0; i < 17; ++i)
- scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x, scene->_arrActor[i]._position.y + 1));
-
- scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x, scene->_actor13._position.y + 1));
- scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x, scene->_actor12._position.y + 1));
- scene->_actor1.setPosition(Common::Point(di, scene->_actor1._position.y));
- scene->_actor2.setPosition(Common::Point(di + 65, scene->_actor1._position.y));
- scene->_actor3.setPosition(Common::Point(di + 130, scene->_actor1._position.y));
- }
- }
+ case 3:
+ setDetails(Rect(225, 142, 263, 161), -1, -1, -1, 2, 1, NULL);
break;
- case 4: {
- int tmpPosY = scene->_actor1._position.y;
- if (tmpPosY > 145) {
- tmpPosY--;
- for (int i = 0; i < 17; ++i)
- scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x, scene->_arrActor[i]._position.y - 1));
-
- scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x, scene->_actor13._position.y - 1));
- scene->_actor12.setPosition(Common::Point(scene->_actor12._position.x, scene->_actor12._position.y - 1));
- scene->_actor1.setPosition(Common::Point(di, scene->_actor1._position.y));
- scene->_actor2.setPosition(Common::Point(di + 65, scene->_actor1._position.y));
- scene->_actor3.setPosition(Common::Point(di + 130, scene->_actor1._position.y));
- }
- }
+ case 4:
+ setDetails(Rect(188, 122, 226, 140), -1, -1, -1, 2, 1, NULL);
break;
case 5:
- R2_GLOBALS._sceneManager.changeScene(1550);
+ setDetails(Rect(188, 162, 226, 180), -1, -1, -1, 2, 1, NULL);
+ break;
+ case 6:
+ setDetails(Rect(269, 169, 301, 185), -1, -1, -1, 2, 1, NULL);
break;
default:
break;
}
+}
- int j = 0;
- for (int i = 0; i < 17; i++) {
- if (scene->_arrActor[i]._bounds.contains(85, 116))
- j = i;
- }
-
- if (scene->_actor13._bounds.contains(85, 116))
- j = 18;
-
- if (scene->_actor12._bounds.contains(85, 116))
- j = 19;
+/*--------------------------------------------------------------------------*/
- if (j)
- scene->_actor11.show();
- else
- scene->_actor11.hide();
+Scene1575::Scene1575() {
+ _field412 = 0;
+ _field414 = 390;
+ _field416 = 0;
+ _field418 = 0;
+ _field41A = 0;
}
-bool Scene1575::Hotspot1::startAction(CursorType action, Event &event) {
- if (action == CURSOR_USE)
- return false;
- return SceneHotspot::startAction(action, event);
+void Scene1575::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_field414);
+ s.syncAsSint16LE(_field416);
+ s.syncAsSint16LE(_field418);
+ s.syncAsSint16LE(_field41A);
}
-void Scene1575::Hotspot1::subA910D(int indx) {
- warning("STUB: Scene1575:Hotspot1::subA910D(%d)", indx);
+double hypotenuse(double v1, double v2) {
+ return sqrt(v1 * v1 + v2 * v2);
}
void Scene1575::postInit(SceneObjectList *OwnerList) {
loadScene(1575);
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E = Rect(0, 0, 320, 200);
SceneExt::postInit();
- _field414 = 390;
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
_actor1.postInit();
_actor1.setup(1575, 1, 1);
@@ -8850,8 +9483,17 @@ void Scene1575::postInit(SceneObjectList *OwnerList) {
for (int i = 0; i < 17; i++) {
_arrActor[i].postInit();
- _arrActor[i].setup(1575, 2, k5A7F6[(3 * i) + 2]);
- warning("TODO: immense pile of floating operations");
+ _arrActor[i].setup(1575, 2, k5A7F6[3 * i + 2]);
+
+ double v1 = hypotenuse(2.0, 3 - k5A7F6[3 * i]);
+ v1 += hypotenuse(2.0, 3 - k5A7F6[3 * i + 1]);
+ int yp = (int)(sqrt(v1) * 75.0 / 17.0 - 161.0);
+
+ int angle = R2_GLOBALS._gfxManagerInstance.getAngle(
+ Common::Point(3, 16), Common::Point(k5A7F6[3 * i], k5A7F6[3 * i + 1]));
+ int xp = angle * 78 / 9 - 319;
+
+ _arrActor[i].setPosition(Common::Point(xp, yp));
_arrActor[i].fixPriority(6);
}
@@ -8883,12 +9525,13 @@ void Scene1575::postInit(SceneObjectList *OwnerList) {
_actor10.setup(1575, 3, 2);
_actor10.setPosition(Common::Point(287, 91));
- _item1.subA910D(1);
- _item1.subA910D(2);
- _item1.subA910D(3);
- _item1.subA910D(4);
- _item1.subA910D(5);
- _item1.subA910D(6);
+ // Initialize buttons
+ _button1.initButton(1);
+ _button2.initButton(2);
+ _button3.initButton(3);
+ _button4.initButton(4);
+ _button5.initButton(5);
+ _button6.initButton(6);
_actor11.postInit();
_actor11.setup(1575, 4, 2);
@@ -8916,6 +9559,7 @@ void Scene1575::postInit(SceneObjectList *OwnerList) {
_actor13.postInit();
_actor13.setup(1575, 2, 4);
+ // TODO
warning("TODO: another immense pile of floating operations");
_actor12.postInit();
@@ -8941,8 +9585,6 @@ void Scene1575::postInit(SceneObjectList *OwnerList) {
void Scene1575::remove() {
SceneExt::remove();
- R2_GLOBALS._v5589E.top = 3;
- R2_GLOBALS._v5589E.bottom = 168;
R2_GLOBALS._uiElements._active = true;
}
@@ -8954,7 +9596,6 @@ void Scene1575::process(Event &event) {
Scene::process(event);
g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
- warning("TODO: check Scene1575::process");
}
void Scene1575::dispatch() {
@@ -9044,26 +9685,24 @@ void Scene1575::dispatch() {
* Scene 1580 - Inside wreck
*
*--------------------------------------------------------------------------*/
+
Scene1580::Scene1580() {
- _field412 = 0;
}
void Scene1580::synchronize(Serializer &s) {
SceneExt::synchronize(s);
-
- s.syncAsSint16LE(_field412);
}
-bool Scene1580::Hotspot1::startAction(CursorType action, Event &event) {
- Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1580::JoystickPlug::startAction(CursorType action, Event &event) {
if (action == R2_JOYSTICK) {
- R2_INVENTORY.setObjectScene(26, 1580);
- R2_GLOBALS._sceneItems.remove(&scene->_item1);
- scene->_actor2.postInit();
- scene->_actor2.setup(1580, 1, 4);
- scene->_actor2.setPosition(Common::Point(159, 163));
- scene->_actor2.setDetails(1550, 78, -1, -1, 2, (SceneItem *) NULL);
+ Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_INVENTORY.setObjectScene(R2_JOYSTICK, 1580);
+ R2_GLOBALS._sceneItems.remove(&scene->_joystickPlug);
+ scene->_joystick.postInit();
+ scene->_joystick.setup(1580, 1, 4);
+ scene->_joystick.setPosition(Common::Point(159, 163));
+ scene->_joystick.setDetails(1550, 78, -1, -1, 2, (SceneItem *) NULL);
scene->_arrActor[5].remove();
@@ -9073,29 +9712,29 @@ bool Scene1580::Hotspot1::startAction(CursorType action, Event &event) {
return SceneHotspot::startAction(action, event);
}
-bool Scene1580::Hotspot2::startAction(CursorType action, Event &event) {
- Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1580::ScreenSlot::startAction(CursorType action, Event &event) {
if (action == R2_DIAGNOSTICS_DISPLAY) {
- R2_INVENTORY.setObjectScene(28, 1580);
+ Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_INVENTORY.setObjectScene(R2_DIAGNOSTICS_DISPLAY, 1580);
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._sceneItems.remove(&scene->_item2);
+ R2_GLOBALS._sceneItems.remove(&scene->_screenSlot);
- scene->_actor3.postInit();
- scene->_actor3.setup(1580, 1, 1);
- scene->_actor3.setPosition(Common::Point(124, 108));
- scene->_actor3.fixPriority(10);
+ scene->_screen.postInit();
+ scene->_screen.setup(1580, 1, 1);
+ scene->_screen.setPosition(Common::Point(124, 108));
+ scene->_screen.fixPriority(10);
- if (R2_INVENTORY.getObjectScene(26) == 1580)
- scene->_actor3.setDetails(1550, 14, -1, -1, 5, &scene->_actor2);
+ if (R2_INVENTORY.getObjectScene(R2_JOYSTICK) == 1580)
+ scene->_screen.setDetails(1550, 14, -1, -1, 5, &scene->_joystick);
else
- scene->_actor3.setDetails(1550, 14, -1, -1, 2, (SceneItem *)NULL);
+ scene->_screen.setDetails(1550, 14, -1, -1, 2, (SceneItem *)NULL);
- scene->_actor1.postInit();
- scene->_actor1.setup(1580, 3, 1);
- scene->_actor1.setPosition(Common::Point(124, 109));
- scene->_actor1.fixPriority(20);
- scene->_field412 = 1;
+ scene->_screenDisplay.postInit();
+ scene->_screenDisplay.setup(1580, 3, 1);
+ scene->_screenDisplay.setPosition(Common::Point(124, 109));
+ scene->_screenDisplay.fixPriority(20);
+ //scene->_field412 = 1;
scene->_sceneMode = 10;
scene->setAction(&scene->_sequenceManager, scene, 1, &R2_GLOBALS._player, NULL);
@@ -9105,16 +9744,16 @@ bool Scene1580::Hotspot2::startAction(CursorType action, Event &event) {
return SceneHotspot::startAction(action, event);
}
-bool Scene1580::Actor2::startAction(CursorType action, Event &event) {
- if ( (action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(28) == 1580)
- && (R2_INVENTORY.getObjectScene(17) == 0) && (R2_INVENTORY.getObjectScene(22) == 0)
- && (R2_INVENTORY.getObjectScene(25) == 0) && (R2_INVENTORY.getObjectScene(18) == 0)
- && (R2_INVENTORY.getObjectScene(23) == 0) && (R2_INVENTORY.getObjectScene(27) == 0)) {
+bool Scene1580::Joystick::startAction(CursorType action, Event &event) {
+ if ( (action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(R2_DIAGNOSTICS_DISPLAY) == 1580)
+ && (R2_INVENTORY.getObjectScene(R2_FUEL_CELL) == 0) && (R2_INVENTORY.getObjectScene(R2_GUIDANCE_MODULE) == 0)
+ && (R2_INVENTORY.getObjectScene(R2_RADAR_MECHANISM) == 0) && (R2_INVENTORY.getObjectScene(R2_GYROSCOPE) == 0)
+ && (R2_INVENTORY.getObjectScene(R2_THRUSTER_VALVE) == 0) && (R2_INVENTORY.getObjectScene(R2_IGNITOR) == 0)) {
Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
scene->_sceneMode = 31;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_stripManager.start(536, scene);
else
scene->_stripManager.start(537, scene);
@@ -9125,13 +9764,13 @@ bool Scene1580::Actor2::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene1580::Actor3::startAction(CursorType action, Event &event) {
- if ((action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(51) == 1580)) {
+bool Scene1580::Screen::startAction(CursorType action, Event &event) {
+ if ((action == CURSOR_USE) && (R2_INVENTORY.getObjectScene(R2_BROKEN_DISPLAY) == 1580)) {
Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
- R2_INVENTORY.setObjectScene(51, R2_GLOBALS._player._characterIndex);
- scene->_item2.setDetails(Rect(69, 29, 177, 108), 1550, 82, -1, -1, 2, NULL);
- scene->_actor1.remove();
+ R2_INVENTORY.setObjectScene(R2_BROKEN_DISPLAY, R2_GLOBALS._player._characterIndex);
+ scene->_screenSlot.setDetails(Rect(69, 29, 177, 108), 1550, 82, -1, -1, 2, NULL);
+ scene->_screenDisplay.remove();
remove();
return true;
}
@@ -9139,21 +9778,21 @@ bool Scene1580::Actor3::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene1580::Actor4::startAction(CursorType action, Event &event) {
+bool Scene1580::StorageCompartment::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._sceneItems.remove(&scene->_actor4);
+ R2_GLOBALS._sceneItems.remove(&scene->_storageCompartment);
scene->_sceneMode = 0;
animate(ANIM_MODE_5, scene);
return true;
}
-bool Scene1580::Actor5::startAction(CursorType action, Event &event) {
+bool Scene1580::HatchButton::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -9167,13 +9806,13 @@ bool Scene1580::Actor5::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1580::Actor6::startAction(CursorType action, Event &event) {
+bool Scene1580::ThrusterValve::startAction(CursorType action, Event &event) {
Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if (R2_GLOBALS._player._characterIndex == 1) {
- R2_INVENTORY.setObjectScene(23, 1);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ R2_INVENTORY.setObjectScene(R2_THRUSTER_VALVE, 1);
remove();
return true;
}
@@ -9199,13 +9838,13 @@ bool Scene1580::Actor6::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene1580::Actor7::startAction(CursorType action, Event &event) {
+bool Scene1580::Ignitor::startAction(CursorType action, Event &event) {
Scene1580 *scene = (Scene1580 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if (R2_GLOBALS._player._characterIndex == 1) {
- R2_INVENTORY.setObjectScene(27, 1);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ R2_INVENTORY.setObjectScene(R2_IGNITOR, 1);
remove();
return true;
}
@@ -9235,7 +9874,6 @@ void Scene1580::postInit(SceneObjectList *OwnerList) {
loadScene(1580);
R2_GLOBALS._sceneManager._fadeMode = FADEMODE_GRADUAL;
SceneExt::postInit();
- _field412 = 0;
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
@@ -9245,136 +9883,134 @@ void Scene1580::postInit(SceneObjectList *OwnerList) {
_sceneMode = 0;
R2_GLOBALS._player.disableControl();
- if (R2_INVENTORY.getObjectScene(26) == 1580) {
- _actor2.postInit();
- _actor2.setup(1580, 1, 4);
- _actor2.setPosition(Common::Point(159, 163));
- _actor2.setDetails(1550, 78, -1, -1, 1, (SceneItem *) NULL);
+ if (R2_INVENTORY.getObjectScene(R2_JOYSTICK) == 1580) {
+ _joystick.postInit();
+ _joystick.setup(1580, 1, 4);
+ _joystick.setPosition(Common::Point(159, 163));
+ _joystick.setDetails(1550, 78, -1, -1, 1, (SceneItem *) NULL);
} else {
- _item1.setDetails(Rect(141, 148, 179, 167), 1550, 79, -1, -1, 1, NULL);
- }
-
- if (R2_INVENTORY.getObjectScene(51) == 1580) {
- _actor3.postInit();
- _actor3.setup(1580, 1, 1);
- _actor3.setPosition(Common::Point(124, 108));
- _actor3.fixPriority(10);
- _actor3.setDetails(1550, 13, -1, -1, 1, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1580, 1, 3);
- _actor1.setPosition(Common::Point(124, 96));
- _actor1.fixPriority(20);
- } else if (R2_INVENTORY.getObjectScene(28) == 1580) {
- _actor3.postInit();
- _actor3.setup(1580, 1, 1);
- _actor3.setPosition(Common::Point(124, 108));
- _actor3.fixPriority(10);
- _actor3.setDetails(1550, 14, -1, -1, 1, (SceneItem *) NULL);
-
- _actor1.postInit();
- _actor1.setup(1580, 3, 1);
- _actor1.setPosition(Common::Point(124, 109));
- _actor1.fixPriority(20);
+ _joystickPlug.setDetails(Rect(141, 148, 179, 167), 1550, 79, -1, -1, 1, NULL);
+ }
+
+ if (R2_INVENTORY.getObjectScene(R2_BROKEN_DISPLAY) == 1580) {
+ _screen.postInit();
+ _screen.setup(1580, 1, 1);
+ _screen.setPosition(Common::Point(124, 108));
+ _screen.fixPriority(10);
+ _screen.setDetails(1550, 13, -1, -1, 1, (SceneItem *) NULL);
+
+ _screenDisplay.postInit();
+ _screenDisplay.setup(1580, 1, 3);
+ _screenDisplay.setPosition(Common::Point(124, 96));
+ _screenDisplay.fixPriority(20);
+ } else if (R2_INVENTORY.getObjectScene(R2_DIAGNOSTICS_DISPLAY) == 1580) {
+ _screen.postInit();
+ _screen.setup(1580, 1, 1);
+ _screen.setPosition(Common::Point(124, 108));
+ _screen.fixPriority(10);
+ _screen.setDetails(1550, 14, -1, -1, 1, (SceneItem *) NULL);
+
+ _screenDisplay.postInit();
+ _screenDisplay.setup(1580, 3, 1);
+ _screenDisplay.setPosition(Common::Point(124, 109));
+ _screenDisplay.fixPriority(20);
_sceneMode = 10;
} else {
- _item2.setDetails(Rect(69, 29, 177, 108), 1550, 82, -1, -1, 1, NULL);
+ _screenSlot.setDetails(Rect(69, 29, 177, 108), 1550, 82, -1, -1, 1, NULL);
}
- _actor4.postInit();
- if (R2_INVENTORY.getObjectScene(58) == 0) {
- _actor4.setup(1580, 5, 1);
- _actor4.setDetails(1550, 80, -1, -1, 1, (SceneItem *) NULL);
+ _storageCompartment.postInit();
+ if (R2_GLOBALS.getFlag(58) == 0) {
+ _storageCompartment.setup(1580, 5, 1);
+ _storageCompartment.setDetails(1550, 80, -1, -1, 1, (SceneItem *) NULL);
} else {
- _actor4.setup(1580, 5, 6);
+ _storageCompartment.setup(1580, 5, 6);
}
- _actor4.setPosition(Common::Point(216, 108));
- _actor4.fixPriority(100);
+ _storageCompartment.setPosition(Common::Point(216, 108));
+ _storageCompartment.fixPriority(100);
- _actor5.postInit();
- _actor5.setup(1580, 4, 1);
- _actor5.setPosition(Common::Point(291, 147));
- _actor5.fixPriority(100);
- _actor5.setDetails(1550, 81, -1, -1, 1, (SceneItem *) NULL);
+ _hatchButton.postInit();
+ _hatchButton.setup(1580, 4, 1);
+ _hatchButton.setPosition(Common::Point(291, 147));
+ _hatchButton.fixPriority(100);
+ _hatchButton.setDetails(1550, 81, -1, -1, 1, (SceneItem *) NULL);
- if (R2_INVENTORY.getObjectScene(23) == 1580) {
- _actor6.postInit();
- _actor6.setup(1580, 6, 2);
- _actor6.setPosition(Common::Point(222, 108));
- _actor6.fixPriority(50);
- _actor6.setDetails(1550, 32, -1, 34, 1, (SceneItem *) NULL);
+ if (R2_INVENTORY.getObjectScene(R2_THRUSTER_VALVE) == 1580) {
+ _thrusterValve.postInit();
+ _thrusterValve.setup(1580, 6, 2);
+ _thrusterValve.setPosition(Common::Point(222, 108));
+ _thrusterValve.fixPriority(50);
+ _thrusterValve.setDetails(1550, 32, -1, 34, 1, (SceneItem *) NULL);
}
- if (R2_INVENTORY.getObjectScene(27) == 1580) {
- _actor7.postInit();
- _actor7.setup(1580, 6, 1);
- _actor7.setPosition(Common::Point(195, 108));
- _actor7.fixPriority(50);
- _actor7.setDetails(1550, 38, -1, 34, 1, (SceneItem *) NULL);
+ if (R2_INVENTORY.getObjectScene(R2_IGNITOR) == 1580) {
+ _ignitor.postInit();
+ _ignitor.setup(1580, 6, 1);
+ _ignitor.setPosition(Common::Point(195, 108));
+ _ignitor.fixPriority(50);
+ _ignitor.setDetails(1550, 38, -1, 34, 1, (SceneItem *) NULL);
}
R2_GLOBALS._player.postInit();
- R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 1580;
R2_GLOBALS._player.hide();
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- _item3.setDetails(Rect(0, 0, 320, 200), 1550, 50, -1, -1, 1, NULL);
-
+ _background.setDetails(Rect(0, 0, 320, 200), 1550, 50, -1, -1, 1, NULL);
}
void Scene1580::signal() {
switch (_sceneMode++) {
case 10:
- _actor1.animate(ANIM_MODE_5, this);
+ _screenDisplay.animate(ANIM_MODE_5, this);
break;
case 11:
- _actor1.setup(1580, 1, 2);
- _actor1.setPosition(Common::Point(124, 94));
+ _screenDisplay.setup(1580, 1, 2);
+ _screenDisplay.setPosition(Common::Point(124, 94));
- if (R2_INVENTORY.getObjectScene(18) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_GYROSCOPE) != 0) {
_arrActor[0].postInit();
_arrActor[0].setup(1580, 2, 1);
_arrActor[0].setPosition(Common::Point(138, 56));
}
- if (R2_INVENTORY.getObjectScene(25) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_RADAR_MECHANISM) != 0) {
_arrActor[1].postInit();
_arrActor[1].setup(1580, 2, 2);
_arrActor[1].setPosition(Common::Point(140, 66));
}
- if (R2_INVENTORY.getObjectScene(27) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_IGNITOR) != 0) {
_arrActor[2].postInit();
_arrActor[2].setup(1580, 2, 3);
_arrActor[2].setPosition(Common::Point(142, 85));
}
- if (R2_INVENTORY.getObjectScene(23) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_THRUSTER_VALVE) != 0) {
_arrActor[3].postInit();
_arrActor[3].setup(1580, 2, 4);
_arrActor[3].setPosition(Common::Point(142, 92));
}
- if (R2_INVENTORY.getObjectScene(22) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_GUIDANCE_MODULE) != 0) {
_arrActor[4].postInit();
_arrActor[4].setup(1580, 2, 5);
_arrActor[4].setPosition(Common::Point(108, 54));
}
- if (R2_INVENTORY.getObjectScene(26) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_JOYSTICK) != 1580) {
_arrActor[5].postInit();
_arrActor[5].setup(1580, 2, 6);
_arrActor[5].setPosition(Common::Point(110, 64));
}
- if (R2_INVENTORY.getObjectScene(45) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_BATTERY) != 0) {
_arrActor[6].postInit();
_arrActor[6].setup(1580, 2, 7);
_arrActor[6].setPosition(Common::Point(108, 80));
}
- if (R2_INVENTORY.getObjectScene(17) != 0) {
+ if (R2_INVENTORY.getObjectScene(R2_FUEL_CELL) != 0) {
_arrActor[7].postInit();
_arrActor[7].setup(1580, 2, 8);
_arrActor[7].setPosition(Common::Point(111, 92));
@@ -9400,17 +10036,8 @@ void Scene1580::signal() {
* Scene 1625 - Miranda being questioned
*
*--------------------------------------------------------------------------*/
-Scene1625::Scene1625() {
- _field412 = 0;
-}
-
-void Scene1625::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
-
- s.syncAsSint16LE(_field412);
-}
-bool Scene1625::Actor7::startAction(CursorType action, Event &event) {
+bool Scene1625::Wire::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -9418,11 +10045,18 @@ bool Scene1625::Actor7::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1631;
- scene->_actor3.postInit();
- scene->setAction(&scene->_sequenceManager, scene, 1631, &scene->_actor3, &scene->_actor7, NULL);
+ scene->_mirandaMouth.postInit();
+ scene->setAction(&scene->_sequenceManager, scene, 1631, &scene->_mirandaMouth, &scene->_wire, NULL);
return true;
}
+Scene1625::Scene1625() {
+}
+
+void Scene1625::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+}
+
void Scene1625::postInit(SceneObjectList *OwnerList) {
loadScene(1625);
R2_GLOBALS._player._characterIndex = R2_MIRANDA;
@@ -9433,41 +10067,42 @@ void Scene1625::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_soldierSpeaker);
R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.hide();
- _actor7.postInit();
- _actor7.setup(1626, 2, 1);
- _actor7.setPosition(Common::Point(206, 133));
- _actor7.setDetails(1625, 0, -1, -1, 1, (SceneItem *) NULL);
+ _wire.postInit();
+ _wire.setup(1626, 2, 1);
+ _wire.setPosition(Common::Point(206, 133));
+ _wire.setDetails(1625, 0, -1, -1, 1, (SceneItem *) NULL);
- _actor5.postInit();
- _actor5.setup(1625, 8, 1);
- _actor5.setPosition(Common::Point(190, 131));
- _actor5.setDetails(1625, 6, -1, 2, 1, (SceneItem *) NULL);
+ _wristRestraints.postInit();
+ _wristRestraints.setup(1625, 8, 1);
+ _wristRestraints.setPosition(Common::Point(190, 131));
+ _wristRestraints.setDetails(1625, 6, -1, 2, 1, (SceneItem *) NULL);
- if (R2_GLOBALS._player._oldCharacterScene[3] == 1625) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 1625) {
if (!R2_GLOBALS.getFlag(83)) {
- _actor4.postInit();
- _actor4.setup(1626, 4, 1);
- _actor4.setPosition(Common::Point(96, 166));
- _actor4.setDetails(1625, -1, -1, -1, 1, (SceneItem *) NULL);
+ _glass.postInit();
+ _glass.setup(1626, 4, 1);
+ _glass.setPosition(Common::Point(96, 166));
+ _glass.setDetails(1625, -1, -1, -1, 1, (SceneItem *) NULL);
}
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
} else {
- _actor1.postInit();
- _actor1.fixPriority(10);
+ _teal.postInit();
+ _teal.fixPriority(10);
- _actor6.postInit();
+ _tealRightArm.postInit();
R2_GLOBALS._player.disableControl();
_sceneMode = 1625;
- setAction(&_sequenceManager, this, 1625, &_actor1, &_actor6, NULL);
+ setAction(&_sequenceManager, this, 1625, &_teal, &_tealRightArm, NULL);
}
R2_GLOBALS._sound1.play(245);
- _item1.setDetails(Rect(0, 0, 320, 200), 1625, 12, -1, -1, 1, NULL);
- R2_GLOBALS._player._oldCharacterScene[3] = 1625;
- R2_GLOBALS._player._characterScene[3] = 1625;
+ _background.setDetails(Rect(0, 0, 320, 200), 1625, 12, -1, -1, 1, NULL);
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 1625;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 1625;
}
void Scene1625::remove() {
@@ -9479,101 +10114,100 @@ void Scene1625::signal() {
switch (_sceneMode) {
case 10:
R2_GLOBALS._player.disableControl();
- _actor4.postInit();
- _actor4.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
+ _glass.postInit();
+ _glass.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
_sceneMode = 1626;
- setAction(&_sequenceManager, this, 1626, &_actor2, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 1626, &_tealHead, &_glass, NULL);
break;
case 12:
- // TODO: check if OK_BTN_STRING is required
MessageDialog::show(DONE_MSG, OK_BTN_STRING);
break;
case 14:
- _actor2.postInit();
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
+ _tealHead.postInit();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(831, this);
break;
case 99:
R2_GLOBALS._player.disableControl();
- switch (_stripManager._field2E8) {
- case 0:
+ switch (_stripManager._exitMode) {
+ case 1:
_sceneMode = 1627;
- setAction(&_sequenceManager, this, 1627, &_actor3, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 1627, &_mirandaMouth, &_glass, NULL);
break;
- case 1:
+ case 2:
_sceneMode = 1629;
- setAction(&_sequenceManager, this, 1629, &_actor2, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 1629, &_tealHead, &_wristRestraints, NULL);
break;
- case 3:
- R2_GLOBALS._player._oldCharacterScene[3] = 3150;
- R2_GLOBALS._player._characterScene[3] = 3150;
+ case 4:
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3150;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3150;
R2_GLOBALS._player._characterIndex = R2_QUINN;
- R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._characterScene[1]);
+ R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._characterScene[R2_QUINN]);
break;
- case 4:
+ case 5:
_sceneMode = 1628;
- _actor2.remove();
- setAction(&_sequenceManager, this, 1628, &_actor3, &_actor4, NULL);
+ _tealHead.remove();
+ setAction(&_sequenceManager, this, 1628, &_mirandaMouth, &_glass, NULL);
break;
- case 5:
- _actor4.postInit();
- _actor4.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
+ case 6:
+ _glass.postInit();
+ _glass.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
_sceneMode = 1632;
- setAction(&_sequenceManager, this, 1632, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 1632, &_glass, NULL);
break;
- case 6:
+ case 7:
_sceneMode = 1633;
- setAction(&_sequenceManager, this, 1633, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 1633, &_glass, NULL);
break;
- case 7:
+ case 8:
_sceneMode = 1635;
- setAction(&_sequenceManager, this, 1635, &_actor3, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 1635, &_mirandaMouth, &_wristRestraints, NULL);
break;
- case 8:
- _actor4.postInit();
- _actor4.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
+ case 9:
+ _glass.postInit();
+ _glass.setDetails(1625, -1, -1, -1, 2, (SceneItem *) NULL);
_sceneMode = 1634;
- setAction(&_sequenceManager, this, 1634, &_actor3, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 1634, &_mirandaMouth, &_wristRestraints, NULL);
break;
- case 2:
+ case 3:
// No break on purpose
default:
_sceneMode = 1630;
- _actor2.postInit();
- setAction(&_sequenceManager, this, 1630, &_actor1, &_actor6, NULL);
+ _tealHead.remove();
+ setAction(&_sequenceManager, this, 1630, &_teal, &_tealRightArm, NULL);
break;
}
- _field412 = _stripManager._field2E8;
+ //_field412 = _stripManager._field2E8;
_stripManager._field2E8 = 0;
break;
case 1625:
- _actor2.postInit();
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
+ _tealHead.postInit();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
_sceneMode = 10;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(800, this);
break;
case 1626:
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
- _actor2.show();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
+ _tealHead.show();
- _actor3.postInit();
- _actor3.setup(1627, 3, 1);
- _actor3.setPosition(Common::Point(196, 65));
+ _mirandaMouth.postInit();
+ _mirandaMouth.setup(1627, 3, 1);
+ _mirandaMouth.setPosition(Common::Point(196, 65));
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(832, this);
break;
case 1627:
- _actor3.setup(1627, 3, 1);
- _actor3.setPosition(Common::Point(196, 65));
- _actor3.show();
+ _mirandaMouth.setup(1627, 3, 1);
+ _mirandaMouth.setPosition(Common::Point(196, 65));
+ _mirandaMouth.show();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -9581,22 +10215,22 @@ void Scene1625::signal() {
break;
case 1628:
R2_GLOBALS.setFlag(83);
- _actor2.postInit();
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
+ _tealHead.postInit();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
- _actor3.setup(1627, 3, 1);
- _actor3.setPosition(Common::Point(196, 65));
- _actor3.show();
+ _mirandaMouth.setup(1627, 3, 1);
+ _mirandaMouth.setPosition(Common::Point(196, 65));
+ _mirandaMouth.show();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(834, this);
break;
case 1629:
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
- _actor2.show();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
+ _tealHead.show();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -9607,34 +10241,33 @@ void Scene1625::signal() {
R2_GLOBALS._player._canWalk = true;
break;
case 1631:
- _actor3.setup(1627, 3, 1);
- _actor3.setPosition(Common::Point(196, 65));
- _actor3.show();
+ _mirandaMouth.setup(1627, 3, 1);
+ _mirandaMouth.setPosition(Common::Point(196, 65));
+ _mirandaMouth.show();
- _actor7.remove();
+ _wire.remove();
- _actor1.postInit();
- _actor1.fixPriority(10);
+ _teal.postInit();
+ _teal.fixPriority(10);
- _actor6.postInit();
- warning("_actor6._actorName = \"arm\";");
+ _tealRightArm.postInit();
- R2_INVENTORY.setObjectScene(40, 3);
+ R2_INVENTORY.setObjectScene(R2_SUPERCONDUCTOR_WIRE, 3);
_sceneMode = 14;
- setAction(&_sequenceManager, this, 1625, &_actor1, &_actor6, NULL);
+ setAction(&_sequenceManager, this, 1625, &_teal, &_tealRightArm, NULL);
break;
case 1632:
- _actor2.setup(1627, 1, 1);
- _actor2.setPosition(Common::Point(68, 68));
- _actor2.show();
+ _tealHead.setup(1627, 1, 1);
+ _tealHead.setPosition(Common::Point(68, 68));
+ _tealHead.show();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(835, this);
break;
case 1633:
- _actor4.remove();
+ _glass.remove();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
_stripManager.start(818, this);
@@ -9645,9 +10278,9 @@ void Scene1625::signal() {
_stripManager.start(836, this);
break;
case 1635:
- _actor3.setup(1627, 3, 1);
- _actor3.setPosition(Common::Point(196, 65));
- _actor3.show();
+ _mirandaMouth.setup(1627, 3, 1);
+ _mirandaMouth.setPosition(Common::Point(196, 65));
+ _mirandaMouth.show();
_sceneMode = 99;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -9666,35 +10299,27 @@ void Scene1625::process(Event &event) {
}
/*--------------------------------------------------------------------------
- * Scene 1700 -
+ * Scene 1700 - Rim
*
*--------------------------------------------------------------------------*/
+
Scene1700::Scene1700() {
- _field77A = 0;
- _field77C = 0;
+ _walkFlag = 0;
}
void Scene1700::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field77A);
- s.syncAsSint16LE(_field77C);
-}
-
-bool Scene1700::Item2::startAction(CursorType action, Event &event) {
- // The original contains a debug trace. It's currently skipped.
- // TODO: either add the debug trace, or remove this function and associated class
- return SceneHotspot::startAction(action, event);
+ s.syncAsSint16LE(_walkFlag);
}
-bool Scene1700::Actor11::startAction(CursorType action, Event &event) {
+bool Scene1700::RimTransport::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1700 *scene = (Scene1700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._v558B6.set(80, 0, 240, 200);
scene->_sceneMode = 4;
Common::Point pt(271, 90);
@@ -9704,7 +10329,7 @@ bool Scene1700::Actor11::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1700::Actor12::startAction(CursorType action, Event &event) {
+bool Scene1700::Companion::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
@@ -9715,7 +10340,7 @@ bool Scene1700::Actor12::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1700::Exit1::changeScene() {
+void Scene1700::NorthExit::changeScene() {
Scene1700 *scene = (Scene1700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
@@ -9727,7 +10352,7 @@ void Scene1700::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1700::Exit2::changeScene() {
+void Scene1700::SouthExit::changeScene() {
Scene1700 *scene = (Scene1700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
@@ -9739,7 +10364,7 @@ void Scene1700::Exit2::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1700::Exit3::changeScene() {
+void Scene1700::WestExit::changeScene() {
Scene1700 *scene = (Scene1700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
@@ -9751,97 +10376,92 @@ void Scene1700::Exit3::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1700::subAF3F8() {
+void Scene1700::enterArea() {
Rect tmpRect;
R2_GLOBALS._walkRegions.load(1700);
- _actor3.remove();
- _actor4.remove();
- _actor5.remove();
- _actor6.remove();
- _actor7.remove();
- _actor8.remove();
- _actor11.remove();
+ _slabWest.remove();
+ _slabEast.remove();
+ _slabShadowWest.remove();
+ _slabShadowEast.remove();
+ _westPlatform.remove();
+ _rimTransportDoor.remove();
+ _rimTransport.remove();
if (_sceneMode != 40) {
- _actor9.remove();
- _actor10.remove();
+ _ledgeHopper.remove();
+ _hatch.remove();
}
- warning("tmpRect = _v5589E;");
- warning("Mouse_hideIfNeeded");
- warning("set_pane_p(_paneNumber);");
- warning("Big loop calling gfx_draw_slice_p");
-
- if (_field77A == 0)
- _field77A = 1;
- else
- _field77A = 0;
-
- warning("set_pane_p(_paneNumber);");
+ // The original had manual code here to redraw the background manually when
+ // changing areas within the scene. Which seems to be totally redundant.
- if ((_sceneMode != 40) && (R2_GLOBALS._v565F6 != 0)){
- _actor9.postInit();
- _actor9.setup(1701, 1, 1);
- _actor9.setPosition(Common::Point(220, 137));
- _actor9.setDetails(1700, 6, -1, -1, 2, (SceneItem *) NULL);
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(12);
+ if (_sceneMode != 40 && R2_GLOBALS._rimLocation == 0) {
+ // Crashed ledge hopper
+ _ledgeHopper.postInit();
+ _ledgeHopper.setup(1701, 1, 1);
+ _ledgeHopper.setPosition(Common::Point(220, 137));
+ _ledgeHopper.setDetails(1700, 6, -1, -1, 2, (SceneItem *) NULL);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(12);
}
- if ((R2_GLOBALS._v565F6 + 2) % 4 == 0) {
- _actor3.postInit();
- _actor3.setup(1700, 1, 1);
- _actor3.setPosition(Common::Point(222, 82));
- _actor3.setDetails(100, -1, -1, -1, 2, (SceneItem *) NULL);
+ if ((R2_GLOBALS._rimLocation + 2) % 4 == 0) {
+ // The slabs forming the bottom of the regular rings the rim transport travels through
+ _slabWest.postInit();
+ _slabWest.setup(1700, 1, 1);
+ _slabWest.setPosition(Common::Point(222, 82));
+ _slabWest.setDetails(100, -1, -1, -1, 2, (SceneItem *) NULL);
- _actor5.postInit();
- _actor5.setup(1700, 2, 1);
- _actor5.setPosition(Common::Point(177, 82));
- _actor5.fixPriority(0);
+ _slabShadowWest.postInit();
+ _slabShadowWest.setup(1700, 2, 1);
+ _slabShadowWest.setPosition(Common::Point(177, 82));
+ _slabShadowWest.fixPriority(0);
- _actor6.postInit();
- _actor6.setup(1700, 2, 2);
- _actor6.setPosition(Common::Point(332, 96));
- _actor6.fixPriority(0);
+ _slabShadowEast.postInit();
+ _slabShadowEast.setup(1700, 2, 2);
+ _slabShadowEast.setPosition(Common::Point(332, 96));
+ _slabShadowEast.fixPriority(0);
- _actor4.postInit();
- _actor4.setup(1700, 1, 2);
- _actor4.setPosition(Common::Point(424, 84));
+ _slabEast.postInit();
+ _slabEast.setup(1700, 1, 2);
+ _slabEast.setPosition(Common::Point(424, 84));
- R2_GLOBALS._walkRegions.enableRegion(11);
+ R2_GLOBALS._walkRegions.disableRegion(11);
}
- if ((R2_GLOBALS._v565F6 + 399) % 800 == 0) {
- _actor7.postInit();
- _actor7.setup(1700, 3, 2);
- _actor7.setPosition(Common::Point(51, 141));
- _actor7.fixPriority(0);
- _actor7.setDetails(100, -1, -1, -1, 2, (SceneItem *) NULL);
+ if ((R2_GLOBALS._rimLocation + 399) % 800 == 0) {
+ // Enable west exit to lift
+ _westPlatform.postInit();
+ _westPlatform.setup(1700, 3, 2);
+ _westPlatform.setPosition(Common::Point(51, 141));
+ _westPlatform.fixPriority(0);
+ _westPlatform.setDetails(100, -1, -1, -1, 2, (SceneItem *) NULL);
- _exit3._enabled = true;
+ _westExit._enabled = true;
} else {
- R2_GLOBALS._walkRegions.enableRegion(1);
- _exit3._enabled = false;
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ _westExit._enabled = false;
}
- if ( ((!R2_GLOBALS.getFlag(15)) && ((R2_GLOBALS._v565F6 == 25) || (R2_GLOBALS._v565F6 == -3)))
- || ((R2_GLOBALS.getFlag(15)) && (R2_GLOBALS._v565F6 == R2_GLOBALS._v565FA))
+ if ( ((!R2_GLOBALS.getFlag(15)) && ((R2_GLOBALS._rimLocation == 25) || (R2_GLOBALS._rimLocation == -3)))
+ || ((R2_GLOBALS.getFlag(15)) && (R2_GLOBALS._rimLocation == R2_GLOBALS._rimTransportLocation))
) {
- R2_GLOBALS._v565FA = R2_GLOBALS._v565F6;
+ // Rim transport vechile located
+ R2_GLOBALS._rimTransportLocation = R2_GLOBALS._rimLocation;
if (!R2_GLOBALS.getFlag(15))
- _field77C = 1;
+ _walkFlag = true;
- _actor11.postInit();
- _actor11.setup(1700, 3, 1);
- _actor11.setPosition(Common::Point(338, 150));
- _actor11.setDetails(1700, 9, -1, -1, 2, (SceneItem *) NULL);
- _actor11.fixPriority(15);
+ _rimTransport.postInit();
+ _rimTransport.setup(1700, 3, 1);
+ _rimTransport.setPosition(Common::Point(338, 150));
+ _rimTransport.setDetails(1700, 9, -1, -1, 2, (SceneItem *) NULL);
+ _rimTransport.fixPriority(15);
- _actor8.postInit();
- _actor8.setup(1700, 4, 1);
- _actor8.setPosition(Common::Point(312, 106));
- _actor8.fixPriority(130);
+ _rimTransportDoor.postInit();
+ _rimTransportDoor.setup(1700, 4, 1);
+ _rimTransportDoor.setPosition(Common::Point(312, 106));
+ _rimTransportDoor.fixPriority(130);
}
}
@@ -9855,12 +10475,9 @@ void Scene1700::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
- _field77A = 0;
- _field77C = 0;
-
- _exit1.setDetails(Rect(94, 0, 319, 12), EXITCURSOR_N, 1700);
- _exit2.setDetails(Rect(0, 161, 319, 168), EXITCURSOR_S, 1700);
- _exit3.setDetails(Rect(0, 0, 2, 138), EXITCURSOR_W, 1800);
+ _northExit.setDetails(Rect(94, 0, 319, 12), EXITCURSOR_N, 1700);
+ _southExit.setDetails(Rect(0, 161, 319, 168), EXITCURSOR_S, 1700);
+ _westExit.setDetails(Rect(0, 0, 12, 138), EXITCURSOR_W, 1800);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setPosition(Common::Point(0, 0));
@@ -9873,44 +10490,44 @@ void Scene1700::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 1);
}
- _actor12.postInit();
- _actor12.animate(ANIM_MODE_1, NULL);
- _actor12.setObjectWrapper(new SceneObjectWrapper());
+ _companion.postInit();
+ _companion.animate(ANIM_MODE_1, NULL);
+ _companion.setObjectWrapper(new SceneObjectWrapper());
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor12.setVisage(1506);
- _actor12._moveDiff = Common::Point(3, 1);
- _actor12.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
+ _companion.setVisage(1506);
+ _companion._moveDiff = Common::Point(3, 1);
+ _companion.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
} else {
- _actor12.setVisage(1501);
- _actor12._moveDiff = Common::Point(2, 1);
- _actor12.setDetails(9001, 1, -1, -1, 1, (SceneItem *) NULL);
+ _companion.setVisage(1501);
+ _companion._moveDiff = Common::Point(2, 1);
+ _companion.setDetails(9001, 1, -1, -1, 1, (SceneItem *) NULL);
}
R2_GLOBALS._sound1.play(134);
- _actor1.postInit();
- _actor1.fixPriority(10);
+ _playerShadow.postInit();
+ _playerShadow.fixPriority(10);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor1.setVisage(1112);
+ _playerShadow.setVisage(1112);
else
- _actor1.setVisage(1111);
+ _playerShadow.setVisage(1111);
- _actor1._effect = 5;
- _actor1._field9C = _field312;
- R2_GLOBALS._player._linkedActor = &_actor1;
+ _playerShadow._effect = EFFECT_SHADOW_MAP;
+ _playerShadow._shadowMap = _shadowPaletteMap;
+ R2_GLOBALS._player._linkedActor = &_playerShadow;
- _actor2.postInit();
- _actor2.fixPriority(10);
+ _companionShadow.postInit();
+ _companionShadow.fixPriority(10);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor2.setVisage(1111);
+ _companionShadow.setVisage(1111);
else
- _actor2.setVisage(1112);
+ _companionShadow.setVisage(1112);
- _actor2._effect = 5;
- _actor2._field9C = _field312;
- _actor12._linkedActor = &_actor2;
+ _companionShadow._effect = EFFECT_SHADOW_MAP;
+ _companionShadow._shadowMap = _shadowPaletteMap;
+ _companion._linkedActor = &_companionShadow;
R2_GLOBALS._sound1.play(134);
@@ -9919,75 +10536,74 @@ void Scene1700::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._characterIndex = R2_QUINN;
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.hide();
- _actor12.hide();
+ _companion.hide();
- _actor10.postInit();
- warning("_actor10._actorName = \"hatch\";");
- _actor10.hide();
+ _hatch.postInit();
+ _hatch.hide();
- _actor9.postInit();
- _actor9.setup(1701, 1, 1);
- _actor9.setPosition(Common::Point(220, 137));
- _actor9.setDetails(1700, 6, -1, -1, 1, (SceneItem *) NULL);
+ _ledgeHopper.postInit();
+ _ledgeHopper.setup(1701, 1, 1);
+ _ledgeHopper.setPosition(Common::Point(220, 137));
+ _ledgeHopper.setDetails(1700, 6, -1, -1, 1, (SceneItem *) NULL);
- _actor1.hide();
- _actor2.hide();
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ _playerShadow.hide();
+ _companionShadow.hide();
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_stripManager.start(539, this);
_sceneMode = 40;
break;
case 1750: {
R2_GLOBALS._player.setPosition(Common::Point(282, 121));
- _actor12.setPosition(Common::Point(282, 139));
+ _companion.setPosition(Common::Point(282, 139));
_sceneMode = 8;
Common::Point pt(262, 101);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
Common::Point pt2(262, 119);
NpcMover *mover2 = new NpcMover();
- _actor12.addMover(mover2, &pt2, this);
+ _companion.addMover(mover2, &pt2, this);
}
break;
case 1800: {
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.setPosition(Common::Point(0, 86));
- _actor12.setPosition(Common::Point(0, 64));
+ _companion.setPosition(Common::Point(0, 64));
_sceneMode = 7;
R2_GLOBALS._player.setObjectWrapper(NULL);
R2_GLOBALS._player._strip = 1;
Common::Point pt(64, 86);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
- _actor12.setObjectWrapper(NULL);
- _actor12._strip = 1;
+ _companion.setObjectWrapper(NULL);
+ _companion._strip = 1;
Common::Point pt2(77, 64);
NpcMover *mover2 = new NpcMover();
- _actor12.addMover(mover2, &pt2, NULL);
+ _companion.addMover(mover2, &pt2, NULL);
}
break;
default:
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setPosition(Common::Point(109, 160));
- _actor12.setPosition(Common::Point(156, 160));
- R2_GLOBALS._walkRegions.enableRegion(15);
+ _companion.setPosition(Common::Point(156, 160));
+ R2_GLOBALS._walkRegions.disableRegion(15);
} else {
R2_GLOBALS._player.setPosition(Common::Point(156, 160));
- _actor12.setPosition(Common::Point(109, 160));
- R2_GLOBALS._walkRegions.enableRegion(17);
+ _companion.setPosition(Common::Point(109, 160));
+ R2_GLOBALS._walkRegions.disableRegion(17);
}
_sceneMode = 50;
setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
break;
}
- R2_GLOBALS._player._characterScene[1] = 1700;
- R2_GLOBALS._player._characterScene[2] = 1700;
- R2_GLOBALS._player._oldCharacterScene[1] = 1700;
- R2_GLOBALS._player._oldCharacterScene[2] = 1700;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1700;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1700;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1700;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1700;
+
+ enterArea();
- R2_GLOBALS._v558B6.set(20, 0, 320, 200);
- subAF3F8();
- _item1.setDetails(1, 1700, 3, -1, -1);
- _item2.setDetails(Rect(0, 0, 480, 200), 1700, 0, -1, -1, 1, NULL);
+ _surface.setDetails(1, 1700, 3, -1, -1);
+ _background.setDetails(Rect(0, 0, 480, 200), 1700, 0, -1, -1, 1, NULL);
}
void Scene1700::remove() {
@@ -9999,62 +10615,62 @@ void Scene1700::signal() {
switch (_sceneMode) {
case 1: {
_sceneMode = 3;
- if ((R2_GLOBALS._v565F6 < 2400) && (R2_GLOBALS._v565F6 >= 0))
- ++R2_GLOBALS._v565F6;
- subAF3F8();
+ if (R2_GLOBALS._rimLocation < 2400)
+ ++R2_GLOBALS._rimLocation;
+ enterArea();
R2_GLOBALS._player.setPosition(Common::Point(235 - (((((235 - R2_GLOBALS._player._position.x) * 100) / 103) * 167) / 100), 170));
Common::Point pt(R2_GLOBALS._player._position.x, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
if (R2_GLOBALS._player._position.x < 132) {
- _actor12.setPosition(Common::Point(156, 170));
+ _companion.setPosition(Common::Point(156, 170));
Common::Point pt2(156, 160);
NpcMover *mover2 = new NpcMover();
- _actor12.addMover(mover2, &pt2, NULL);
- R2_GLOBALS._walkRegions.enableRegion(15);
+ _companion.addMover(mover2, &pt2, NULL);
+ R2_GLOBALS._walkRegions.disableRegion(15);
} else {
- _actor12.setPosition(Common::Point(109, 170));
+ _companion.setPosition(Common::Point(109, 170));
Common::Point pt3(109, 160);
NpcMover *mover3 = new NpcMover();
- _actor12.addMover(mover3, &pt3, NULL);
- R2_GLOBALS._walkRegions.enableRegion(17);
+ _companion.addMover(mover3, &pt3, NULL);
+ R2_GLOBALS._walkRegions.disableRegion(17);
}
}
break;
case 2: {
_sceneMode = 3;
- if ((R2_GLOBALS._v565F6 > -2400) && (R2_GLOBALS._v565F6 < 0))
- R2_GLOBALS._v565F6--;
- subAF3F8();
+ if (R2_GLOBALS._rimLocation > -2400)
+ --R2_GLOBALS._rimLocation;
+ enterArea();
R2_GLOBALS._player.setPosition(Common::Point(235 - (((((235 - R2_GLOBALS._player._position.x) * 100) / 167) * 103) / 100), 0));
Common::Point pt(R2_GLOBALS._player._position.x, 10);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
if (R2_GLOBALS._player._position.x >= 171) {
- _actor12.setPosition(Common::Point(155, 0));
+ _companion.setPosition(Common::Point(155, 0));
Common::Point pt2(155, 10);
NpcMover *mover2 = new NpcMover();
- _actor12.addMover(mover2, &pt2, NULL);
- R2_GLOBALS._walkRegions.enableRegion(15);
+ _companion.addMover(mover2, &pt2, NULL);
+ R2_GLOBALS._walkRegions.disableRegion(15);
} else {
- _actor12.setPosition(Common::Point(188, 0));
+ _companion.setPosition(Common::Point(188, 0));
Common::Point pt3(188, 10);
NpcMover *mover3 = new NpcMover();
- _actor12.addMover(mover3, &pt3, NULL);
- R2_GLOBALS._walkRegions.enableRegion(17);
+ _companion.addMover(mover3, &pt3, NULL);
+ R2_GLOBALS._walkRegions.disableRegion(17);
}
}
break;
case 3:
- if (_field77C == 0) {
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ if (!_walkFlag) {
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
} else {
R2_GLOBALS.setFlag(15);
- _field77C = 0;
+ _walkFlag = false;
_sceneMode = 31;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_stripManager.start(542, this);
else
@@ -10065,11 +10681,11 @@ void Scene1700::signal() {
_sceneMode = 5;
Common::Point pt(271, 90);
PlayerMover *mover = new PlayerMover();
- _actor12.addMover(mover, &pt, NULL);
- if (R2_GLOBALS._player._characterIndex == 1)
- setAction(&_sequenceManager, this, 1700, &R2_GLOBALS._player, &_actor8, NULL);
+ _companion.addMover(mover, &pt, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ setAction(&_sequenceManager, this, 1700, &R2_GLOBALS._player, &_rimTransportDoor, NULL);
else
- setAction(&_sequenceManager, this, 1701, &R2_GLOBALS._player, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 1701, &R2_GLOBALS._player, &_rimTransportDoor, NULL);
}
break;
case 5:
@@ -10081,16 +10697,16 @@ void Scene1700::signal() {
case 7:
R2_GLOBALS._player.setObjectWrapper(new SceneObjectWrapper());
R2_GLOBALS._player._strip = 1;
- _actor12.setObjectWrapper(new SceneObjectWrapper());
- _actor12._strip = 1;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- R2_GLOBALS._walkRegions.enableRegion(14);
+ _companion.setObjectWrapper(new SceneObjectWrapper());
+ _companion._strip = 1;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ R2_GLOBALS._walkRegions.disableRegion(14);
break;
case 8:
R2_GLOBALS._player._strip = 2;
- _actor12._strip = 1;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- R2_GLOBALS._walkRegions.enableRegion(12);
+ _companion._strip = 1;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ R2_GLOBALS._walkRegions.disableRegion(12);
break;
case 30:
_sceneMode = 31;
@@ -10102,29 +10718,29 @@ void Scene1700::signal() {
_stripManager.start(541, this);
break;
case 31:
- R2_GLOBALS._v56AAB = 0;
R2_GLOBALS._player.enableControl(CURSOR_TALK);
break;
case 40:
R2_GLOBALS._player.disableControl();
_sceneMode = 1704;
- setAction(&_sequenceManager, this, 1704, &R2_GLOBALS._player, &_actor12, &_actor10, &_actor9, &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 1704, &R2_GLOBALS._player, &_companion,
+ &_hatch, &_ledgeHopper, &_playerShadow, &_companionShadow, NULL);
break;
case 50:
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- R2_GLOBALS._walkRegions.enableRegion(15);
+ R2_GLOBALS._walkRegions.disableRegion(15);
else
- R2_GLOBALS._walkRegions.enableRegion(17);
+ R2_GLOBALS._walkRegions.disableRegion(17);
R2_GLOBALS._player.enableControl();
break;
case 1704:
R2_GLOBALS._sound1.play(134);
- R2_GLOBALS._walkRegions.enableRegion(15);
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(12);
+ R2_GLOBALS._walkRegions.disableRegion(15);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(12);
R2_GLOBALS._player.fixPriority(-1);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
default:
R2_GLOBALS._player.enableControl();
@@ -10133,182 +10749,189 @@ void Scene1700::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1750 -
+ * Scene 1750 - Maintaiance Vechile
*
*--------------------------------------------------------------------------*/
-Scene1750::Actor4::Actor4() {
- _fieldA4 = 0;
- _fieldA6 = 0;
- _fieldA8 = 0;
- _fieldAA = 0;
- _fieldAC = 0;
- _fieldAE = 0;
+
+Scene1750::Button::Button() {
+ _buttonId = 0;
}
-void Scene1750::Actor4::synchronize(Serializer &s) {
+void Scene1750::Button::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
- s.syncAsSint16LE(_fieldA8);
- s.syncAsSint16LE(_fieldAA);
- s.syncAsSint16LE(_fieldAC);
- s.syncAsSint16LE(_fieldAE);
+ s.syncAsSint16LE(_buttonId);
}
-Scene1750::Actor5::Actor5() {
- _fieldA4 = 0;
-}
+bool Scene1750::Button::startAction(CursorType action, Event &event) {
+ if (action != CURSOR_USE)
+ return SceneActor::startAction(action, event);
-void Scene1750::Actor5::synchronize(Serializer &s) {
- SceneActor::synchronize(s);
+ Scene1750 *scene = (Scene1750 *)R2_GLOBALS._sceneManager._scene;
- s.syncAsSint16LE(_fieldA4);
+ switch (_buttonId) {
+ case 1:
+ // Forward button
+ show();
+ scene->_backwardButton.hide();
+ if (scene->_speed < 0)
+ scene->_speed = -scene->_speed;
+ scene->_direction = 1;
+ break;
+ case 2:
+ // Backwards button
+ show();
+ scene->_forwardButton.hide();
+ if (scene->_speed > 0)
+ scene->_speed = -scene->_speed;
+ scene->_direction = -1;
+ break;
+ case 3:
+ // Exit button
+ if (scene->_rotation->_idxChange == 0) {
+ show();
+ R2_GLOBALS._sceneManager.changeScene(1700);
+ } else {
+ scene->_speed = 0;
+ scene->_speedSlider._moveRate = 20;
+ scene->_forwardButton._moveDiff.y = 1;
+ Common::Point pt(286, 143);
+ NpcMover *mover = new NpcMover();
+ scene->_speedSlider.addMover(mover, &pt, NULL);
+ }
+ default:
+ break;
+ }
+
+ return true;
}
-Scene1750::Scene1750() {
- _field412 = 0;
- _field413 = 0;
- _field415 = 0;
- _field417 = 0;
- _field419 = 0;
- _field41B = 0;
- _field41D = 0;
+/*------------------------------------------------------------------------*/
+
+Scene1750::SpeedSlider::SpeedSlider() {
+ _incrAmount = 0;
+ _xp = 0;
+ _ys = 0;
+ _height = 0;
+ _thumbHeight = 0;
+ _mouseDown = false;
}
-void Scene1750::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
- SYNC_POINTER(_rotation);
+void Scene1750::SpeedSlider::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field413);
- s.syncAsSint16LE(_field415);
- s.syncAsSint16LE(_field417);
- s.syncAsSint16LE(_field419);
- s.syncAsSint16LE(_field41B);
- s.syncAsSint16LE(_field41D);
-}
-
-void Scene1750::Actor4::subB1A76(int arg1, int arg2, int arg3, int arg4, int arg5) {
- _fieldA4 = arg1;
- _fieldAE = 0;
- _fieldA6 = arg2;
- _fieldA8 = arg3;
- _fieldAA = arg4;
- _fieldAC = arg5;
+ s.syncAsSint16LE(_incrAmount);
+ s.syncAsSint16LE(_xp);
+ s.syncAsSint16LE(_ys);
+ s.syncAsSint16LE(_height);
+ s.syncAsSint16LE(_thumbHeight);
+ s.syncAsSint16LE(_mouseDown);
+}
+
+void Scene1750::SpeedSlider::setupSlider(int incrAmount, int xp, int ys, int height, int thumbHeight) {
+ _mouseDown = false;
+ _incrAmount = incrAmount;
+ _xp = xp;
+ _ys = ys;
+ _height = height;
+ _thumbHeight = thumbHeight;
postInit();
setup(1750, 1, 1);
fixPriority(255);
- setPosition(Common::Point(_fieldA6, _fieldA8 + ((_fieldAA * (arg1 - 1)) / (_fieldAC - 1))));
+ setPosition(Common::Point(_xp, _ys + ((_height * (incrAmount - 1)) / (_thumbHeight - 1))));
}
-void Scene1750::Actor4::subB1B27() {
+void Scene1750::SpeedSlider::calculateSlider() {
Scene1750 *scene = (Scene1750 *)R2_GLOBALS._sceneManager._scene;
- int tmpVar = (_fieldAA / (_fieldAC - 1)) / 2;
- int tmpVar2 = ((_position.y - _fieldA8 + tmpVar) * _fieldAC) / (_fieldAA + 2 * tmpVar);
-
- setPosition(Common::Point(_fieldA6, _fieldA8 + ((_fieldAA * tmpVar2) / (_fieldAC - 1))));
- scene->_field415 = scene->_field412 * tmpVar2;
-}
+ int tmpVar = (_height / (_thumbHeight - 1)) / 2;
+ int tmpVar2 = ((_position.y - _ys + tmpVar) * _thumbHeight) / (_height + 2 * tmpVar);
-void Scene1750::Actor4::remove() {
- // Function kept to match IDA. Could be removed.
- SceneActor::remove();
+ setPosition(Common::Point(_xp, _ys + ((_height * tmpVar2) / (_thumbHeight - 1))));
+ scene->_speed = scene->_direction * tmpVar2;
}
-void Scene1750::Actor4::process(Event &event) {
- if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE) && (_bounds.contains(event.mousePos))) {
- _fieldAE = 1;
+void Scene1750::SpeedSlider::process(Event &event) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE) &&
+ (_bounds.contains(event.mousePos))) {
+ _mouseDown = true;
event.eventType = EVENT_NONE;
}
- if ((event.eventType == EVENT_BUTTON_UP) && (_fieldAE != 0)) {
- _fieldAE = 0;
+ if ((event.eventType == EVENT_BUTTON_UP) && _mouseDown) {
+ _mouseDown = false;
event.handled = true;
addMover(NULL);
- subB1B27();
+ calculateSlider();
}
- if (_fieldAE != 0) {
+ if (_mouseDown) {
event.handled = true;
- if (event.mousePos.y >= _fieldA8) {
- if (_fieldA8 + _fieldAA >= event.mousePos.y)
- setPosition(Common::Point(_fieldA6, event.mousePos.y));
+ if (event.mousePos.y >= _ys) {
+ if (_ys + _height >= event.mousePos.y)
+ setPosition(Common::Point(_xp, event.mousePos.y));
else
- setPosition(Common::Point(_fieldA6, _fieldA8 + _fieldAA));
+ setPosition(Common::Point(_xp, _ys + _height));
} else {
- setPosition(Common::Point(_fieldA6, _fieldA8));
+ setPosition(Common::Point(_xp, _ys));
}
}
}
-bool Scene1750::Actor4::startAction(CursorType action, Event &event) {
+bool Scene1750::SpeedSlider::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE)
return SceneActor::startAction(action, event);
return false;
}
-bool Scene1750::Actor5::startAction(CursorType action, Event &event) {
- if (action != CURSOR_USE)
- return SceneActor::startAction(action, event);
+/*------------------------------------------------------------------------*/
- Scene1750 *scene = (Scene1750 *)R2_GLOBALS._sceneManager._scene;
+Scene1750::Scene1750() {
+ _direction = 0;
+ _speedCurrent = 0;
+ _speed = 0;
+ _speedDelta = 0;
+ _rotationSegment = 0;
+ _rotationSegCurrent = 0;
+ _newRotation = 0;
- switch (_fieldA4) {
- case 1:
- show();
- scene->_actor6.hide();
- if (scene->_field415 < 0)
- scene->_field415 ^= 0xFFFE;
- scene->_field412 = 1;
- break;
- case 2:
- show();
- scene->_actor5.hide();
- if (scene->_field415 > 0)
- scene->_field415 ^= 0xFFFE;
- scene->_field412 = -1;
- break;
- case 3:
- if (scene->_rotation->_idxChange == 0) {
- show();
- R2_GLOBALS._sceneManager.changeScene(1700);
- } else {
- scene->_field415 = 0;
- scene->_actor4._moveRate = 20;
- scene->_actor5._moveDiff.y = 1;
- Common::Point pt(286, 143);
- NpcMover *mover = new NpcMover();
- scene->_actor4.addMover(mover, &pt, NULL);
- }
- default:
- break;
- }
+ _rotation = nullptr;
+}
- return true;
+void Scene1750::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+ SYNC_POINTER(_rotation);
+
+ s.syncAsSint16LE(_direction);
+ s.syncAsSint16LE(_speedCurrent);
+ s.syncAsSint16LE(_speed);
+ s.syncAsSint16LE(_speedDelta);
+ s.syncAsSint16LE(_rotationSegment);
+ s.syncAsSint16LE(_rotationSegCurrent);
+ s.syncAsSint16LE(_newRotation);
}
void Scene1750::postInit(SceneObjectList *OwnerList) {
loadScene(1750);
R2_GLOBALS._sound1.play(115);
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E.set(0, 0, 320, 200);
+
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
- R2_GLOBALS._player._characterScene[1] = 1750;
- R2_GLOBALS._player._characterScene[2] = 1750;
- R2_GLOBALS._player._oldCharacterScene[1] = 1750;
- R2_GLOBALS._player._oldCharacterScene[2] = 1750;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1750;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1750;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1750;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1750;
_rotation = R2_GLOBALS._scenePalette.addRotation(224, 254, 1);
_rotation->setDelay(0);
_rotation->_idxChange = 0;
_rotation->_countdown = 2;
- switch ((R2_GLOBALS._v565F6 + 2) % 4) {
+ switch ((R2_GLOBALS._rimLocation + 2) % 4) {
case 0:
_rotation->_currIndex = 247;
break;
@@ -10346,79 +10969,75 @@ void Scene1750::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.enableControl();
- _actor3.postInit();
- _actor3.setup(1750, 3, 1);
- _actor3.setPosition(Common::Point(49, 185));
- _actor3.fixPriority(7);
- _actor3.setDetails(1750, 30, -1, -1, 1, (SceneItem *) NULL);
+ _radarSweep.postInit();
+ _radarSweep.setup(1750, 3, 1);
+ _radarSweep.setPosition(Common::Point(49, 185));
+ _radarSweep.fixPriority(7);
+ _radarSweep.setDetails(1750, 30, -1, -1, 1, (SceneItem *) NULL);
- _actor1.postInit();
- _actor1.setup(1750, 2, 1);
- _actor1.setPosition(Common::Point(35, ((_rotation->_currIndex - 218) % 4) + ((R2_GLOBALS._v565F6 % 800) * 4) - 1440));
- _actor1.fixPriority(8);
+ _scannerIcon.postInit();
+ _scannerIcon.setup(1750, 2, 1);
+ _scannerIcon.setPosition(Common::Point(35, ((_rotation->_currIndex - 218) % 4) + ((R2_GLOBALS._rimLocation % 800) * 4) - 1440));
+ _scannerIcon.fixPriority(8);
- _actor2.postInit();
- _actor2.setup(1750, 1, 4);
+ _redLights.postInit();
+ _redLights.setup(1750, 1, 4);
- int tmpVar = abs(_actor1._position.y - 158) / 100;
+ int tmpVar = ABS(_scannerIcon._position.y - 158) / 100;
if (tmpVar >= 8)
- _actor2.hide();
- else if (_actor1._position.y <= 158)
- _actor2.setPosition(Common::Point(137, (tmpVar * 7) + 122));
+ _redLights.hide();
+ else if (_scannerIcon._position.y <= 158)
+ _redLights.setPosition(Common::Point(137, (tmpVar * 7) + 122));
else
- _actor2.setPosition(Common::Point(148, (tmpVar * 7) + 122));
-
- _actor4.subB1A76(1, 286, 143, 41, 15);
- _actor4.setDetails(1750, 24, 1, -1, 1, (SceneItem *) NULL);
-
- _actor5.postInit();
- _actor5._fieldA4 = 1;
- _actor5.setup(1750, 1, 2);
- _actor5.setPosition(Common::Point(192, 140));
- _actor5.setDetails(1750, 18, 1, -1, 1, (SceneItem *) NULL);
-
- _actor6.postInit();
- _actor6._fieldA4 = 2;
- _actor6.setup(1750, 1, 3);
- _actor6.setPosition(Common::Point(192, 163));
- _actor6.setDetails(1750, 18, 1, -1, 1, (SceneItem *) NULL);
- _actor6.hide();
-
- _actor7.postInit();
- _actor7._fieldA4 = 3;
- _actor7.setup(1750, 1, 5);
- _actor7.setPosition(Common::Point(230, 183));
- _actor7.setDetails(1750, 27, 1, -1, 1, (SceneItem *) NULL);
-
- _field412 = 1;
- _field417 = 0;
- _field413 = 0;
- _field415 = 0;
- _field419 = ((_rotation->_currIndex - 218) / 4) % 4;
-
- _item2.setDetails(Rect(129, 112, 155, 175), 1750, 21, -1, -1, 1, NULL);
- _item3.setDetails(Rect(93, 122, 126, 172), 1750, 15, -1, -1, 1, NULL);
- _item4.setDetails(Rect(3, 3, 157, 99), 1750, 9, -1, -1, 1, NULL);
- _item5.setDetails(Rect(162, 3, 316, 99), 1750, 12, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 1750, 6, 1, -1, 1, NULL);
+ _redLights.setPosition(Common::Point(148, (tmpVar * 7) + 122));
+
+ _speedSlider.setupSlider(1, 286, 143, 41, 15);
+ _speedSlider.setDetails(1750, 24, 1, -1, 1, (SceneItem *) NULL);
+
+ _forwardButton.postInit();
+ _forwardButton._buttonId = 1;
+ _forwardButton.setup(1750, 1, 2);
+ _forwardButton.setPosition(Common::Point(192, 140));
+ _forwardButton.setDetails(1750, 18, 1, -1, 1, (SceneItem *) NULL);
+
+ _backwardButton.postInit();
+ _backwardButton._buttonId = 2;
+ _backwardButton.setup(1750, 1, 3);
+ _backwardButton.setPosition(Common::Point(192, 163));
+ _backwardButton.setDetails(1750, 18, 1, -1, 1, (SceneItem *) NULL);
+ _backwardButton.hide();
+
+ _exitButton.postInit();
+ _exitButton._buttonId = 3;
+ _exitButton.setup(1750, 1, 5);
+ _exitButton.setPosition(Common::Point(230, 183));
+ _exitButton.setDetails(1750, 27, 1, -1, 1, (SceneItem *) NULL);
+
+ _direction = 1; // Forward by default
+ _speedDelta = 0;
+ _speedCurrent = 0;
+ _speed = 0;
+ _rotationSegment = ((_rotation->_currIndex - 218) / 4) % 4;
+
+ _redLightsDescr.setDetails(Rect(129, 112, 155, 175), 1750, 21, -1, -1, 1, NULL);
+ _greenLights.setDetails(Rect(93, 122, 126, 172), 1750, 15, -1, -1, 1, NULL);
+ _frontView.setDetails(Rect(3, 3, 157, 99), 1750, 9, -1, -1, 1, NULL);
+ _rearView.setDetails(Rect(162, 3, 316, 99), 1750, 12, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 1750, 6, 1, -1, 1, NULL);
}
void Scene1750::remove() {
- _rotation->remove();
+ if (R2_GLOBALS._rimLocation == 2400)
+ R2_GLOBALS._rimLocation = 2399;
- if (R2_GLOBALS._v565F6 == 2400)
- R2_GLOBALS._v565F6 = 2399;
+ if (R2_GLOBALS._rimLocation == -2400)
+ R2_GLOBALS._rimLocation = -2399;
- if (R2_GLOBALS._v565F6 == -2400)
- R2_GLOBALS._v565F6 = -2399;
-
- R2_GLOBALS._v565FA = R2_GLOBALS._v565F6;
+ R2_GLOBALS._rimTransportLocation = R2_GLOBALS._rimLocation;
SceneExt::remove();
R2_GLOBALS._sound1.fadeOut2(NULL);
- R2_GLOBALS._v5589E.top = 3;
- R2_GLOBALS._v5589E.bottom = 168;
R2_GLOBALS._uiElements._active = true;
}
@@ -10429,26 +11048,97 @@ void Scene1750::signal() {
void Scene1750::process(Event &event) {
Scene::process(event);
if (!event.handled)
- _actor4.process(event);
+ _speedSlider.process(event);
}
-void Scene1750::dispatch() {}
+void Scene1750::dispatch() {
+ if (_rotation) {
+ if (!_speedDelta && (_speed != _speedCurrent)) {
+ if (_speedCurrent >= _speed)
+ --_speedCurrent;
+ else
+ ++_speedCurrent;
+
+ _speedDelta = 21 - ABS(_speedCurrent);
+ }
+
+ if (_speedDelta == 1) {
+ if (_speedCurrent == 0) {
+ _radarSweep.show();
+ _rotation->_idxChange = 0;
+ } else {
+ if (_rotation->_idxChange == 0)
+ _radarSweep.hide();
+
+ if (_speedCurrent < -12) {
+ _rotation->setDelay(15 - ABS(_speedCurrent));
+ _rotation->_idxChange = -2;
+ } else if (_speedCurrent < 0) {
+ _rotation->setDelay(10 - ABS(_speedCurrent));
+ _rotation->_idxChange = -1;
+ } else if (_speedCurrent < 11) {
+ _rotation->setDelay(10 - _speedCurrent);
+ _rotation->_idxChange = 1;
+ } else {
+ _rotation->setDelay(15 - _speedCurrent);
+ _rotation->_idxChange = 2;
+ }
+ }
+ }
+
+ if (_speedDelta)
+ --_speedDelta;
+
+ _rotationSegCurrent = _rotationSegment;
+ _rotationSegment = ((_rotation->_currIndex - 218) / 4) % 4;
+
+ if ((_rotationSegCurrent + 1) == _rotationSegment || (_rotationSegCurrent - 3) == _rotationSegment) {
+ if (R2_GLOBALS._rimLocation < 2400) {
+ ++R2_GLOBALS._rimLocation;
+ }
+ }
+
+ if ((_rotationSegCurrent - 1) == _rotationSegment || (_rotationSegCurrent + 3) == _rotationSegment) {
+ if (R2_GLOBALS._rimLocation > -2400) {
+ --R2_GLOBALS._rimLocation;
+ }
+ }
+
+ if (_rotation->_currIndex != _newRotation) {
+ // Handle setting the position of the lift icon in the scanner display
+ _newRotation = _rotation->_currIndex;
+ _scannerIcon.setPosition(Common::Point(35, ((_rotation->_currIndex - 218) % 4) +
+ ((R2_GLOBALS._rimLocation % 800) * 4) - 1440));
+ }
+ }
+
+ int v = ABS(_scannerIcon._position.y - 158) / 100;
+ if (v < 8) {
+ // Show how close the user is to the lift on the second column of lights
+ _redLights.show();
+ _redLights.setPosition(Common::Point((_scannerIcon._position.y <= 158) ? 137 : 148,
+ v * 7 + 122));
+ } else {
+ _redLights.hide();
+ }
+}
/*--------------------------------------------------------------------------
- * Scene 1800 -
+ * Scene 1800 - Rim Lift Exterior
*
*--------------------------------------------------------------------------*/
+
Scene1800::Scene1800() {
- _field412 = 0;
+ _locationMode = 0;
}
void Scene1800::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_locationMode);
}
-bool Scene1800::Hotspot5::startAction(CursorType action, Event &event) {
+bool Scene1800::Background::startAction(CursorType action, Event &event) {
if ((action != R2_COM_SCANNER) && (action != R2_COM_SCANNER_2))
return false;
@@ -10457,7 +11147,7 @@ bool Scene1800::Hotspot5::startAction(CursorType action, Event &event) {
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- if (R2_GLOBALS._v565F6 == 1201) {
+ if (R2_GLOBALS._rimLocation == 1201) {
scene->_stripManager.start(548, this);
} else if (R2_GLOBALS.getFlag(66)) {
return false;
@@ -10465,7 +11155,7 @@ bool Scene1800::Hotspot5::startAction(CursorType action, Event &event) {
scene->_stripManager.start(546, this);
}
} else {
- if (R2_GLOBALS._v565F6 == 1201) {
+ if (R2_GLOBALS._rimLocation == 1201) {
scene->_stripManager.start(549, this);
} else if (R2_GLOBALS.getFlag(66)) {
return false;
@@ -10478,7 +11168,7 @@ bool Scene1800::Hotspot5::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1800::Actor6::startAction(CursorType action, Event &event) {
+bool Scene1800::Lever::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -10494,40 +11184,47 @@ bool Scene1800::Actor6::startAction(CursorType action, Event &event) {
if (_frame == 1) {
R2_GLOBALS.setFlag(64);
scene->_sceneMode = 1810;
- scene->setAction(&scene->_sequenceManager, scene, 1810, &R2_GLOBALS._player, &scene->_actor6, &scene->_actor4, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1810, &R2_GLOBALS._player, &scene->_lever, &scene->_leftStaircase, &scene->_rightStaircase, NULL);
} else {
R2_GLOBALS.clearFlag(64);
scene->_sceneMode = 1811;
- scene->setAction(&scene->_sequenceManager, scene, 1811, &R2_GLOBALS._player, &scene->_actor6, &scene->_actor4, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1811, &R2_GLOBALS._player, &scene->_lever, &scene->_leftStaircase, &scene->_rightStaircase, NULL);
}
return true;
}
-bool Scene1800::Actor7::startAction(CursorType action, Event &event) {
+bool Scene1800::Doors::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1800 *scene = (Scene1800 *)R2_GLOBALS._sceneManager._scene;
if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ // Seeker trying to force open the door
R2_GLOBALS._player.disableControl();
- if (scene->_field412 >= 2) {
+ if (scene->_locationMode >= 2) {
if (R2_GLOBALS.getFlag(14)) {
+ // Allow door to close
scene->_sceneMode = 1809;
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
} else {
+ // Force open door
scene->_sceneMode = 1808;
- scene->setAction(&scene->_sequenceManager, scene, 1808, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1808, &R2_GLOBALS._player, &scene->_doors, NULL);
R2_GLOBALS.setFlag(14);
}
} else {
+ // Seeker failing to force open doors
scene->_sceneMode = 1813;
- scene->setAction(&scene->_sequenceManager, scene, 1813, &R2_GLOBALS._player, NULL);
+ // Original was using 1813 in setAction too, but it somewhat broken.
+ // Seeker goes 2 pixels to high, hiding behind the door
+ scene->setAction(&scene->_sequenceManager, scene, 1808, &R2_GLOBALS._player, &scene->_doors, NULL);
}
} else if (R2_GLOBALS.getFlag(14)) {
return SceneActor::startAction(action, event);
} else {
+ // Quinn trying to force open doors
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1812;
scene->setAction(&scene->_sequenceManager, scene, 1812, &R2_GLOBALS._player, NULL);
@@ -10536,40 +11233,40 @@ bool Scene1800::Actor7::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1800::Actor8::startAction(CursorType action, Event &event) {
+bool Scene1800::PassengerDoor::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
Scene1800 *scene = (Scene1800 *)R2_GLOBALS._sceneManager._scene;
if (_position.x < 160) {
- if (scene->_actor4._frame == 1) {
+ if (scene->_leftStaircase._frame == 1) {
return SceneActor::startAction(action, event);
} else {
R2_GLOBALS.setFlag(29);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(14)) {
- scene->_sceneMode = 1804;
- scene->setAction(&scene->_sequenceManager, scene, 1804, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor8, NULL);
- } else {
scene->_sceneMode = 1;
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &scene->_companion, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
+ } else {
+ scene->_sceneMode = 1804;
+ scene->setAction(&scene->_sequenceManager, scene, 1804, &R2_GLOBALS._player, &scene->_companion, &scene->_leftDoor, NULL);
}
} else {
if (R2_GLOBALS.getFlag(14)) {
scene->_sceneMode = 1;
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
} else {
scene->_sceneMode = 1805;
- scene->setAction(&scene->_sequenceManager, scene, 1805, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor8, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1805, &R2_GLOBALS._player, &scene->_companion, &scene->_leftDoor, NULL);
}
}
}
} else {
- if (scene->_actor4._frame == 1) {
+ if (scene->_leftStaircase._frame == 1) {
return SceneActor::startAction(action, event);
} else {
R2_GLOBALS.clearFlag(29);
@@ -10577,20 +11274,20 @@ bool Scene1800::Actor8::startAction(CursorType action, Event &event) {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(14)) {
scene->_sceneMode = 2;
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &scene->_companion, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
} else {
scene->_sceneMode = 1806;
- scene->setAction(&scene->_sequenceManager, scene, 1806, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor9, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1806, &R2_GLOBALS._player, &scene->_companion, &scene->_rightDoor, NULL);
}
} else {
if (R2_GLOBALS.getFlag(14)) {
scene->_sceneMode = 2;
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
} else {
scene->_sceneMode = 1807;
- scene->setAction(&scene->_sequenceManager, scene, 1807, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor9, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1807, &R2_GLOBALS._player, &scene->_companion, &scene->_rightDoor, NULL);
}
}
}
@@ -10599,25 +11296,25 @@ bool Scene1800::Actor8::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1800::Exit1::changeScene() {
+void Scene1800::SouthExit::changeScene() {
Scene1800 *scene = (Scene1800 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(14)) {
scene->_sceneMode = 3;
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &scene->_companion, &scene->_doors, NULL);
else
- scene->setAction(&scene->_sequenceManager, scene, 1809, &scene->_actor2, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1809, &R2_GLOBALS._player, &scene->_doors, NULL);
R2_GLOBALS.clearFlag(14);
} else {
scene->_sceneMode = 1802;
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL);
else
- scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL);
}
}
@@ -10629,95 +11326,98 @@ void Scene1800::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_seekerSpeaker);
if (R2_GLOBALS._sceneManager._previousScene == -1)
- R2_GLOBALS._v565F6 = 1201;
+ R2_GLOBALS._rimLocation = 1201;
- if (R2_GLOBALS._v565F6 == 1201)
- _field412 = 2;
+ // Set the mode based on whether this is the "correct" lift or not
+ if (R2_GLOBALS._rimLocation == 1201)
+ _locationMode = 2;
else
- _field412 = 0;
+ _locationMode = 0;
scalePalette(65, 65, 65);
- _exit1.setDetails(Rect(0, 160, 319, 168), EXITCURSOR_S, 1800);
- _item5.setDetails(Rect(0, 0, 320, 200), -1, -1, -1, -1, 1, NULL);
-
- _actor6.postInit();
- _actor6.setup(1801, 4, 1);
- _actor6.setPosition(Common::Point(170, 24));
- _actor6.setDetails(1800, 13, 14, 15, 1, (SceneItem *) NULL);
-
- _actor7.postInit();
- _actor7.setup(1801, 3, 1);
- _actor7.setPosition(Common::Point(160, 139));
- _actor7.setDetails(1800, 6, -1, -1, 1, (SceneItem *) NULL);
-
- _actor8.postInit();
- _actor8.setup(1800, 1, 1);
- _actor8.setPosition(Common::Point(110, 78));
- _actor8.fixPriority(135);
- _actor8.setDetails(1800, 20, -1, -1, 1, (SceneItem *) NULL);
-
- _actor9.postInit();
- _actor9.setup(1800, 2, 1);
- _actor9.setPosition(Common::Point(209, 78));
- _actor9.fixPriority(135);
- _actor9.setDetails(1800, 20, -1, -1, 1, (SceneItem *) NULL);
-
- _actor4.postInit();
- if ((_field412 != 1) && (_field412 != 3) && (!R2_GLOBALS.getFlag(64)))
- _actor4.setup(1801, 2, 1);
+ _southExit.setDetails(Rect(0, 160, 319, 168), EXITCURSOR_S, 1800);
+ _background.setDetails(Rect(0, 0, 320, 200), -1, -1, -1, -1, 1, NULL);
+
+ _lever.postInit();
+ _lever.setup(1801, 4, 1);
+ _lever.setPosition(Common::Point(170, 124));
+ _lever.setDetails(1800, 13, 14, 15, 1, (SceneItem *) NULL);
+
+ _doors.postInit();
+ _doors.setup(1801, 3, 1);
+ _doors.setPosition(Common::Point(160, 139));
+ _doors.setDetails(1800, 6, -1, -1, 1, (SceneItem *) NULL);
+
+ _leftDoor.postInit();
+ _leftDoor.setup(1800, 1, 1);
+ _leftDoor.setPosition(Common::Point(110, 78));
+ _leftDoor.fixPriority(135);
+ _leftDoor.setDetails(1800, 20, -1, -1, 1, (SceneItem *) NULL);
+
+ _rightDoor.postInit();
+ _rightDoor.setup(1800, 2, 1);
+ _rightDoor.setPosition(Common::Point(209, 78));
+ _rightDoor.fixPriority(135);
+ _rightDoor.setDetails(1800, 20, -1, -1, 1, (SceneItem *) NULL);
+
+ _leftStaircase.postInit();
+ if ((_locationMode != 1) && (_locationMode != 3) && (!R2_GLOBALS.getFlag(64)))
+ _leftStaircase.setup(1801, 2, 1);
else
- _actor4.setup(1801, 2, 10);
- _actor4.setPosition(Common::Point(76, 142));
- _actor4.setDetails(1800, 3, -1, -1, 1, (SceneItem *) NULL);
+ _leftStaircase.setup(1801, 2, 10);
+ _leftStaircase.setPosition(Common::Point(76, 142));
+ _leftStaircase.setDetails(1800, 3, -1, -1, 1, (SceneItem *) NULL);
- _actor5.postInit();
- if ((_field412 != 1) && (_field412 != 3) && (!R2_GLOBALS.getFlag(64)))
- _actor5.setup(1801, 1, 1);
+ _rightStaircase.postInit();
+ if ((_locationMode != 1) && (_locationMode != 3) && (!R2_GLOBALS.getFlag(64)))
+ _rightStaircase.setup(1801, 1, 1);
else
- _actor5.setup(1801, 1, 10);
- _actor5.setPosition(Common::Point(243, 142));
- _actor5.setDetails(1800, 3, -1, -1, 1, (SceneItem *) NULL);
+ _rightStaircase.setup(1801, 1, 10);
+ _rightStaircase.setPosition(Common::Point(243, 142));
+ _rightStaircase.setDetails(1800, 3, -1, -1, 1, (SceneItem *) NULL);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ // Standard Quinn setup
+ R2_GLOBALS._player.setVisage(1503);
+ R2_GLOBALS._player._moveDiff = Common::Point(2, 2);
+ } else {
+ // Seeker setup dependent on whether he's holding the doors or not
if (R2_GLOBALS.getFlag(14)) {
R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL);
R2_GLOBALS._player.setObjectWrapper(NULL);
R2_GLOBALS._player.setup(1801, 5, 12);
R2_GLOBALS._player.setPosition(Common::Point(160, 139));
- R2_GLOBALS._walkRegions.enableRegion(9);
- _actor7.hide();
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ _doors.hide();
} else {
R2_GLOBALS._player.setVisage(1507);
}
R2_GLOBALS._player._moveDiff = Common::Point(4, 2);
- } else {
- R2_GLOBALS._player.setVisage(1503);
- R2_GLOBALS._player._moveDiff = Common::Point(2, 2);
}
- _actor2.postInit();
- _actor2.animate(ANIM_MODE_1, NULL);
- _actor2.setObjectWrapper(new SceneObjectWrapper());
+ _companion.postInit();
+ _companion.animate(ANIM_MODE_1, NULL);
+ _companion.setObjectWrapper(new SceneObjectWrapper());
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(14)) {
- _actor2.animate(ANIM_MODE_NONE, NULL);
- _actor2.setObjectWrapper(NULL);
- _actor2.setup(1801, 5, 12);
+ _companion.animate(ANIM_MODE_NONE, NULL);
+ _companion.setObjectWrapper(NULL);
+ _companion.setup(1801, 5, 12);
- R2_GLOBALS._walkRegions.enableRegion(9);
- _actor7.hide();
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ _doors.hide();
} else {
- _actor2.setup(1507, 1, 1);
- _actor2.setPosition(Common::Point(180, 160));
+ _companion.setup(1507, 1, 1);
+ _companion.setPosition(Common::Point(180, 160));
}
- _actor2.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
- _actor2._moveDiff = Common::Point(4, 2);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
+ _companion._moveDiff = Common::Point(4, 2);
} else {
- _actor2.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
- _actor2.setVisage(1503);
- _actor2._moveDiff = Common::Point(2, 2);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
+ _companion.setVisage(1503);
+ _companion._moveDiff = Common::Point(2, 2);
}
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1800) {
@@ -10725,12 +11425,12 @@ void Scene1800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setPosition(Common::Point(114, 150));
R2_GLOBALS._player.setStrip(5);
if (R2_GLOBALS.getFlag(14)) {
- _actor2.setPosition(Common::Point(160, 139));
- R2_GLOBALS._walkRegions.enableRegion(8);
+ _companion.setPosition(Common::Point(160, 139));
+ R2_GLOBALS._walkRegions.disableRegion(8);
} else {
- _actor2.setPosition(Common::Point(209, 150));
- _actor2.setStrip(6);
- R2_GLOBALS._walkRegions.enableRegion(8);
+ _companion.setPosition(Common::Point(209, 150));
+ _companion.setStrip(6);
+ R2_GLOBALS._walkRegions.disableRegion(8);
}
} else {
if (R2_GLOBALS.getFlag(14)) {
@@ -10740,55 +11440,55 @@ void Scene1800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setPosition(Common::Point(209, 150));
R2_GLOBALS._player.setStrip(6);
}
- _actor2.setPosition(Common::Point(114, 150));
- _actor2.setStrip(5);
- R2_GLOBALS._walkRegions.enableRegion(10);
- R2_GLOBALS._walkRegions.enableRegion(11);
+ _companion.setPosition(Common::Point(114, 150));
+ _companion.setStrip(5);
+ R2_GLOBALS._walkRegions.disableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(11);
}
} else {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setPosition(Common::Point(140, 160));
- _actor2.setPosition(Common::Point(180, 160));
+ _companion.setPosition(Common::Point(180, 160));
} else {
R2_GLOBALS._player.setPosition(Common::Point(180, 160));
- _actor2.setPosition(Common::Point(140, 160));
+ _companion.setPosition(Common::Point(140, 160));
}
}
- _actor1.postInit();
- _actor1.fixPriority(10);
+ _playerShadow.postInit();
+ _playerShadow.fixPriority(10);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor1.setVisage(1111);
+ _playerShadow.setVisage(1111);
else
- _actor1.setVisage(1110);
+ _playerShadow.setVisage(1110);
- _actor1._effect = 5;
- _actor1._field9C = _field312;
+ _playerShadow._effect = EFFECT_SHADOW_MAP;
+ _playerShadow._shadowMap = _shadowPaletteMap;
- R2_GLOBALS._player._linkedActor = &_actor1;
+ R2_GLOBALS._player._linkedActor = &_playerShadow;
- _actor3.postInit();
- _actor3.fixPriority(10);
+ _companionShadow.postInit();
+ _companionShadow.fixPriority(10);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor3.setVisage(1110);
+ _companionShadow.setVisage(1110);
else
- _actor3.setVisage(1111);
+ _companionShadow.setVisage(1111);
- _actor3._effect = 5;
- _actor3._field9C = _field312;
+ _companionShadow._effect = EFFECT_SHADOW_MAP;
+ _companionShadow._shadowMap = _shadowPaletteMap;
- _actor2._linkedActor = &_actor3;
+ _companion._linkedActor = &_companionShadow;
- R2_GLOBALS._player._characterScene[1] = 1800;
- R2_GLOBALS._player._characterScene[2] = 1800;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1800;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1800;
- _item2.setDetails(Rect(128, 95, 190, 135), 1800, 10, -1, -1, 1, NULL);
- _item1.setDetails(Rect(95, 3, 223, 135), 1800, 0, -1, -1, 1, NULL);
+ _elevatorContents.setDetails(Rect(128, 95, 190, 135), 1800, 10, -1, -1, 1, NULL);
+ _elevator.setDetails(Rect(95, 3, 223, 135), 1800, 0, -1, -1, 1, NULL);
// Original was calling _item3.setDetails(Rect(1800, 11, 24, 23), 25, -1, -1, -1, 1, NULL);
// This is *wrong*. The following statement is a wild guess based on good common sense
- _item3.setDetails(11, 1800, 23, 24, 25);
- _item4.setDetails(Rect(0, 0, 320, 200), 1800, 17, -1, 19, 1, NULL);
+ _surface.setDetails(11, 1800, 23, 24, 25);
+ _secBackground.setDetails(Rect(0, 0, 320, 200), 1800, 17, -1, 19, 1, NULL);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1800) {
@@ -10796,38 +11496,38 @@ void Scene1800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
} else {
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
}
} else if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1850) {
if (R2_GLOBALS.getFlag(29)) {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_sceneMode = 1814;
- setAction(&_sequenceManager, this, 1814, &R2_GLOBALS._player, &_actor2, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 1814, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
} else {
_sceneMode = 1815;
- setAction(&_sequenceManager, this, 1815, &R2_GLOBALS._player, &_actor2, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 1815, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
}
} else {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_sceneMode = 1816;
- setAction(&_sequenceManager, this, 1816, &R2_GLOBALS._player, &_actor2, &_actor9, NULL);
+ setAction(&_sequenceManager, this, 1816, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
} else {
_sceneMode = 1817;
- setAction(&_sequenceManager, this, 1817, &R2_GLOBALS._player, &_actor2, &_actor9, NULL);
+ setAction(&_sequenceManager, this, 1817, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
}
}
} else {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_sceneMode = 1800;
- setAction(&_sequenceManager, this, 1800, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 1800, &R2_GLOBALS._player, &_companion, NULL);
} else {
_sceneMode = 1801;
- setAction(&_sequenceManager, this, 1801, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 1801, &R2_GLOBALS._player, &_companion, NULL);
}
}
- R2_GLOBALS._player._oldCharacterScene[1] = 1800;
- R2_GLOBALS._player._oldCharacterScene[2] = 1800;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1800;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1800;
}
void Scene1800::signal() {
@@ -10835,27 +11535,27 @@ void Scene1800::signal() {
case 1:
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_sceneMode = 1804;
- setAction(&_sequenceManager, this, 1804, &R2_GLOBALS._player, &_actor2, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 1804, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
} else {
_sceneMode = 1805;
- setAction(&_sequenceManager, this, 1805, &R2_GLOBALS._player, &_actor2, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 1805, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
}
break;
case 2:
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_sceneMode = 1806;
- setAction(&_sequenceManager, this, 1806, &R2_GLOBALS._player, &_actor2, &_actor9, NULL);
+ setAction(&_sequenceManager, this, 1806, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
} else {
_sceneMode = 1807;
- setAction(&_sequenceManager, this, 1807, &R2_GLOBALS._player, &_actor2, &_actor9, NULL);
+ setAction(&_sequenceManager, this, 1807, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
}
break;
case 3:
_sceneMode = 1802;
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- setAction(&_sequenceManager, this, 1802, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 1802, &R2_GLOBALS._player, &_companion, NULL);
else
- setAction(&_sequenceManager, this, 1803, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 1803, &R2_GLOBALS._player, &_companion, NULL);
break;
case 10:
// No break on purpose
@@ -10884,8 +11584,31 @@ void Scene1800::signal() {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.enableControl(CURSOR_USE);
break;
+ // Cases 23 and 24 have been added to fix missing hardcoded logic in the original,
+ // when Seeker tries to open the door
+ case 23:
+ _sceneMode = 24;
+ R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._player.setup(1801, 5, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_8, NULL);
+ _stripManager.start(550, this);
+ break;
+ case 24:
+ R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._player.setup(1507, 4, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+
+ _doors.setup(1801, 3, 1);
+ _doors.setPosition(Common::Point(160, 139));
+ _doors.setDetails(1800, 6, -1, -1, 1, (SceneItem *) NULL);
+ _doors.show();
+
+ R2_GLOBALS._player._position.y += 2;
+ R2_GLOBALS._player.show();
+ break;
case 1800:
- R2_GLOBALS._walkRegions.enableRegion(8);
+ R2_GLOBALS._walkRegions.disableRegion(8);
if (R2_GLOBALS.getFlag(63))
R2_GLOBALS._player.enableControl(CURSOR_USE);
else {
@@ -10895,14 +11618,14 @@ void Scene1800::signal() {
}
break;
case 1801:
- R2_GLOBALS._walkRegions.enableRegion(10);
- R2_GLOBALS._walkRegions.enableRegion(11);
+ R2_GLOBALS._walkRegions.disableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(11);
R2_GLOBALS.setFlag(63);
// The following check is completely dumb.
// Either an original bug, or dead code.
if (R2_GLOBALS.getFlag(63)) {
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
} else {
_sceneMode = 10;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -10925,24 +11648,29 @@ void Scene1800::signal() {
break;
case 1808:
_sceneMode = 12;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_stripManager.start(553, this);
break;
case 1812:
_sceneMode = 13;
R2_GLOBALS._player.animate(ANIM_MODE_5, this);
break;
+ // Case 1813 has been added to fix Seeker missing animation in the original game
+ case 1813:
+ _sceneMode = 23;
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
case 1814:
// No break on purpose
case 1815:
- R2_GLOBALS._walkRegions.enableRegion(10);
- R2_GLOBALS._walkRegions.enableRegion(11);
+ R2_GLOBALS._walkRegions.disableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(11);
R2_GLOBALS._player.enableControl();
break;
case 1816:
// No break on purpose
case 1817:
- R2_GLOBALS._walkRegions.enableRegion(8);
+ R2_GLOBALS._walkRegions.disableRegion(8);
R2_GLOBALS._player.enableControl();
break;
default:
@@ -10959,18 +11687,11 @@ void Scene1800::saveCharacter(int characterIndex) {
}
/*--------------------------------------------------------------------------
- * Scene 1850 -
+ * Scene 1850 - Rim Lift Interior
*
*--------------------------------------------------------------------------*/
-Scene1850::Scene1850() {
- warning("STUBBED: Scene1850()");
-}
-
-void Scene1850::synchronize(Serializer &s) {
- warning("STUBBED: Scene1850::synchronize()");
-}
-bool Scene1850::Hotspot2::startAction(CursorType action, Event &event) {
+bool Scene1850::Button::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneHotspot::startAction(action, event);
@@ -10984,13 +11705,13 @@ bool Scene1850::Hotspot2::startAction(CursorType action, Event &event) {
else
scene->setAction(&scene->_sequenceManager1, scene, 1852, &R2_GLOBALS._player, NULL);
} else if (R2_GLOBALS.getFlag(30)) {
- scene->_field41E = 1;
+ scene->_seqNumber = 1;
scene->_sceneMode = 1860;
if (R2_GLOBALS.getFlag(32))
- scene->setAction(&scene->_sequenceManager1, scene, 1860, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1860, &R2_GLOBALS._player, &scene->_robot, NULL);
else
- scene->setAction(&scene->_sequenceManager1, scene, 1859, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1859, &R2_GLOBALS._player, &scene->_robot, NULL);
R2_GLOBALS.clearFlag(30);
} else {
@@ -11005,30 +11726,30 @@ bool Scene1850::Hotspot2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1850::Actor5::startAction(CursorType action, Event &event) {
+bool Scene1850::Robot::startAction(CursorType action, Event &event) {
Scene1850 *scene = (Scene1850 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if ((R2_GLOBALS._player._characterIndex != R2_SEEKER) || (R2_GLOBALS.getFlag(33)) || (R2_GLOBALS.getFlag(30)))
+ if ((R2_GLOBALS._player._characterIndex != R2_SEEKER) || R2_GLOBALS.getFlag(33) || R2_GLOBALS.getFlag(30))
return SceneActor::startAction(action, event);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1857;
if (R2_GLOBALS.getFlag(32))
- scene->setAction(&scene->_sequenceManager1, scene, 1858, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1858, &R2_GLOBALS._player, &scene->_robot, NULL);
else
- scene->setAction(&scene->_sequenceManager1, scene, 1857, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1857, &R2_GLOBALS._player, &scene->_robot, NULL);
R2_GLOBALS.setFlag(30);
return true;
break;
case CURSOR_LOOK:
if (R2_GLOBALS.getFlag(34))
- SceneItem::display(1850, 2, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1850, 2, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
else
- SceneItem::display(1850, 1, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1850, 1, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
break;
@@ -11038,7 +11759,7 @@ bool Scene1850::Actor5::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 30;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
scene->_stripManager.start(558, scene);
return true;
@@ -11048,18 +11769,20 @@ bool Scene1850::Actor5::startAction(CursorType action, Event &event) {
} else if (R2_GLOBALS.getFlag(30)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1875;
- scene->_actor2.postInit();
+ scene->_airbag.postInit();
if (R2_GLOBALS.getFlag(32))
- scene->setAction(&scene->_sequenceManager1, scene, 1876, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1876,
+ &R2_GLOBALS._player, &scene->_airbag, NULL);
else
- scene->setAction(&scene->_sequenceManager1, scene, 1875, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1875,
+ &R2_GLOBALS._player, &scene->_airbag, NULL);
return true;
} else if (R2_GLOBALS.getFlag(70)) {
R2_GLOBALS._player.disableControl();
- scene->_sceneMode = 30;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ scene->_sceneMode = 20;
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
scene->_stripManager.start(557, scene);
R2_GLOBALS.setFlag(69);
@@ -11075,7 +11798,8 @@ bool Scene1850::Actor5::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1878;
- scene->setAction(&scene->_sequenceManager1, scene, 1878, &R2_GLOBALS._player, &scene->_actor5, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1878, &R2_GLOBALS._player,
+ &scene->_robot, &scene->_airbag, NULL);
}
return true;
@@ -11086,20 +11810,20 @@ bool Scene1850::Actor5::startAction(CursorType action, Event &event) {
}
}
-bool Scene1850::Actor6::startAction(CursorType action, Event &event) {
+bool Scene1850::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneHotspot::startAction(action, event);
- Scene1850 *scene = (Scene1850 *)R2_GLOBALS._sceneManager._scene;
-
if (R2_GLOBALS.getFlag(32)) {
- SceneItem::display(3240, 4, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(3240, 4, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
return true;
}
+ Scene1850 *scene = (Scene1850 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- if (scene->_field412 == 1851)
- R2_GLOBALS._player._effect = 1;
+ if (scene->_sceneMode == 1851)
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
if (_position.x >= 160)
R2_GLOBALS.setFlag(29);
@@ -11108,30 +11832,30 @@ bool Scene1850::Actor6::startAction(CursorType action, Event &event) {
if ((R2_GLOBALS._player._characterIndex == R2_SEEKER) && (R2_GLOBALS.getFlag(30))) {
if (_position.x >= 160)
- scene->_field41E = 3;
+ scene->_seqNumber = 3;
else
- scene->_field41E = 2;
+ scene->_seqNumber = 2;
scene->_sceneMode = 1860;
if (R2_GLOBALS.getFlag(32)) {
- scene->setAction(&scene->_sequenceManager1, scene, 1860, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1860, &R2_GLOBALS._player, &scene->_robot, NULL);
} else {
- scene->setAction(&scene->_sequenceManager1, scene, 1859, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1859, &R2_GLOBALS._player, &scene->_robot, NULL);
}
} else {
scene->_sceneMode = 11;
if (_position.x >= 160) {
- scene->setAction(&scene->_sequenceManager1, scene, 1866, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1866, &R2_GLOBALS._player, &scene->_rightDoor, NULL);
} else {
- scene->setAction(&scene->_sequenceManager1, scene, 1865, &R2_GLOBALS._player, &scene->_actor6, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1865, &R2_GLOBALS._player, &scene->_leftDoor, NULL);
}
}
return true;
}
-bool Scene1850::Actor8::startAction(CursorType action, Event &event) {
+bool Scene1850::DisplayScreen::startAction(CursorType action, Event &event) {
if ((action != CURSOR_USE) || (_position.y != 120))
return SceneHotspot::startAction(action, event);
@@ -11149,6 +11873,28 @@ bool Scene1850::Actor8::startAction(CursorType action, Event &event) {
return true;
}
+/*------------------------------------------------------------------------*/
+
+Scene1850::Scene1850() {
+ _sceneMode = 0;
+ _shadeCountdown = 0;
+ _shadeDirection = 0;
+ _shadeChanging = false;
+ _seqNumber = 0;
+}
+
+void Scene1850::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_sceneMode);
+ s.syncAsSint16LE(_shadeCountdown);
+ s.syncAsSint16LE(_shadeDirection);
+ s.syncAsSint16LE(_shadeChanging);
+ s.syncAsSint16LE(_seqNumber);
+ s.syncAsSint16LE(_playerDest.x);
+ s.syncAsSint16LE(_playerDest.y);
+}
+
void Scene1850::postInit(SceneObjectList *OwnerList) {
loadScene(1850);
@@ -11158,10 +11904,10 @@ void Scene1850::postInit(SceneObjectList *OwnerList) {
_palette1.loadPalette(0);
if (R2_GLOBALS.getFlag(31)) {
- _field412 = 1850;
+ _sceneMode = 1850;
g_globals->_scenePalette.loadPalette(1850);
} else {
- _field412 = 1851;
+ _sceneMode = 1851;
g_globals->_scenePalette.loadPalette(1851);
}
@@ -11173,173 +11919,173 @@ void Scene1850::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
- _field418 = 0;
- _field41E = 0;
- _field41A = Common::Point(0, 0);
+ _shadeChanging = false;
+ _seqNumber = 0;
+ _playerDest = Common::Point(0, 0);
- R2_GLOBALS._player._characterScene[1] = 1850;
- R2_GLOBALS._player._characterScene[2] = 1850;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1850;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1850;
- _item2.setDetails(Rect(101, 56, 111, 63), 1850, 19, -1, -1, 1, NULL);
+ _button.setDetails(Rect(101, 56, 111, 63), 1850, 19, -1, -1, 1, NULL);
- _actor6.postInit();
- _actor6.setup(1850, 3, 1);
- _actor6.setPosition(Common::Point(66, 102));
- _actor6.setDetails(1850, 22, -1, -1, 1, (SceneItem *) NULL);
+ _leftDoor.postInit();
+ _leftDoor.setup(1850, 3, 1);
+ _leftDoor.setPosition(Common::Point(66, 102));
+ _leftDoor.setDetails(1850, 22, -1, -1, 1, (SceneItem *) NULL);
- _actor7.postInit();
- _actor7.setup(1850, 2, 1);
- _actor7.setPosition(Common::Point(253, 102));
- _actor7.setDetails(1850, 22, -1, -1, 1, (SceneItem *) NULL);
+ _rightDoor.postInit();
+ _rightDoor.setup(1850, 2, 1);
+ _rightDoor.setPosition(Common::Point(253, 102));
+ _rightDoor.setDetails(1850, 22, -1, -1, 1, (SceneItem *) NULL);
- R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(1);
- _actor5.postInit();
+ _robot.postInit();
if (R2_GLOBALS.getFlag(34)) {
- R2_GLOBALS._walkRegions.enableRegion(2);
- _actor5.setup(1851, 4, 3);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ _robot.setup(1851, 4, 3);
} else if (R2_GLOBALS.getFlag(30)) {
- _actor5.setup(1851, 2, 2);
+ _robot.setup(1851, 2, 2);
} else {
- R2_GLOBALS._walkRegions.enableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(5);
if (R2_GLOBALS.getFlag(33)) {
- R2_GLOBALS._walkRegions.enableRegion(2);
- _actor5.setup(1851, 1, 3);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ _robot.setup(1851, 1, 3);
} else {
- _actor5.setup(1851, 2, 1);
+ _robot.setup(1851, 2, 1);
}
}
- _actor5.setPosition(Common::Point(219, 130));
- _actor5.fixPriority(114);
- _actor5.setDetails(1850, -1, -1, -1, 1, (SceneItem *) NULL);
+ _robot.setPosition(Common::Point(219, 130));
+ _robot.fixPriority(114);
+ _robot.setDetails(1850, -1, -1, -1, 1, (SceneItem *) NULL);
R2_GLOBALS._player.postInit();
- _actor1.postInit();
+ _companion.postInit();
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL);
} else {
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL);
}
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1850) {
- R2_GLOBALS._player._effect = 6;
- _actor1._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
+ _companion._effect = EFFECT_SHADED2;
if (R2_GLOBALS.getFlag(31)) {
R2_GLOBALS._player._shade = 0;
- _actor1._shade = 0;
+ _companion._shade = 0;
} else {
R2_GLOBALS._player._shade = 6;
- _actor1._shade = 6;
+ _companion._shade = 6;
}
if (R2_INVENTORY.getObjectScene(R2_AIRBAG) == 1850) {
- _actor2.postInit();
+ _airbag.postInit();
if (R2_GLOBALS.getFlag(34)) {
- _actor2.setup(1851, 4, 2);
- _actor2.fixPriority(114);
+ _airbag.setup(1851, 4, 2);
+ _airbag.fixPriority(114);
} else {
- _actor2.setup(1851, 4, 1);
+ _airbag.setup(1851, 4, 1);
}
- _actor2.setPosition(Common::Point(179, 113));
+ _airbag.setPosition(Common::Point(179, 113));
- if ((_actor5._strip == 1) && (_actor5._frame == 3)){
- _actor2.hide();
+ if ((_robot._strip == 1) && (_robot._frame == 3)){
+ _airbag.hide();
}
- _actor2.setDetails(1850, 6, -1, -1, 1, (SceneItem *) NULL);
+ _airbag.setDetails(1850, 6, -1, -1, 1, (SceneItem *) NULL);
}
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(32)) {
R2_GLOBALS._player.setVisage(1511);
- _actor1.setVisage(1508);
+ _companion.setVisage(1508);
- _actor3.postInit();
- _actor3.setup(1853, 3, 1);
- _actor3.setPosition(Common::Point(122, 113));
- _actor3.fixPriority(114);
- _actor3._effect = 6;
+ _screen.postInit();
+ _screen.setup(1853, 3, 1);
+ _screen.setPosition(Common::Point(122, 113));
+ _screen.fixPriority(114);
+ _screen._effect = EFFECT_SHADED2;
// Totally useless test
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor3.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
+ _screen.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
} else {
// And the associated dead code
- _actor3.setDetails(1850, 30, -1, -1, 2, (SceneItem *) NULL);
+ _screen.setDetails(1850, 30, -1, -1, 2, (SceneItem *) NULL);
}
- _actor4.postInit();
- _actor4.setup(1853, 3, 2);
- _actor4.setPosition(Common::Point(139, 111));
- _actor4.fixPriority(114);
- _actor4._effect = 6;
+ _helmet.postInit();
+ _helmet.setup(1853, 3, 2);
+ _helmet.setPosition(Common::Point(139, 111));
+ _helmet.fixPriority(114);
+ _helmet._effect = EFFECT_SHADED2;
// Still totally useless test
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor4.setDetails(1850, 29, -1, -1, 2, (SceneItem *) NULL);
+ _helmet.setDetails(1850, 29, -1, -1, 2, (SceneItem *) NULL);
} else {
// Another piece of dead code
- _actor4.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
+ _helmet.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
}
if (R2_GLOBALS.getFlag(31)) {
- _actor3._shade = 0;
- _actor4._shade = 0;
+ _screen._shade = 0;
+ _helmet._shade = 0;
} else {
- _actor3._shade = 6;
- _actor4._shade = 6;
+ _screen._shade = 6;
+ _helmet._shade = 6;
}
} else {
R2_GLOBALS._player.setVisage(1500);
- _actor1.setVisage(1505);
+ _companion.setVisage(1505);
}
} else { // Not Quinn
if (R2_GLOBALS.getFlag(32)) {
R2_GLOBALS._player.setVisage(1508);
- _actor1.setVisage(1511);
+ _companion.setVisage(1511);
- _actor3.postInit();
- _actor3.setup(1853, 3, 1);
- _actor3.setPosition(Common::Point(122, 113));
- _actor3.fixPriority(114);
- _actor3._effect = 6;
+ _screen.postInit();
+ _screen.setup(1853, 3, 1);
+ _screen.setPosition(Common::Point(122, 113));
+ _screen.fixPriority(114);
+ _screen._effect = EFFECT_SHADED2;
// Totally useless test
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
// Dead code
- _actor3.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
+ _screen.setDetails(1850, 28, -1, -1, 2, (SceneItem *) NULL);
} else {
- _actor3.setDetails(1850, 30, -1, -1, 2, (SceneItem *) NULL);
+ _screen.setDetails(1850, 30, -1, -1, 2, (SceneItem *) NULL);
}
- _actor4.postInit();
- _actor4.setup(1853, 3, 2);
- _actor4.setPosition(Common::Point(139, 111));
- _actor4.fixPriority(114);
- _actor4._effect = 6;
+ _helmet.postInit();
+ _helmet.setup(1853, 3, 2);
+ _helmet.setPosition(Common::Point(139, 111));
+ _helmet.fixPriority(114);
+ _helmet._effect = EFFECT_SHADED2;
// Again, useless test
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
// and dead code
- _actor4.setDetails(1850, 29, -1, -1, 1, (SceneItem *) NULL);
+ _helmet.setDetails(1850, 29, -1, -1, 1, (SceneItem *) NULL);
} else {
- _actor4.setDetails(1850, 28, -1, -1, 1, (SceneItem *) NULL);
+ _helmet.setDetails(1850, 28, -1, -1, 1, (SceneItem *) NULL);
}
if (R2_GLOBALS.getFlag(31)) {
- _actor3._shade = 0;
- _actor4._shade = 0;
+ _screen._shade = 0;
+ _helmet._shade = 0;
} else {
- _actor3._shade = 6;
- _actor4._shade = 6;
+ _screen._shade = 6;
+ _helmet._shade = 6;
}
} else {
R2_GLOBALS._player.setVisage(1505);
- _actor1.setVisage(1500);
+ _companion.setVisage(1500);
}
}
@@ -11347,25 +12093,25 @@ void Scene1850::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS._player.setPosition(Common::Point(80, 114));
- _actor1.animate(ANIM_MODE_1, NULL);
- _actor1.setObjectWrapper(new SceneObjectWrapper());
- _actor1.setStrip(3);
- _actor1.setPosition(Common::Point(180, 96));
+ _companion.animate(ANIM_MODE_1, NULL);
+ _companion.setObjectWrapper(new SceneObjectWrapper());
+ _companion.setStrip(3);
+ _companion.setPosition(Common::Point(180, 96));
if (R2_GLOBALS.getFlag(30)) {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor1.animate(ANIM_MODE_NONE, NULL);
- _actor1.setObjectWrapper(NULL);
+ _companion.animate(ANIM_MODE_NONE, NULL);
+ _companion.setObjectWrapper(NULL);
if (R2_GLOBALS.getFlag(32)) {
- _actor1.setup(1854, 1, 3);
+ _companion.setup(1854, 1, 3);
} else {
- _actor1.setup(1854, 2, 3);
+ _companion.setup(1854, 2, 3);
}
- _actor1.setPosition(Common::Point(164, 106));
+ _companion.setPosition(Common::Point(164, 106));
} else {
- _actor1.animate(ANIM_MODE_NONE, NULL);
- _actor1.setObjectWrapper(NULL);
+ _companion.animate(ANIM_MODE_NONE, NULL);
+ _companion.setObjectWrapper(NULL);
if (R2_GLOBALS.getFlag(32)) {
R2_GLOBALS._player.setup(1854, 1, 3);
} else {
@@ -11378,58 +12124,58 @@ void Scene1850::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.enableControl();
} else { // R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 1850
- R2_GLOBALS._player._effect = 1;
- _actor1._effect = 1;
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
+ _companion._effect = EFFECT_SHADED;
R2_GLOBALS._player.disableControl();
_sceneMode = 10;
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(29)) {
- setAction(&_sequenceManager1, this, 1863, &R2_GLOBALS._player, &_actor1, &_actor7, NULL);
+ setAction(&_sequenceManager1, this, 1863, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
} else {
- setAction(&_sequenceManager1, this, 1861, &R2_GLOBALS._player, &_actor1, &_actor6, NULL);
+ setAction(&_sequenceManager1, this, 1861, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
}
} else {
if (R2_GLOBALS.getFlag(29)) {
- setAction(&_sequenceManager1, this, 1864, &R2_GLOBALS._player, &_actor1, &_actor7, NULL);
+ setAction(&_sequenceManager1, this, 1864, &R2_GLOBALS._player, &_companion, &_rightDoor, NULL);
} else {
- setAction(&_sequenceManager1, this, 1862, &R2_GLOBALS._player, &_actor1, &_actor6, NULL);
+ setAction(&_sequenceManager1, this, 1862, &R2_GLOBALS._player, &_companion, &_leftDoor, NULL);
}
}
}
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- _actor1._moveDiff = Common::Point(5, 3);
+ _companion._moveDiff = Common::Point(5, 3);
} else {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- _actor1._moveDiff = Common::Point(3, 2);
+ _companion._moveDiff = Common::Point(3, 2);
}
- _actor8.postInit();
- _actor8.setup(1850, 1, 1);
+ _displayScreen.postInit();
+ _displayScreen.setup(1850, 1, 1);
if (R2_GLOBALS.getFlag(62)) {
- _actor8.setPosition(Common::Point(159, 120));
+ _displayScreen.setPosition(Common::Point(159, 120));
} else {
- _actor8.setPosition(Common::Point(159, 184));
+ _displayScreen.setPosition(Common::Point(159, 184));
}
- _actor8.fixPriority(113);
+ _displayScreen.fixPriority(113);
if (R2_GLOBALS.getFlag(34)) {
- _actor8.setDetails(1850, 25, -1, -1, 4, &_actor5);
+ _displayScreen.setDetails(1850, 25, -1, -1, 4, &_robot);
} else {
- _actor8.setDetails(1850, 25, -1, -1, 2, (SceneItem *) NULL);
+ _displayScreen.setDetails(1850, 25, -1, -1, 2, (SceneItem *) NULL);
}
if (!R2_GLOBALS.getFlag(62)) {
- _actor8.hide();
+ _displayScreen.hide();
}
- _item1.setDetails(Rect(0, 0, 320, 200), 1850, 16, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 1850, 16, -1, -1, 1, NULL);
- R2_GLOBALS._player._oldCharacterScene[1] = 1850;
- R2_GLOBALS._player._oldCharacterScene[2] = 1850;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1850;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1850;
}
void Scene1850::remove() {
@@ -11445,13 +12191,13 @@ void Scene1850::remove() {
void Scene1850::signal() {
switch (_sceneMode) {
case 10:
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
R2_GLOBALS._player._shade = 6;
- _actor1._effect = 6;
- _actor1._shade = 6;
+ _companion._effect = EFFECT_SHADED2;
+ _companion._shade = 6;
- R2_GLOBALS._walkRegions.enableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(5);
if (R2_GLOBALS.getFlag(68)) {
R2_GLOBALS._player.enableControl();
@@ -11471,7 +12217,8 @@ void Scene1850::signal() {
break;
case 16:
_sceneMode = 1870;
- setAction(&_sequenceManager1, this, 1870, &R2_GLOBALS._player, &_actor1, &_actor3, &_actor4, NULL);
+ setAction(&_sequenceManager1, this, 1870, &R2_GLOBALS._player, &_companion,
+ &_screen, &_helmet, NULL);
break;
case 20:
R2_GLOBALS._player.enableControl(CURSOR_TALK);
@@ -11479,7 +12226,8 @@ void Scene1850::signal() {
case 21:
R2_GLOBALS._player.disableControl();
_sceneMode = 1877;
- setAction(&_sequenceManager1, this, 1877, &R2_GLOBALS._player, &_actor1, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1877, &R2_GLOBALS._player, &_companion,
+ &_robot, NULL);
break;
case 30:
R2_GLOBALS._player.disableControl();
@@ -11489,40 +12237,41 @@ void Scene1850::signal() {
case 1852:
// No break on purpose:
case 1853:
- if (_field412 == 1851) {
+ if (_sceneMode == 1851) { // At this point, SceneMode can't be equal to 1851 => dead code
R2_GLOBALS.setFlag(31);
_palette1.loadPalette(1850);
- _field412 = 1850;
+ _sceneMode = 1850;
} else {
R2_GLOBALS.clearFlag(31);
_palette1.loadPalette(1851);
- _field412 = 1851;
+ _sceneMode = 1851;
}
- _field418 = 1;
+ _shadeChanging = true;
if (R2_GLOBALS.getFlag(30)) {
- _actor8.setAction(&_sequenceManager2, NULL, 1867, &_actor8, NULL);
+ _displayScreen.setAction(&_sequenceManager2, NULL, 1867, &_displayScreen, NULL);
} else if (R2_GLOBALS.getFlag(34)) {
if (R2_GLOBALS.getFlag(62)) {
R2_GLOBALS.clearFlag(62);
- _actor8.setAction(&_sequenceManager2, this, 1851, &_actor8, NULL);
+ _displayScreen.setAction(&_sequenceManager2, this, 1851, &_displayScreen, NULL);
} else {
R2_GLOBALS.setFlag(62);
- _actor8.setAction(&_sequenceManager2, this, 1850, &_actor8, NULL);
+ _displayScreen.setAction(&_sequenceManager2, this, 1850, &_displayScreen, NULL);
}
} else if (R2_GLOBALS.getFlag(33)) {
R2_GLOBALS.setFlag(62);
R2_GLOBALS.setFlag(34);
- R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(2);
- _actor2.postInit();
- _actor2.setDetails(1850, 6, -1, -1, 5, &_actor5);
+ _airbag.postInit();
+ _airbag.setDetails(1850, 6, -1, -1, 5, &_robot);
_sceneMode = 1879;
- _actor8.setAction(&_sequenceManager2, this, 1879, &_actor5, &_actor8, &_actor2, NULL);
+ _displayScreen.setAction(&_sequenceManager2, this, 1879, &_robot,
+ &_displayScreen, &_airbag, NULL);
} else {
- _actor8.setAction(&_sequenceManager2, NULL, 1867, &_actor8, NULL);
+ _displayScreen.setAction(&_sequenceManager2, NULL, 1867, &_displayScreen, NULL);
}
if (R2_GLOBALS.getFlag(34))
@@ -11530,12 +12279,12 @@ void Scene1850::signal() {
else
R2_GLOBALS._scenePalette.addFader(_palette1._palette, 256, 5, this);
- if (_field412 == 1851)
- _field416 = -20;
+ if (_sceneMode == 1851)
+ _shadeDirection = -20;
else
- _field416 = 20;
+ _shadeDirection = 20;
- _field414 = 20;
+ _shadeCountdown = 20;
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (_sceneMode == 1879)
@@ -11571,7 +12320,7 @@ void Scene1850::signal() {
case 1858:
R2_GLOBALS._player.disableControl();
_sceneMode = 1859;
- setAction(&_sequenceManager1, this, 1859, &R2_GLOBALS._player, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1859, &R2_GLOBALS._player, &_robot, NULL);
R2_GLOBALS.clearFlag(30);
break;
case 1859:
@@ -11581,16 +12330,16 @@ void Scene1850::signal() {
_stripManager.start(575, this);
break;
case 1860:
- if (_field41A.x != 0) {
+ if (_playerDest.x != 0) {
R2_GLOBALS._player.enableControl();
PlayerMover *mover = new PlayerMover();
- R2_GLOBALS._player.addMover(mover, &_field41A, this);
+ R2_GLOBALS._player.addMover(mover, &_playerDest, this);
- _field41A = Common::Point(0, 0);
+ _playerDest = Common::Point(0, 0);
}
- switch (_field41E) {
+ switch (_seqNumber) {
case 1:
_sceneMode = 1853;
if (R2_GLOBALS.getFlag(32)) {
@@ -11601,24 +12350,23 @@ void Scene1850::signal() {
break;
case 2:
_sceneMode = 11;
- setAction(&_sequenceManager1, this, 1865, &R2_GLOBALS._player, &_actor6, NULL);
+ setAction(&_sequenceManager1, this, 1865, &R2_GLOBALS._player, &_leftDoor, NULL);
break;
case 3:
- warning("_field41E == 3");
_sceneMode = 11;
- setAction(&_sequenceManager1, this, 1866, &R2_GLOBALS._player, &_actor7, NULL);
+ setAction(&_sequenceManager1, this, 1866, &R2_GLOBALS._player, &_rightDoor, NULL);
break;
default:
break;
}
- _field41E = 0;
+ _seqNumber = 0;
break;
case 1870:
- R2_GLOBALS._walkRegions.enableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(5);
R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 1);
R2_GLOBALS.setFlag(32);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 1875:
R2_INVENTORY.setObjectScene(R2_AIRBAG, 1850);
@@ -11627,41 +12375,41 @@ void Scene1850::signal() {
_stripManager.start(561, this);
break;
case 1877:
- _actor3.postInit();
- _actor3._effect = 6;
+ _screen.postInit();
+ _screen._effect = EFFECT_SHADED2;
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor3.setDetails(1850, 28, -1, -1, 2, (SceneItem *)NULL);
+ _screen.setDetails(1850, 28, -1, -1, 2, (SceneItem *)NULL);
} else {
- _actor3.setDetails(1850, 30, -1, -1, 2, (SceneItem *)NULL);
+ _screen.setDetails(1850, 30, -1, -1, 2, (SceneItem *)NULL);
}
- _actor4.postInit();
- _actor4._effect = 6;
+ _helmet.postInit();
+ _helmet._effect = EFFECT_SHADED2;
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor4.setDetails(1850, 29, -1, -1, 2, (SceneItem *)NULL);
+ _helmet.setDetails(1850, 29, -1, -1, 2, (SceneItem *)NULL);
} else {
- _actor4.setDetails(1850, 28, -1, -1, 2, (SceneItem *)NULL);
+ _helmet.setDetails(1850, 28, -1, -1, 2, (SceneItem *)NULL);
}
if (R2_GLOBALS.getFlag(31)) {
- _actor3._shade = 0;
- _actor4._shade = 0;
+ _screen._shade = 0;
+ _helmet._shade = 0;
} else {
- _actor3._shade = 6;
- _actor4._shade = 6;
+ _screen._shade = 6;
+ _helmet._shade = 6;
}
R2_GLOBALS.clearFlag(30);
_sceneMode = 15;
- setAction(&_sequenceManager1, this, 1869, &R2_GLOBALS._player, &_actor3, NULL);
- setAction(&_sequenceManager2, this, 1868, &_actor1, &_actor4, NULL);
+ setAction(&_sequenceManager1, this, 1869, &R2_GLOBALS._player, &_screen, NULL);
+ _companion.setAction(&_sequenceManager2, this, 1868, &_companion, &_helmet, NULL);
break;
case 1878:
R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 1850);
R2_GLOBALS.setFlag(33);
- R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(2);
R2_GLOBALS._player.enableControl();
break;
case 1879:
@@ -11681,17 +12429,17 @@ void Scene1850::signal() {
}
void Scene1850::process(Event &event) {
- if ( (event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_ARROW)
- && (R2_GLOBALS._player._characterIndex == R2_SEEKER) && (R2_GLOBALS.getFlag(30))) {
- _field41A = event.mousePos;
+ if ( (event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_WALK)
+ && (R2_GLOBALS._player._characterIndex == R2_SEEKER) && (R2_GLOBALS.getFlag(30))) {
+ _playerDest = event.mousePos;
R2_GLOBALS._player.disableControl();
_sceneMode = 1860;
if (R2_GLOBALS.getFlag(32)) {
- setAction(&_sequenceManager1, this, 1860, &R2_GLOBALS._player, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1860, &R2_GLOBALS._player, &_robot, NULL);
} else {
- setAction(&_sequenceManager1, this, 1859, &R2_GLOBALS._player, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 1859, &R2_GLOBALS._player, &_robot, NULL);
}
- R2_GLOBALS.clearFlag(32);
+ R2_GLOBALS.clearFlag(30);
event.handled = true;
}
@@ -11699,119 +12447,120 @@ void Scene1850::process(Event &event) {
}
void Scene1850::dispatch() {
- if (_field418 != 0) {
- _field414--;
- if (_field414 == 0)
- _field418 = 0;
+ if (_shadeChanging) {
+ _shadeCountdown--;
+ if (_shadeCountdown == 0)
+ _shadeChanging = false;
- if (_field416 >= 0) {
- R2_GLOBALS._player._shade = (_field414 * 6) / _field416;
+ if (_shadeDirection >= 0) {
+ R2_GLOBALS._player._shade = (_shadeCountdown * 6) / _shadeDirection;
} else {
- R2_GLOBALS._player._shade = ((_field414 * 6) / _field416) + 6;
+ R2_GLOBALS._player._shade = ((_shadeCountdown * 6) / _shadeDirection) + 6;
}
R2_GLOBALS._player._flags |= OBJFLAG_PANES;
- _actor1._shade = R2_GLOBALS._player._shade;
- _actor1._flags |= OBJFLAG_PANES;
+ _companion._shade = R2_GLOBALS._player._shade;
+ _companion._flags |= OBJFLAG_PANES;
- _actor3._shade = R2_GLOBALS._player._shade;
- _actor3._flags |= OBJFLAG_PANES;
+ _screen._shade = R2_GLOBALS._player._shade;
+ _screen._flags |= OBJFLAG_PANES;
- _actor4._shade = R2_GLOBALS._player._shade;
- _actor4._flags |= OBJFLAG_PANES;
+ _helmet._shade = R2_GLOBALS._player._shade;
+ _helmet._flags |= OBJFLAG_PANES;
}
if (R2_GLOBALS.getFlag(32)) {
- _actor3.setPosition(Common::Point(_actor8._position.x - 37, _actor8._position.y - 71));
- _actor4.setPosition(Common::Point(_actor8._position.x - 20, _actor8._position.y - 73));
+ _screen.setPosition(Common::Point(_displayScreen._position.x - 37, _displayScreen._position.y - 71));
+ _helmet.setPosition(Common::Point(_displayScreen._position.x - 20, _displayScreen._position.y - 73));
}
if (R2_INVENTORY.getObjectScene(R2_AIRBAG) == 1850) {
- _actor2.setPosition(Common::Point(_actor8._position.x + 20, _actor8._position.y - 71));
+ _airbag.setPosition(Common::Point(_displayScreen._position.x + 20, _displayScreen._position.y - 71));
}
Scene::dispatch();
}
/*--------------------------------------------------------------------------
- * Scene 1875 -
+ * Scene 1875 - Rim Lift Computer
*
*--------------------------------------------------------------------------*/
-Scene1875::Actor1875::Actor1875() {
- _fieldA4 = 0;
- _fieldA6 = 0;
+
+Scene1875::Button::Button() {
+ _buttonId = 0;
+ _buttonDown = false;
}
-void Scene1875::Actor1875::synchronize(Serializer &s) {
+void Scene1875::Button::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
+ s.syncAsSint16LE(_buttonId);
+ s.syncAsSint16LE(_buttonDown);
}
-void Scene1875::Actor1875::subB84AB() {
+void Scene1875::Button::doButtonPress() {
Scene1875 *scene = (Scene1875 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._sound1.play(227);
int newFrameNumber;
- switch (_fieldA4) {
+ switch (_buttonId) {
case 3:
- if ((scene->_actor1._frame == 1) && (scene->_actor4._strip == 2)) {
+ if ((scene->_map._frame == 1) && (scene->_button1._strip == 2)) {
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
scene->_sceneMode = 10;
- scene->_stripManager.start(576, this);
+ scene->_stripManager.start(576, scene);
} else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 1890;
- scene->_actor2.postInit();
- scene->setAction(&scene->_sequenceManager, scene, 1890, &scene->_actor2, NULL);
+ scene->_rimPosition.postInit();
+ scene->setAction(&scene->_sequenceManager, scene, 1890, &scene->_rimPosition, NULL);
}
break;
case 4:
- newFrameNumber = scene->_actor1._frame + 1;
+ newFrameNumber = scene->_map._frame + 1;
if (newFrameNumber > 6)
newFrameNumber = 1;
- scene->_actor1.setFrame(newFrameNumber);
+ scene->_map.setFrame(newFrameNumber);
break;
case 5:
- newFrameNumber = scene->_actor1._frame - 1;
+ newFrameNumber = scene->_map._frame - 1;
if (newFrameNumber < 1)
newFrameNumber = 6;
- scene->_actor1.setFrame(newFrameNumber);
+ scene->_map.setFrame(newFrameNumber);
break;
default:
break;
}
}
-void Scene1875::Actor1875::subB8271(int indx) {
+void Scene1875::Button::initButton(int buttonId) {
postInit();
- _fieldA4 = indx;
- _fieldA6 = 0;
+ _buttonId = buttonId;
+ _buttonDown = false;
setVisage(1855);
- if (_fieldA4 == 1)
+ if (_buttonId == 1)
setStrip(2);
else
setStrip(1);
- setFrame(_fieldA4);
- switch (_fieldA4 - 1) {
- case 0:
+ setFrame(_buttonId);
+ switch (_buttonId) {
+ case 1:
setPosition(Common::Point(20, 144));
break;
- case 1:
+ case 2:
setPosition(Common::Point(82, 144));
break;
- case 2:
+ case 3:
setPosition(Common::Point(136, 144));
break;
- case 3:
+ case 4:
setPosition(Common::Point(237, 144));
break;
- case 4:
+ case 5:
setPosition(Common::Point(299, 144));
break;
default:
@@ -11821,36 +12570,37 @@ void Scene1875::Actor1875::subB8271(int indx) {
setDetails(1875, 6, 1, -1, 2, (SceneItem *) NULL);
}
-void Scene1875::Actor1875::process(Event &event) {
- if ((R2_GLOBALS._player._uiEnabled) || (event.handled))
+void Scene1875::Button::process(Event &event) {
+ if (!R2_GLOBALS._player._uiEnabled || event.handled)
return;
Scene1875 *scene = (Scene1875 *)R2_GLOBALS._sceneManager._scene;
- if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == R2_STEPPING_DISKS) && (_bounds.contains(event.mousePos)) && (_fieldA6 == 0)) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE)
+ && (_bounds.contains(event.mousePos)) && !_buttonDown) {
setStrip(2);
- switch (_fieldA4) {
+ switch (_buttonId) {
case 1:
R2_GLOBALS._sound2.play(227);
- scene->_actor5.setStrip(1);
+ scene->_button2.setStrip(1);
break;
case 2:
R2_GLOBALS._sound2.play(227);
- scene->_actor4.setStrip(1);
+ scene->_button1.setStrip(1);
break;
default:
break;
}
- _fieldA6 = 1;
+ _buttonDown = true;
event.handled = true;
}
- if ((event.eventType == EVENT_BUTTON_UP) && (_fieldA6 != 0)) {
- if ((_fieldA4 == 3) || (_fieldA4 == 4) || (_fieldA4 == 5)) {
+ if ((event.eventType == EVENT_BUTTON_UP) && _buttonDown) {
+ if ((_buttonId == 3) || (_buttonId == 4) || (_buttonId == 5)) {
setStrip(1);
- subB84AB();
+ doButtonPress();
}
- _fieldA6 = 0;
+ _buttonDown = false;
event.handled = true;
}
}
@@ -11859,43 +12609,47 @@ void Scene1875::postInit(SceneObjectList *OwnerList) {
loadScene(1875);
SceneExt::postInit();
- R2_GLOBALS._player._characterScene[1] = 1875;
- R2_GLOBALS._player._characterScene[2] = 1875;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1875;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1875;
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
- _actor4.subB8271(1);
- _actor5.subB8271(2);
- _actor6.subB8271(3);
- _actor7.subB8271(4);
- _actor8.subB8271(5);
+ _button1.initButton(1);
+ _button2.initButton(2);
+ _button3.initButton(3);
+ _button4.initButton(4);
+ _button5.initButton(5);
- _actor1.postInit();
- _actor1.setup(1855, 4, 1);
- _actor1.setPosition(Common::Point(160, 116));
+ _map.postInit();
+ _map.setup(1855, 4, 1);
+ _map.setPosition(Common::Point(160, 116));
R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.hide();
+
if (R2_GLOBALS._sceneManager._previousScene == 1625) {
R2_GLOBALS._sound1.play(122);
R2_GLOBALS._player.disableControl();
_sceneMode = 11;
- _actor2.postInit();
- setAction(&_sequenceManager, this, 1892, &_actor2, NULL);
- } else if (R2_GLOBALS._sceneManager._previousScene == 3150) {
- R2_GLOBALS._sound1.play(116);
+ _rimPosition.postInit();
+ setAction(&_sequenceManager, this, 1892, &_rimPosition, NULL);
} else {
+ if (R2_GLOBALS._sceneManager._previousScene == 3150) {
+ R2_GLOBALS._sound1.play(116);
+ }
+
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
}
- _item2.setDetails(Rect(43, 14, 275, 122), 1875, 9, 1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 1875, 3, -1, -1, 1, NULL);
+ _screen.setDetails(Rect(43, 14, 275, 122), 1875, 9, 1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 1875, 3, -1, -1, 1, NULL);
- R2_GLOBALS._player._characterScene[1] = 1875;
- R2_GLOBALS._player._characterScene[2] = 1875;
- R2_GLOBALS._player._oldCharacterScene[1] = 1875;
- R2_GLOBALS._player._oldCharacterScene[2] = 1875;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 1875;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1875;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1875;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1875;
}
void Scene1875::signal() {
@@ -11903,8 +12657,8 @@ void Scene1875::signal() {
case 10:
R2_GLOBALS._player.disableControl();
_sceneMode = 1891;
- _actor2.postInit();
- setAction(&_sequenceManager, this, 1891, &_actor2, NULL);
+ _rimPosition.postInit();
+ setAction(&_sequenceManager, this, 1891, &_rimPosition, NULL);
break;
case 11:
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -11912,7 +12666,7 @@ void Scene1875::signal() {
_stripManager.start(577, this);
break;
case 1890:
- _actor2.remove();
+ _rimPosition.remove();
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
break;
@@ -11934,20 +12688,19 @@ void Scene1875::signal() {
void Scene1875::process(Event &event) {
Scene::process(event);
- _actor4.process(event);
- _actor5.process(event);
- _actor6.process(event);
- _actor7.process(event);
- _actor8.process(event);
+ _button1.process(event);
+ _button2.process(event);
+ _button3.process(event);
+ _button4.process(event);
+ _button5.process(event);
}
/*--------------------------------------------------------------------------
- * Scene 1900 -
+ * Scene 1900 - Spill Mountains Elevator Exit
*
*--------------------------------------------------------------------------*/
-bool Scene1900::Actor2::startAction(CursorType action, Event &event) {
- Scene1900 *scene = (Scene1900 *)R2_GLOBALS._sceneManager._scene;
+bool Scene1900::LiftDoor::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -11958,24 +12711,26 @@ bool Scene1900::Actor2::startAction(CursorType action, Event &event) {
return true;
}
+ Scene1900 *scene = (Scene1900 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.enableControl(CURSOR_USE);
if (_position.x >= 160) {
scene->_sceneMode = 1905;
- scene->setAction(&scene->_sequenceManager1, scene, 1905, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1905, &R2_GLOBALS._player, &scene->_rightDoor, NULL);
} else {
R2_GLOBALS.setFlag(29);
scene->_sceneMode = 1904;
- scene->setAction(&scene->_sequenceManager1, scene, 1904, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 1904, &R2_GLOBALS._player, &scene->_leftDoor, NULL);
}
return true;
}
-void Scene1900::Exit1::changeScene() {
+void Scene1900::WestExit::changeScene() {
Scene1900 *scene = (Scene1900 *)R2_GLOBALS._sceneManager._scene;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 10;
Common::Point pt(-10, 135);
@@ -11983,10 +12738,10 @@ void Scene1900::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1900::Exit2::changeScene() {
+void Scene1900::EastExit::changeScene() {
Scene1900 *scene = (Scene1900 *)R2_GLOBALS._sceneManager._scene;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 11;
Common::Point pt(330, 135);
@@ -12003,7 +12758,7 @@ void Scene1900::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene == -1) {
R2_GLOBALS._sceneManager._previousScene = 1925;
R2_GLOBALS._player._characterIndex = R2_SEEKER;
- R2_GLOBALS._player._oldCharacterScene[2] = 1925;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1925;
}
if (R2_GLOBALS._sceneManager._previousScene != 1875)
@@ -12013,11 +12768,11 @@ void Scene1900::postInit(SceneObjectList *OwnerList) {
_stripManager.setFontNumber(3);
_stripManager.addSpeaker(&_seekerSpeaker);
- _exit1.setDetails(Rect(0, 105, 14, 145), R2_COM_SCANNER, 2000);
- _exit1.setDest(Common::Point(14, 135));
+ _westExit.setDetails(Rect(0, 105, 14, 145), EXITCURSOR_W, 2000);
+ _westExit.setDest(Common::Point(14, 135));
- _exit2.setDetails(Rect(305, 105, 320, 145), R2_SPENT_POWER_CAPSULE, 2000);
- _exit2.setDest(Common::Point(315, 135));
+ _eastExit.setDetails(Rect(305, 105, 320, 145), EXITCURSOR_E, 2000);
+ _eastExit.setDest(Common::Point(315, 135));
R2_GLOBALS._player.postInit();
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
@@ -12034,83 +12789,85 @@ void Scene1900::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene != 1925)
R2_GLOBALS.clearFlag(29);
- _actor2.postInit();
- _actor2.setup(1901, 1, 1);
- _actor2.setPosition(Common::Point(95, 109));
- _actor2.fixPriority(100);
+ _leftDoor.postInit();
+ _leftDoor.setup(1901, 1, 1);
+ _leftDoor.setPosition(Common::Point(95, 109));
+ _leftDoor.fixPriority(100);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor2.setDetails(1900, 0, 1, 2, 1, (SceneItem *) NULL);
+ _leftDoor.setDetails(1900, 0, 1, 2, 1, (SceneItem *) NULL);
else
- _actor2.setDetails(1900, 0, 1, -1, 1, (SceneItem *) NULL);
+ _leftDoor.setDetails(1900, 0, 1, -1, 1, (SceneItem *) NULL);
- _actor3.postInit();
- _actor3.setup(1901, 2, 1);
- _actor3.setPosition(Common::Point(225, 109));
- _actor3.fixPriority(100);
+ _rightDoor.postInit();
+ _rightDoor.setup(1901, 2, 1);
+ _rightDoor.setPosition(Common::Point(225, 109));
+ _rightDoor.fixPriority(100);
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
- _actor3.setDetails(1900, 0, 1, 2, 1, (SceneItem *) NULL);
+ _rightDoor.setDetails(1900, 0, 1, 2, 1, (SceneItem *) NULL);
else
- _actor3.setDetails(1900, 0, 1, -1, 1, (SceneItem *) NULL);
+ _rightDoor.setDetails(1900, 0, 1, -1, 1, (SceneItem *) NULL);
if (R2_GLOBALS._sceneManager._previousScene != 1875) {
- _object1.postInit();
- _object1.setup(1945, 6, 1);
- _object1.setPosition(Common::Point(96, 109));
- _object1.fixPriority(80);
+ _leftDoorFrame.postInit();
+ _leftDoorFrame.setup(1945, 6, 1);
+ _leftDoorFrame.setPosition(Common::Point(96, 109));
+ _leftDoorFrame.fixPriority(80);
- _object2.postInit();
- _object2.setup(1945, 6, 2);
- _object2.setPosition(Common::Point(223, 109));
- _object2.fixPriority(80);
+ _rightDoorFrame.postInit();
+ _rightDoorFrame.setup(1945, 6, 2);
+ _rightDoorFrame.setPosition(Common::Point(223, 109));
+ _rightDoorFrame.fixPriority(80);
}
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1875) {
R2_GLOBALS._player._characterIndex = R2_QUINN;
- _actor1.postInit();
+ _companion.postInit();
_sceneMode = 20;
- R2_GLOBALS._player.setAction(&_sequenceManager1, NULL, 1901, &R2_GLOBALS._player, &_actor2, NULL);
- _actor1.setAction(&_sequenceManager2, this, 1900, &_actor1, &_actor3, NULL);
+ R2_GLOBALS._player.setAction(&_sequenceManager1, NULL, 1901, &R2_GLOBALS._player, &_leftDoor, NULL);
+ _companion.setAction(&_sequenceManager2, this, 1900, &_companion, &_rightDoor, NULL);
} else if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1925) {
if (R2_GLOBALS.getFlag(29)) {
R2_GLOBALS.clearFlag(29);
- _actor2.hide();
+ _leftDoor.hide();
R2_GLOBALS._player.setStrip(6);
R2_GLOBALS._player.setPosition(Common::Point(90, 106));
_sceneMode = 1906;
- setAction(&_sequenceManager1, this, 1906, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager1, this, 1906, &R2_GLOBALS._player, &_leftDoor, NULL);
} else {
- _actor3.hide();
+ _rightDoor.hide();
R2_GLOBALS._player.setStrip(5);
R2_GLOBALS._player.setPosition(Common::Point(230, 106));
_sceneMode = 1907;
- setAction(&_sequenceManager1, this, 1907, &R2_GLOBALS._player, &_actor3, NULL);
+ setAction(&_sequenceManager1, this, 1907, &R2_GLOBALS._player, &_rightDoor, NULL);
}
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- _actor1.setPosition(Common::Point(30, 110));
- R2_GLOBALS._walkRegions.enableRegion(1);
- _actor1.setup(2008, 3, 1);
- _actor1.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ _companion.setPosition(Common::Point(30, 110));
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ _companion.setup(2008, 3, 1);
+ _companion.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
}
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 1900;
- } else if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- _actor1.setPosition(Common::Point(30, 110));
- R2_GLOBALS._walkRegions.enableRegion(1);
- if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- _actor1.setup(20, 3, 1);
- _actor1.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
- } else {
- _actor1.setup(2008, 3, 1);
- _actor1.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
+ } else {
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ _companion.setPosition(Common::Point(30, 110));
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 3, 1);
+ _companion.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
+ } else {
+ _companion.setup(2008, 3, 1);
+ _companion.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
+ }
}
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- if (R2_GLOBALS._v56605[1] == 5) {
+ if (R2_GLOBALS._spillLocation[R2_QUINN] == 5) {
_sceneMode = 1902;
setAction(&_sequenceManager1, this, 1902, &R2_GLOBALS._player, NULL);
} else {
@@ -12118,7 +12875,7 @@ void Scene1900::postInit(SceneObjectList *OwnerList) {
setAction(&_sequenceManager1, this, 1903, &R2_GLOBALS._player, NULL);
}
} else {
- if (R2_GLOBALS._v56605[2] == 5) {
+ if (R2_GLOBALS._spillLocation[R2_SEEKER] == 5) {
_sceneMode = 1908;
setAction(&_sequenceManager1, this, 1908, &R2_GLOBALS._player, NULL);
} else {
@@ -12133,8 +12890,8 @@ void Scene1900::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 1900;
}
- _item2.setDetails(Rect(77, 2, 240, 103), 1900, 6, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 1900, 3, -1, -1, 1, NULL);
+ _elevator.setDetails(Rect(77, 2, 240, 103), 1900, 6, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 1900, 3, -1, -1, 1, NULL);
}
void Scene1900::remove() {
@@ -12145,16 +12902,16 @@ void Scene1900::remove() {
void Scene1900::signal() {
switch (_sceneMode) {
case 10:
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 5;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 5;
R2_GLOBALS._sceneManager.changeScene(2000);
break;
case 11:
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 6;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 6;
R2_GLOBALS._sceneManager.changeScene(2000);
break;
case 20:
++_sceneMode;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_stripManager.start(1300, this);
break;
case 21:
@@ -12167,20 +12924,20 @@ void Scene1900::signal() {
break;
case 22:
_sceneMode = 1910;
- _actor1.setAction(&_sequenceManager2, this, 1910, &_actor1, NULL);
+ _companion.setAction(&_sequenceManager2, this, 1910, &_companion, NULL);
break;
case 1904:
R2_GLOBALS._scene1925CurrLevel = -3;
// No break on purpose
case 1905:
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
R2_GLOBALS._sceneManager.changeScene(1925);
break;
case 1910:
- R2_INVENTORY.setObjectScene(22, 2535);
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._player._oldCharacterScene[1] = 1900;
- R2_GLOBALS._player._oldCharacterScene[2] = 1900;
+ R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 2535);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1900;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1900;
R2_GLOBALS._sceneManager.changeScene(2450);
break;
case 1906:
@@ -12193,11 +12950,12 @@ void Scene1900::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1925 -
+ * Scene 1925 - Spill Mountains Elevator Shaft
*
*--------------------------------------------------------------------------*/
+
Scene1925::Scene1925() {
- _field9B8 = 0;
+ _newSceneMode = 0;
for (int i = 0; i < 5; i++)
_levelResNum[i] = 0;
}
@@ -12205,20 +12963,20 @@ Scene1925::Scene1925() {
void Scene1925::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field9B8);
+ s.syncAsSint16LE(_newSceneMode);
for (int i = 0; i < 5; i++)
s.syncAsSint16LE(_levelResNum[i]);
}
-bool Scene1925::Hotspot2::startAction(CursorType action, Event &event) {
- Scene1925 *scene = (Scene1925 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1925::Button::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneHotspot::startAction(action, event);
if ((R2_GLOBALS._player._position.x == 110) && (R2_GLOBALS._player._position.y == 100))
return SceneHotspot::startAction(action, event);
+ Scene1925 *scene = (Scene1925 *)R2_GLOBALS._sceneManager._scene;
+
if ((R2_GLOBALS._player._position.x == 154) && (R2_GLOBALS._player._position.y == 20))
scene->_sceneMode = 1928;
else if ((R2_GLOBALS._player._position.x == 154) && (R2_GLOBALS._player._position.y == 200))
@@ -12226,12 +12984,13 @@ bool Scene1925::Hotspot2::startAction(CursorType action, Event &event) {
else
scene->_sceneMode = 1930;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player,
+ &scene->_door, NULL);
return true;
}
-bool Scene1925::Hotspot3::startAction(CursorType action, Event &event) {
+bool Scene1925::Ladder::startAction(CursorType action, Event &event) {
if ((!R2_GLOBALS.getFlag(29)) || (action != CURSOR_USE))
return SceneHotspot::startAction(action, event);
@@ -12241,9 +13000,10 @@ bool Scene1925::Hotspot3::startAction(CursorType action, Event &event) {
scene->_sceneMode = 0;
if ((R2_GLOBALS._player._position.x == 110) && (R2_GLOBALS._player._position.y == 100)) {
- scene->_exit3._enabled = false;
+ scene->_westExit._enabled = false;
scene->_sceneMode = 1925;
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode,
+ &R2_GLOBALS._player, &scene->_door, NULL);
return true;
}
@@ -12278,10 +13038,11 @@ void Scene1925::ExitUp::changeScene() {
scene->_sceneMode = 0;
if ((R2_GLOBALS._player._position.x == 110) && (R2_GLOBALS._player._position.y == 100)) {
- scene->_exit3._enabled = false;
- scene->_field9B8 = 1927;
+ scene->_westExit._enabled = false;
+ scene->_newSceneMode = 1927;
scene->_sceneMode = 1925;
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode,
+ &R2_GLOBALS._player, &scene->_door, NULL);
return;
}
@@ -12300,7 +13061,7 @@ void Scene1925::ExitUp::changeScene() {
}
}
-void Scene1925::Exit2::changeScene() {
+void Scene1925::ExitDown::changeScene() {
Scene1925 *scene = (Scene1925 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
@@ -12308,10 +13069,11 @@ void Scene1925::Exit2::changeScene() {
scene->_sceneMode = 0;
if ((R2_GLOBALS._player._position.x == 110) && (R2_GLOBALS._player._position.y == 100)) {
- scene->_exit3._enabled = false;
- scene->_field9B8 = 1926;
+ scene->_westExit._enabled = false;
+ scene->_newSceneMode = 1926;
scene->_sceneMode = 1925;
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode,
+ &R2_GLOBALS._player, &scene->_door, NULL);
return;
}
@@ -12329,20 +13091,20 @@ void Scene1925::Exit2::changeScene() {
scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
}
-void Scene1925::Exit3::changeScene() {
+void Scene1925::WestExit::changeScene() {
Scene1925 *scene = (Scene1925 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 1921;
scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
}
-void Scene1925::Exit4::changeScene() {
+void Scene1925::EastExit::changeScene() {
Scene1925 *scene = (Scene1925 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 1920;
scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
}
@@ -12368,18 +13130,18 @@ void Scene1925::changeLevel(bool upFlag) {
break;
case 3:
loadScene(_levelResNum[4]);
- _item2.setDetails(Rect(133, 68, 140, 77), 1925, 3, -1, 5, 2, NULL);
- _actor1.setDetails(1925, 0, 1, 2, 2, (SceneItem *) NULL);
- _actor1.show();
+ _button.setDetails(Rect(133, 68, 140, 77), 1925, 3, -1, 5, 2, NULL);
+ _door.setDetails(1925, 0, 1, 2, 2, (SceneItem *) NULL);
+ _door.show();
break;
case 512:
R2_GLOBALS._scene1925CurrLevel = 508;
// No break on purpose
default:
loadScene(_levelResNum[(R2_GLOBALS._scene1925CurrLevel % 4)]);
- R2_GLOBALS._sceneItems.remove(&_item2);
- R2_GLOBALS._sceneItems.remove(&_actor1);
- _actor1.hide();
+ R2_GLOBALS._sceneItems.remove(&_button);
+ R2_GLOBALS._sceneItems.remove(&_door);
+ _door.hide();
break;
}
@@ -12407,34 +13169,35 @@ void Scene1925::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(220);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._player._characterScene[2] = 1925;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1925;
R2_GLOBALS._player._characterIndex = R2_SEEKER;
+
switch (R2_GLOBALS._scene1925CurrLevel) {
case -2:
- _exit4.setDetails(Rect(203, 44, 247, 111), EXITCURSOR_E, 1925);
- _item3.setDetails(Rect(31, 3, 45, 167), 1925, 6, -1, 8, 1, NULL);
+ _eastExit.setDetails(Rect(203, 44, 247, 111), EXITCURSOR_E, 1925);
+ _ladder.setDetails(Rect(31, 3, 45, 167), 1925, 6, -1, 8, 1, NULL);
break;
case 3:
- _actor1.setDetails(1925, 0, 1, 2, 1, (SceneItem *) NULL);
- _item2.setDetails(Rect(133, 68, 140, 77), 1925, 3, -1, 5, 1, NULL);
+ _door.setDetails(1925, 0, 1, 2, 1, (SceneItem *) NULL);
+ _button.setDetails(Rect(133, 68, 140, 77), 1925, 3, -1, 5, 1, NULL);
// No break on purpose
case -3:
- _exit3.setDetails(Rect(83, 38, 128, 101), EXITCURSOR_W, 1925);
+ _westExit.setDetails(Rect(83, 38, 128, 101), EXITCURSOR_W, 1925);
// No break on purpose
default:
_exitUp.setDetails(Rect(128, 0, 186, 10), EXITCURSOR_N, 1925);
- _exit2.setDetails(Rect(128, 160, 190, 167), EXITCURSOR_S, 1925);
- _item3.setDetails(Rect(141, 11, 167, 159), 1925, 6, -1, -1, 1, NULL);
+ _exitDown.setDetails(Rect(128, 160, 190, 167), EXITCURSOR_S, 1925);
+ _ladder.setDetails(Rect(141, 11, 167, 159), 1925, 6, -1, -1, 1, NULL);
break;
}
- _actor1.postInit();
- _actor1.setup(1925, 5, 1);
- _actor1.setPosition(Common::Point(128, 35));
- _actor1.hide();
+ _door.postInit();
+ _door.setup(1925, 5, 1);
+ _door.setPosition(Common::Point(128, 35));
+ _door.hide();
if (R2_GLOBALS._scene1925CurrLevel == 3)
- _actor1.show();
+ _door.show();
R2_GLOBALS._player.enableControl(CURSOR_USE);
switch (R2_GLOBALS._scene1925CurrLevel) {
@@ -12444,7 +13207,7 @@ void Scene1925::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setPosition(Common::Point(224, 109));
break;
case -3:
- _actor1.hide();
+ _door.hide();
R2_GLOBALS._player.setup(20, 5, 1);
R2_GLOBALS._player.setPosition(Common::Point(110, 100));
break;
@@ -12459,14 +13222,14 @@ void Scene1925::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._player._canWalk = false;
- _field9B8 = 0;
+ _newSceneMode = 0;
R2_GLOBALS._sceneManager._previousScene = 1925;
- _item1.setDetails(Rect(27, 0, 292, 200), 1925, 9, -1, -1, 1, NULL);
+ _background.setDetails(Rect(27, 0, 292, 200), 1925, 9, -1, -1, 1, NULL);
}
void Scene1925::remove() {
R2_GLOBALS._sound1.fadeOut2(NULL);
- R2_GLOBALS._player._oldCharacterScene[2] = 1925;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1925;
SceneExt::remove();
}
@@ -12497,10 +13260,10 @@ void Scene1925::signal() {
changeLevel(true);
break;
case 1925:
- _exit3._enabled = false;
- if (_field9B8 != 0) {
- _sceneMode = _field9B8;
- _field9B8 = 0;
+ _westExit._enabled = false;
+ if (_newSceneMode != 0) {
+ _sceneMode = _newSceneMode;
+ _newSceneMode = 0;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
}
// No break on purpose
@@ -12513,24 +13276,25 @@ void Scene1925::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1945 -
+ * Scene 1945 - Spill Mountains Shaft Bottom
*
*--------------------------------------------------------------------------*/
+
Scene1945::Scene1945() {
- _fieldEAA = 0;
- _fieldEAC = 0;
- _fieldEAE = CURSOR_NONE;
+ _nextSceneMode1 = 0;
+ _nextSceneMode2 = 0;
+ _lampUsed = CURSOR_NONE;
}
void Scene1945::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_fieldEAA);
- s.syncAsSint16LE(_fieldEAC);
- s.syncAsSint16LE(_fieldEAE);
+ s.syncAsSint16LE(_nextSceneMode1);
+ s.syncAsSint16LE(_nextSceneMode2);
+ s.syncAsSint16LE(_lampUsed);
}
-bool Scene1945::Hotspot3::startAction(CursorType action, Event &event) {
+bool Scene1945::Ice::startAction(CursorType action, Event &event) {
Scene1945 *scene = (Scene1945 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -12541,10 +13305,10 @@ bool Scene1945::Hotspot3::startAction(CursorType action, Event &event) {
scene->_sceneMode = 1942;
else {
scene->_sceneMode = 1940;
- scene->_fieldEAA = 1942;
+ scene->_nextSceneMode1 = 1942;
}
// At this point the original check if _sceneMode != 0. Skipped.
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_gunpowder, NULL);
return true;
break;
case CURSOR_USE:
@@ -12559,9 +13323,9 @@ bool Scene1945::Hotspot3::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
if (event.mousePos.x > 130)
- scene->_item3.setDetails(1945, 3, -1, -1, 3, (SceneItem *) NULL);
+ scene->_ice.setDetails(1945, 3, -1, -1, 3, (SceneItem *) NULL);
else
- scene->_item3.setDetails(1945, 3, -1, 5, 3, (SceneItem *) NULL);
+ scene->_ice.setDetails(1945, 3, -1, 5, 3, (SceneItem *) NULL);
}
// No break on purpose
default:
@@ -12570,22 +13334,23 @@ bool Scene1945::Hotspot3::startAction(CursorType action, Event &event) {
}
}
-bool Scene1945::Hotspot4::startAction(CursorType action, Event &event) {
- Scene1945 *scene = (Scene1945 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene1945::Ladder::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneHotspot::startAction(action, event);
+ Scene1945 *scene = (Scene1945 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl(CURSOR_USE);
scene->_sceneMode = 0;
if ((R2_GLOBALS._player._position.x == 221) && (R2_GLOBALS._player._position.y == 142)) {
scene->_sceneMode = 1949;
- scene->_fieldEAA = 1947;
+ scene->_nextSceneMode1 = 1947;
} else if ( ((R2_GLOBALS._player._position.x == 197) && (R2_GLOBALS._player._position.y == 158))
|| ((R2_GLOBALS._player._position.x == 191) && (R2_GLOBALS._player._position.y == 142)) ) {
scene->_sceneMode = 1947;
- } else if ((R2_GLOBALS._player._position.x == 221) && (R2_GLOBALS._player._position.y == 142) && (event.mousePos.y >= 30)) {
+ } else if ((R2_GLOBALS._player._position.x == 154) && (R2_GLOBALS._player._position.y == 50)
+ && (event.mousePos.y >= 30)) {
scene->_sceneMode = 1940;
} else {
R2_GLOBALS._player.enableControl(CURSOR_USE);
@@ -12598,23 +13363,23 @@ bool Scene1945::Hotspot4::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1945::Actor3::startAction(CursorType action, Event &event) {
- if ((action == R2_ALCOHOL_LAMP_3) && (action == R2_ALCOHOL_LAMP_2)) {
+bool Scene1945::Gunpowder::startAction(CursorType action, Event &event) {
+ if ((action == R2_ALCOHOL_LAMP_3) || (action == R2_ALCOHOL_LAMP_2)) {
Scene1945 *scene = (Scene1945 *)R2_GLOBALS._sceneManager._scene;
- scene->_fieldEAE = action;
+ scene->_lampUsed = action;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 0;
if ((R2_GLOBALS._player._position.x == 191) && (R2_GLOBALS._player._position.y == 142)) {
scene->_sceneMode= 1947;
- scene->_fieldEAA = 1943;
+ scene->_nextSceneMode1 = 1943;
} else if ((R2_GLOBALS._player._position.x == 154) && (R2_GLOBALS._player._position.y == 50)) {
scene->_sceneMode = 1940;
- scene->_fieldEAA = 1943;
+ scene->_nextSceneMode1 = 1943;
} else {
scene->_sceneMode = 1949;
- scene->_fieldEAA = 1947;
- scene->_fieldEAC = 1943;
+ scene->_nextSceneMode1 = 1947;
+ scene->_nextSceneMode2 = 1943;
}
// At this point the original check if _sceneMode != 0. Skipped.
scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
@@ -12633,7 +13398,7 @@ void Scene1945::ExitUp::changeScene() {
if ((R2_GLOBALS._player._position.x == 221) && (R2_GLOBALS._player._position.y == 142)) {
scene->_sceneMode = 1949;
- scene->_fieldEAA = 1947;
+ scene->_nextSceneMode1 = 1947;
} else if ( ((R2_GLOBALS._player._position.x == 197) && (R2_GLOBALS._player._position.y == 158))
|| ((R2_GLOBALS._player._position.x == 191) && (R2_GLOBALS._player._position.y == 142)) ) {
scene->_sceneMode = 1947;
@@ -12647,7 +13412,7 @@ void Scene1945::ExitUp::changeScene() {
}
}
-void Scene1945::Exit2::changeScene() {
+void Scene1945::CorridorExit::changeScene() {
Scene1945 *scene = (Scene1945 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
@@ -12656,7 +13421,7 @@ void Scene1945::Exit2::changeScene() {
if ((R2_GLOBALS._player._position.x == 154) && (R2_GLOBALS._player._position.y == 50)) {
scene->_sceneMode = 1940;
- scene->_fieldEAA = 1945;
+ scene->_nextSceneMode1 = 1945;
} else if ( ((R2_GLOBALS._player._position.x == 197) && (R2_GLOBALS._player._position.y == 158))
|| ((R2_GLOBALS._player._position.x == 191) && (R2_GLOBALS._player._position.y == 142)) ) {
scene->_sceneMode = 1945;
@@ -12674,36 +13439,36 @@ void Scene1945::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- R2_GLOBALS._player._characterScene[2] = 1945;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 1945;
R2_GLOBALS._player._characterIndex = R2_SEEKER;
_exitUp.setDetails(Rect(128, 0, 186, 10), EXITCURSOR_N, 1945);
- _exit2.setDetails(Rect(238, 144, 274, 167), EXITCURSOR_E, 1945);
+ _corridorExit.setDetails(Rect(238, 144, 274, 167), EXITCURSOR_E, 1945);
- _item4.setDetails(Rect(141, 3, 167, 126), 1945, 9, -1, -1, 1, NULL);
+ _ladder.setDetails(Rect(141, 3, 167, 126), 1945, 9, -1, -1, 1, NULL);
if (!R2_GLOBALS.getFlag(43)) {
- _exit2._enabled = false;
- _actor3.postInit();
- _actor3.setup(1945, 4, 1);
- _actor3.setPosition(Common::Point(253, 169));
- _actor3.fixPriority(150);
+ _corridorExit._enabled = false;
+ _gunpowder.postInit();
+ _gunpowder.setup(1945, 4, 1);
+ _gunpowder.setPosition(Common::Point(253, 169));
+ _gunpowder.fixPriority(150);
if (R2_GLOBALS.getFlag(42))
- _actor3.setDetails(1945, 15, -1, -1, 1, (SceneItem *) NULL);
+ _gunpowder.setDetails(1945, 15, -1, -1, 1, (SceneItem *) NULL);
else
- _actor3.hide();
+ _gunpowder.hide();
- _actor1.postInit();
- _actor1.setup(1945, 8, 1);
- _actor1.setPosition(Common::Point(253, 169));
- _actor1.fixPriority(130);
+ _coveringIce.postInit();
+ _coveringIce.setup(1945, 8, 1);
+ _coveringIce.setPosition(Common::Point(253, 169));
+ _coveringIce.fixPriority(130);
- _actor2.postInit();
- _actor2.setup(1945, 3, 1);
- _actor2.hide();
+ _alcoholLamp.postInit();
+ _alcoholLamp.setup(1945, 3, 1);
+ _alcoholLamp.hide();
} else {
- _exit2._enabled = true;
+ _corridorExit._enabled = true;
}
switch (R2_GLOBALS._sceneManager._previousScene) {
@@ -12726,12 +13491,12 @@ void Scene1945::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._player._canWalk = false;
- _fieldEAA = 0;
- _fieldEAC = 0;
+ _nextSceneMode1 = 0;
+ _nextSceneMode2 = 0;
- _item3.setDetails(11, 1945, 3, -1, 5);
- _item1.setDetails(Rect(238, 144, 274, 167), 1945, 0, -1, 2, 1, NULL);
- _item2.setDetails(Rect(27, 3, 292, 167), 1945, 3, -1, -1, 1, NULL);
+ _ice.setDetails(11, 1945, 3, -1, 5);
+ _hole.setDetails(Rect(238, 144, 274, 167), 1945, 0, -1, 2, 1, NULL);
+ _ice2.setDetails(Rect(27, 3, 292, 167), 1945, 3, -1, -1, 1, NULL);
}
void Scene1945::remove() {
@@ -12742,9 +13507,9 @@ void Scene1945::remove() {
void Scene1945::signal() {
switch (_sceneMode) {
case 1940:
- if (_fieldEAA == 1943) {
- _sceneMode = _fieldEAA;
- setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor2, NULL);
+ if (_nextSceneMode1 == 1943) {
+ _sceneMode = _nextSceneMode1;
+ setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_alcoholLamp, NULL);
} else {
_sceneMode = 1946;
setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, NULL);
@@ -12752,27 +13517,27 @@ void Scene1945::signal() {
return;
break;
case 1941:
- if (_fieldEAA == 0) {
+ if (_nextSceneMode1 == 0) {
R2_GLOBALS._scene1925CurrLevel = 0;
R2_GLOBALS.setFlag(29);
R2_GLOBALS._sceneManager.changeScene(1925);
} else {
- _sceneMode = _fieldEAA;
- _fieldEAA = 0;
+ _sceneMode = _nextSceneMode1;
+ _nextSceneMode1 = 0;
setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, NULL);
}
return;
case 1942:
R2_INVENTORY.setObjectScene(R2_GUNPOWDER, 0);
- _actor3.setDetails(1945, 15, -1, -1, 2, (SceneItem *) NULL);
+ _gunpowder.setDetails(1945, 15, -1, -1, 2, (SceneItem *) NULL);
R2_GLOBALS.setFlag(42);
break;
case 1943:
R2_GLOBALS._sound1.fadeOut2(NULL);
- R2_INVENTORY.setObjectScene(_fieldEAE, 0);
+ R2_INVENTORY.setObjectScene(_lampUsed, 0);
_sceneMode = 1948;
- setAction(&_sequenceManager1, this, _sceneMode, &_actor3, &_actor2, &_actor1, NULL);
- setAction(&_sequenceManager2, NULL, 1941, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager1, this, _sceneMode, &_gunpowder, &_alcoholLamp, &_coveringIce, NULL);
+ R2_GLOBALS._player.setAction(&_sequenceManager2, NULL, 1941, &R2_GLOBALS._player, NULL);
return;
case 1944:
break;
@@ -12780,18 +13545,19 @@ void Scene1945::signal() {
R2_GLOBALS._sceneManager.changeScene(1950);
return;
case 1946:
- if (_fieldEAA == 1942) {
- _sceneMode = _fieldEAA;
- _fieldEAA = 0;
- setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor3, NULL);
+ if (_nextSceneMode1 == 1942) {
+ _sceneMode = _nextSceneMode1;
+ _nextSceneMode1 = 0;
+ setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_gunpowder, NULL);
return;
}
+ _sceneMode = 0;
break;
case 1947:
- if (_fieldEAA == 1943) {
- _sceneMode = _fieldEAA;
- _fieldEAA = 1948;
- setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor2, NULL);
+ if (_nextSceneMode1 == 1943) {
+ _sceneMode = _nextSceneMode1;
+ _nextSceneMode1 = 1948;
+ setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_alcoholLamp, NULL);
} else {
_sceneMode = 1941;
setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, NULL);
@@ -12799,20 +13565,20 @@ void Scene1945::signal() {
return;
case 1948:
R2_GLOBALS._sound1.play(220);
- _exit2._enabled = true;
- R2_GLOBALS._sceneItems.remove(&_actor3);
+ _corridorExit._enabled = true;
+ R2_GLOBALS._sceneItems.remove(&_gunpowder);
R2_GLOBALS.clearFlag(42);
- R2_GLOBALS.clearFlag(43);
- _fieldEAA = 1940;
+ R2_GLOBALS.setFlag(43);
+ _nextSceneMode1 = 1940;
// No break on purpose
case 1949:
- _sceneMode = _fieldEAA;
- if (_fieldEAC == 1943) {
- _fieldEAA = _fieldEAC;
- _fieldEAC = 0;
- setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor2, NULL);
+ _sceneMode = _nextSceneMode1;
+ if (_nextSceneMode2 == 1943) {
+ _nextSceneMode1 = _nextSceneMode2;
+ _nextSceneMode2 = 0;
+ setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_alcoholLamp, NULL);
} else {
- _fieldEAA = 0;
+ _nextSceneMode1 = 0;
setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, NULL);
}
return;
@@ -12825,115 +13591,91 @@ void Scene1945::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 1950 -
+ * Scene 1950 - Flup Tube Corridor Maze
*
*--------------------------------------------------------------------------*/
-Scene1950::Area1::Area1() {
- _field20 = 0;
- _fieldB65 = 0;
-}
-void Scene1950::Area1::synchronize(Serializer &s) {
- SceneArea::synchronize(s);
-
- s.syncAsByte(_field20);
- s.syncAsSint16LE(_fieldB65);
-}
-Scene1950::Scene1950() {
- _field412 = 0;
- _field414 = 0;
- _field416 = 0;
- _field418 = Common::Point(0, 0);
- _field41C = 0;
+Scene1950::KeypadWindow::KeypadWindow() {
+ _buttonIndex = 0;
}
-void Scene1950::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
+void Scene1950::KeypadWindow::synchronize(Serializer &s) {
+ SceneArea::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
- s.syncAsSint16LE(_field418.x);
- s.syncAsSint16LE(_field418.y);
- s.syncAsSint16LE(_field41C);
+ s.syncAsSint16LE(_buttonIndex);
}
-Scene1950::Area1::Actor10::Actor10() {
- _fieldA4 = 0;
- _fieldA6 = 0;
- _fieldA8 = 0;
+Scene1950::KeypadWindow::KeypadButton::KeypadButton() {
+ _buttonIndex = 0;
+ _pressed = false;
+ _toggled = false;
}
-void Scene1950::Area1::Actor10::synchronize(Serializer &s) {
+void Scene1950::KeypadWindow::KeypadButton::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
- s.syncAsSint16LE(_fieldA8);
+ s.syncAsSint16LE(_buttonIndex);
+ s.syncAsSint16LE(_pressed);
+ s.syncAsSint16LE(_toggled);
}
-void Scene1950::Area1::Actor10::init(int indx) {
-// Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+void Scene1950::KeypadWindow::KeypadButton::init(int indx) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- _fieldA4 = indx;
- _fieldA6 = 0;
- _fieldA8 = 0;
+ _buttonIndex = indx;
+ _pressed = false;
+ _toggled = false;
postInit();
setup(1971, 2, 1);
fixPriority(249);
- setPosition(Common::Point(((_fieldA4 / 4) * 22) + 127, ((_fieldA4 / 4) * 19) + 71));
- warning("FIXME: invalid call to scene->_sceneAreas.push_front(this);");
+ setPosition(Common::Point(((_buttonIndex % 4) * 22) + 127, ((_buttonIndex / 4) * 19) + 71));
+ scene->_sceneAreas.push_front(this);
}
-void Scene1950::Area1::Actor10::process(Event &event) {
- if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE) && (_bounds.contains(event.mousePos)) && (_fieldA6 == 0)) {
+void Scene1950::KeypadWindow::KeypadButton::process(Event &event) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE)
+ && (_bounds.contains(event.mousePos)) && !_pressed) {
R2_GLOBALS._sound2.play(227);
- if (_fieldA8 == 0) {
+ if (!_toggled) {
setFrame(2);
- _fieldA8 = 1;
+ _toggled = true;
} else {
setFrame(1);
- _fieldA8 = 0;
+ _toggled = false;
}
- _fieldA6 = 1;
+ _pressed = true;
event.handled = true;
}
- if ((event.eventType == EVENT_BUTTON_UP) && (_fieldA6 != 0)) {
- _fieldA6 = 0;
+ if ((event.eventType == EVENT_BUTTON_UP) && _pressed) {
+ _pressed = false;
event.handled = true;
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- scene->subBF4B4(_fieldA4);
+ scene->doButtonPress(_buttonIndex);
}
}
-bool Scene1950::Area1::Actor10::startAction(CursorType action, Event &event) {
+bool Scene1950::KeypadWindow::KeypadButton::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE)
return false;
return SceneActor::startAction(action, event);
}
-void Scene1950::Area1::remove() {
+void Scene1950::KeypadWindow::remove() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- for (_fieldB65 = 0; _fieldB65 < 16; ++_fieldB65) {
- warning("Unexpected _sceneAreas.remove() call");
- // R2_GLOBALS._sceneAreas.remove(&_arrActor1[_fieldB65]);
- _arrActor1[_fieldB65].remove();
+ for (_buttonIndex = 0; _buttonIndex < 16; ++_buttonIndex) {
+ scene->_sceneAreas.remove(&_buttons[_buttonIndex]);
+ _buttons[_buttonIndex].remove();
}
- // sub201EA
- R2_GLOBALS._sceneItems.remove((SceneItem *)this);
- _areaActor.remove();
- SceneArea::remove();
- R2_GLOBALS._insetUp--;
- //
+ ModalWindow::remove();
if (!R2_GLOBALS.getFlag(37))
R2_GLOBALS._sound2.play(278);
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->_exit3._enabled = true;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ scene->_eastExit._enabled = true;
if (!R2_GLOBALS.getFlag(37)) {
if (R2_GLOBALS.getFlag(36)) {
@@ -12946,65 +13688,31 @@ void Scene1950::Area1::remove() {
}
}
-void Scene1950::Area1::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
- if (_field20 != R2_GLOBALS._insetUp)
- return;
-
- CursorType cursor = R2_GLOBALS._events.getCursor();
-
- if (_areaActor._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 Scene1950::Area1::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
+void Scene1950::KeypadWindow::setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
if (R2_GLOBALS._player._mover)
R2_GLOBALS._player.addMover(NULL);
R2_GLOBALS._player._canWalk = false;
- // UnkArea1200::proc12();
- _areaActor.postInit();
- _areaActor.setup(visage, stripFrameNum, frameNum);
- _areaActor.setPosition(Common::Point(posX, posY));
- _areaActor.fixPriority(250);
- _cursorNum = CURSOR_INVALID;
- scene->_sceneAreas.push_front(this);
- ++R2_GLOBALS._insetUp;
- _field20 = R2_GLOBALS._insetUp;
- //
+ ModalWindow::setup2(visage, stripFrameNum, frameNum, posX, posY);
- _areaActor.fixPriority(248);
- scene->_exit3._enabled = false;
- proc13(1950, 27, 28, 27);
+ _object1.fixPriority(248);
+ scene->_eastExit._enabled = false;
+ setup3(1950, 27, 28, 27);
- for (_fieldB65 = 0; _fieldB65 < 16; _fieldB65++)
- _arrActor1[_fieldB65].init(_fieldB65);
+ for (_buttonIndex = 0; _buttonIndex < 16; _buttonIndex++)
+ _buttons[_buttonIndex].init(_buttonIndex);
}
-void Scene1950::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13()
+void Scene1950::KeypadWindow::setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
+ // Copy of Scene1200::LaserPanel::proc13()
_areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
-bool Scene1950::Hotspot2::startAction(CursorType action, Event &event) {
+/*--------------------------------------------------------------------------*/
+
+bool Scene1950::Keypad::startAction(CursorType action, Event &event) {
if ((action != CURSOR_USE) || (R2_GLOBALS.getFlag(37)))
return SceneHotspot::startAction(action, event);
@@ -13021,21 +13729,21 @@ bool Scene1950::Hotspot2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1950::Actor2::startAction(CursorType action, Event &event) {
+bool Scene1950::Door::startAction(CursorType action, Event &event) {
if (action != R2_SCRITH_KEY)
return SceneActor::startAction(action, event);
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- R2_INVENTORY.setObjectScene(31, 0);
+ R2_INVENTORY.setObjectScene(R2_SCRITH_KEY, 0);
scene->_sceneMode = 1958;
- scene->setAction(&scene->_sequenceManager, scene, 1958, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1958, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
}
-bool Scene1950::Actor3::startAction(CursorType action, Event &event) {
- if ((action != CURSOR_USE) || (R2_INVENTORY.getObjectScene(35) != 1950))
+bool Scene1950::Scrolls::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) != 1950))
return SceneActor::startAction(action, event);
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
@@ -13047,7 +13755,7 @@ bool Scene1950::Actor3::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene1950::Actor5::startAction(CursorType action, Event &event) {
+bool Scene1950::Gem::startAction(CursorType action, Event &event) {
if ((action != CURSOR_USE) || (!R2_GLOBALS.getFlag(37)))
return SceneActor::startAction(action, event);
@@ -13060,85 +13768,84 @@ bool Scene1950::Actor5::startAction(CursorType action, Event &event) {
return true;
}
-Scene1950::Actor8::Actor8() {
- _fieldA4 = 0;
- _fieldA6 = 0;
- _fieldA8 = 0;
- _fieldAA = 0;
- _fieldAC = 0;
- _fieldAE = 0;
- _fieldAF = 0;
+/*--------------------------------------------------------------------------*/
+
+Scene1950::Vampire::Vampire() {
+ _deadPosition = Common::Point(0, 0);
+ _deltaX = 0;
+ _deltaY = 0;
+ _vampireMode = 0;
}
-void Scene1950::Actor8::synchronize(Serializer &s) {
+void Scene1950::Vampire::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
- s.syncAsSint16LE(_fieldA8);
- s.syncAsSint16LE(_fieldAA);
- s.syncAsSint16LE(_fieldAC);
- s.syncAsByte(_fieldAE);
- s.syncAsByte(_fieldAF);
+ s.syncAsSint16LE(_deadPosition.x);
+ s.syncAsSint16LE(_deadPosition.y);
+ s.syncAsSint16LE(_deltaX);
+ s.syncAsSint16LE(_deltaY);
+ s.syncAsSint16LE(_vampireMode);
}
-void Scene1950::Actor8::signal() {
+void Scene1950::Vampire::signal() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- switch (_fieldAC) {
+ switch (_vampireMode) {
case 19: {
- _fieldAC = 0;
+ _vampireMode = 0;
setVisage(1960);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
setStrip(2);
else
setStrip(1);
NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &scene->_field418, this);
+ addMover(mover, &scene->_vampireDestPos, scene);
}
break;
case 20: {
- _fieldAC = 19;
+ // Non fatal shot
+ _vampireMode = 19;
R2_GLOBALS._player.setVisage(22);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
R2_GLOBALS._player.setStrip(1);
else
R2_GLOBALS._player.setStrip(2);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) + 1]--;
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
- if (R2_GLOBALS._v566A5 == 3)
- _fieldA4 = _position.x + 10;
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ _deadPosition.x = _position.x + 10;
else
- _fieldA4 = _position.x - 10;
+ _deadPosition.x = _position.x - 10;
+ _deadPosition.y = _position.y - 4;
- _fieldA6 = _position.y -4;
setVisage(1961);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
setStrip(2);
else
setStrip(1);
animate(ANIM_MODE_2, NULL);
- Common::Point pt(_fieldA4, _fieldA6);
+ Common::Point pt = _deadPosition;
PlayerMover *mover = new PlayerMover();
addMover(mover, &pt, this);
R2_GLOBALS._player.enableControl();
}
break;
- case 21:
+ case 21: {
+ // Fatal shot
R2_GLOBALS._player.setVisage(22);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
R2_GLOBALS._player.setStrip(1);
else
R2_GLOBALS._player.setStrip(2);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
setVisage(1961);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
setStrip(4);
else
setStrip(3);
@@ -13148,47 +13855,49 @@ void Scene1950::Actor8::signal() {
R2_GLOBALS._sound2.play(226);
animate(ANIM_MODE_5, NULL);
fixPriority(10);
- R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) ]--;
- R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) + 1]--;
- R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) + 2] = _position.x;
- R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) + 3] = _position.y;
- _fieldA8 = (_position.x - R2_GLOBALS._player._position.x) / 2;
- _fieldAA = (_position.y - R2_GLOBALS._player._position.y) / 2;
-
- _fieldAE = 0;
- for (_fieldAF = 0; _fieldAF < 18; ++_fieldAF)
- if (R2_GLOBALS._v56613[4 * _fieldAF] == 0)
- ++_fieldAE;
-
- if (_fieldAE == 18) {
+
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive = false;
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._position = _position;
+ _deltaX = (_position.x - R2_GLOBALS._player._position.x) / 2;
+ _deltaY = (_position.y - R2_GLOBALS._player._position.y) / 2;
+
+ byte vampireCount = 0;
+ for (byte i = 0; i < 18; ++i) {
+ if (!R2_GLOBALS._vampireData[i]._isAlive)
+ ++vampireCount;
+ }
+
+ if (vampireCount == 18) {
R2_GLOBALS.setFlag(36);
- _fieldAC = 23;
- Common::Point pt(R2_GLOBALS._player._position.x + _fieldA8, R2_GLOBALS._player._position.y + _fieldAA);
+ _vampireMode = 23;
+ Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
- } else if (_fieldAE == 1) {
- _fieldAC = 22;
- Common::Point pt(R2_GLOBALS._player._position.x + _fieldA8, R2_GLOBALS._player._position.y + _fieldAA);
+ } else if (vampireCount == 1) {
+ _vampireMode = 22;
+ Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
} else {
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
}
- if (R2_GLOBALS._v566A5 == 3)
- scene->_exit3._enabled = true;
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ scene->_eastExit._enabled = true;
else
- scene->_exit6._enabled = true;
+ scene->_westExit._enabled = true;
- scene->_field416 = 0;
+ scene->_vampireActive = false;
+ }
break;
case 22:
- SceneItem::display(1950, 18, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ SceneItem::display(1950, 18, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 23:
- SceneItem::display(1950, 25, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- scene->_sceneMode = R2_GLOBALS._v566A5;
+ SceneItem::display(1950, 25, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ scene->_sceneMode = R2_GLOBALS._flubMazeEntryDirection;
scene->setAction(&scene->_sequenceManager, scene, 1960, &R2_GLOBALS._player, NULL);
break;
default:
@@ -13196,21 +13905,22 @@ void Scene1950::Actor8::signal() {
}
}
-bool Scene1950::Actor8::startAction(CursorType action, Event &event) {
+bool Scene1950::Vampire::startAction(CursorType action, Event &event) {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- if ((R2_GLOBALS._v56613[(scene->_field41C - 1) * 4] == 0) || (action != R2_PHOTON_STUNNER))
+ if (!R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive ||
+ (action != R2_PHOTON_STUNNER))
return SceneActor::startAction(action, event);
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._v56613[((scene->_field41C - 1) * 4) + 1] <= 1)
- _fieldAC = 21;
+ if (R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired <= 1)
+ _vampireMode = 21;
else
- _fieldAC = 20;
+ _vampireMode = 20;
R2_GLOBALS._player.setVisage(25);
- if (R2_GLOBALS._v566A5 == 3)
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
R2_GLOBALS._player.setStrip(2);
else
R2_GLOBALS._player.setStrip(1);
@@ -13220,12 +13930,14 @@ bool Scene1950::Actor8::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1950::Exit1::changeScene() {
+/*--------------------------------------------------------------------------*/
+
+void Scene1950::NorthExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 1;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 1;
scene->_sceneMode = 11;
Common::Point pt(160, 127);
@@ -13233,15 +13945,15 @@ void Scene1950::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1950::Exit2::changeScene() {
+void Scene1950::UpExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 2;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 2;
scene->_sceneMode = 12;
- if (scene->_field412 == 0) {
+ if (!scene->_upExitStyle) {
if (R2_GLOBALS.getFlag(36))
scene->setAction(&scene->_sequenceManager, scene, 1953, &R2_GLOBALS._player, NULL);
else
@@ -13254,15 +13966,15 @@ void Scene1950::Exit2::changeScene() {
}
}
-void Scene1950::Exit3::changeScene() {
+void Scene1950::EastExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 3;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 3;
scene->_sceneMode = 13;
- if (scene->_field416 != 0)
+ if (scene->_vampireActive)
R2_GLOBALS._player.animate(ANIM_MODE_9);
Common::Point pt(340, 160);
@@ -13270,12 +13982,12 @@ void Scene1950::Exit3::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1950::Exit4::changeScene() {
+void Scene1950::DownExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 4;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 4;
scene->_sceneMode = 14;
if (R2_GLOBALS.getFlag(36))
@@ -13284,12 +13996,12 @@ void Scene1950::Exit4::changeScene() {
scene->setAction(&scene->_sequenceManager, scene, 1973, &R2_GLOBALS._player, NULL);
}
-void Scene1950::Exit5::changeScene() {
+void Scene1950::SouthExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 5;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 5;
scene->_sceneMode = 15;
Common::Point pt(160, 213);
@@ -13297,30 +14009,32 @@ void Scene1950::Exit5::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene1950::Exit6::changeScene() {
+void Scene1950::WestExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 5;
- if (R2_GLOBALS._v566A4 == 2) {
- if ((R2_GLOBALS.getFlag(36)) && (R2_INVENTORY.getObjectScene(34) == 2) && (R2_INVENTORY.getObjectScene(35) == 2)) {
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 6;
+
+ if (R2_GLOBALS._flubMazeArea == 2) {
+ // In the very first corridor area after the Scrith Door
+ if ((R2_GLOBALS.getFlag(36)) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 2) && (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)) {
scene->_sceneMode = 1961;
Common::Point pt(-20, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, scene);
} else {
if (!R2_GLOBALS.getFlag(36))
- SceneItem::display(1950, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- if ((R2_INVENTORY.getObjectScene(34) == 1950) || (R2_INVENTORY.getObjectScene(35) == 1950))
- SceneItem::display(1950, 34, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1950, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ if ((R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 1950))
+ SceneItem::display(1950, 34, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
scene->_sceneMode = 0;
Common::Point pt(30, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
} else {
- if (scene->_field416 != 0)
+ if (scene->_vampireActive)
R2_GLOBALS._player.animate(ANIM_MODE_9);
scene->_sceneMode = 16;
@@ -13330,28 +14044,28 @@ void Scene1950::Exit6::changeScene() {
}
}
-void Scene1950::Exit7::changeScene() {
+void Scene1950::ShaftExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 0;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 0;
scene->_sceneMode = 1951;
scene->setAction(&scene->_sequenceManager, scene, 1951, &R2_GLOBALS._player, NULL);
}
-void Scene1950::Exit8::changeScene() {
+void Scene1950::DoorExit::changeScene() {
Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A5 = 3;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 3;
if (R2_GLOBALS._player._visage == 22) {
scene->_sceneMode = 1975;
scene->setAction(&scene->_sequenceManager, scene, 1975, &R2_GLOBALS._player, NULL);
} else {
- SceneItem::display(1950, 22, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- R2_GLOBALS._v566A5 = 0;
+ SceneItem::display(1950, 22, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._flubMazeEntryDirection = 0;
scene->_sceneMode = 0;
Common::Point pt(250, 150);
NpcMover *mover = new NpcMover();
@@ -13360,33 +14074,55 @@ void Scene1950::Exit8::changeScene() {
}
}
-void Scene1950::subBDC1E() {
- _exit1._enabled = false;
- _exit2._enabled = false;
- _exit3._enabled = false;
- _exit4._enabled = false;
- _exit5._enabled = false;
- _exit6._enabled = false;
- _exit7._enabled = false;
- _exit8._enabled = false;
- _exit1._insideArea = false;
- _exit2._insideArea = false;
- _exit3._insideArea = false;
- _exit4._insideArea = false;
- _exit5._insideArea = false;
- _exit6._insideArea = false;
- _exit7._insideArea = false;
- _exit8._insideArea = false;
- _exit1._moving = false;
- _exit2._moving = false;
- _exit3._moving = false;
- _exit4._moving = false;
- _exit5._moving = false;
- _exit6._moving = false;
- _exit7._moving = false;
- _exit8._moving = false;
- _field412 = 0;
- switch (R2_GLOBALS._v566A4 - 1) {
+/*--------------------------------------------------------------------------*/
+
+Scene1950::Scene1950() {
+ _upExitStyle = false;
+ _removeFlag = false;
+ _vampireActive = false;
+ _vampireDestPos = Common::Point(0, 0);
+ _vampireIndex = 0;
+}
+
+void Scene1950::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_upExitStyle);
+ s.syncAsSint16LE(_removeFlag);
+ s.syncAsSint16LE(_vampireActive);
+ s.syncAsSint16LE(_vampireDestPos.x);
+ s.syncAsSint16LE(_vampireDestPos.y);
+ s.syncAsSint16LE(_vampireIndex);
+}
+
+void Scene1950::initArea() {
+ _northExit._enabled = false;
+ _upExit._enabled = false;
+ _eastExit._enabled = false;
+ _downExit._enabled = false;
+ _southExit._enabled = false;
+ _westExit._enabled = false;
+ _shaftExit._enabled = false;
+ _doorExit._enabled = false;
+ _northExit._insideArea = false;
+ _upExit._insideArea = false;
+ _eastExit._insideArea = false;
+ _downExit._insideArea = false;
+ _southExit._insideArea = false;
+ _westExit._insideArea = false;
+ _shaftExit._insideArea = false;
+ _doorExit._insideArea = false;
+ _northExit._moving = false;
+ _upExit._moving = false;
+ _eastExit._moving = false;
+ _downExit._moving = false;
+ _southExit._moving = false;
+ _westExit._moving = false;
+ _shaftExit._moving = false;
+ _doorExit._moving = false;
+ _upExitStyle = false;
+
+ switch (R2_GLOBALS._flubMazeArea - 1) {
case 0:
loadScene(1948);
break;
@@ -13611,25 +14347,25 @@ void Scene1950::subBDC1E() {
// No break on purpose
case 67:
loadScene(1985);
- _field412 = 1;
+ _upExitStyle = true;
break;
default:
break;
}
- if (R2_GLOBALS._v566A4 != 1)
+ if (R2_GLOBALS._flubMazeArea != 1)
R2_GLOBALS._walkRegions.load(1950);
- switch (R2_GLOBALS._v566A4 - 1) {
+ switch (R2_GLOBALS._flubMazeArea - 1) {
case 0:
- _exit7._enabled = true;
- if ((R2_INVENTORY.getObjectScene(31) == 0) && (R2_INVENTORY.getObjectScene(34) == 1950))
- _exit8._enabled = true;
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(4);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
+ _shaftExit._enabled = true;
+ if ((R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950))
+ _doorExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
break;
case 1:
// No break on purpose
@@ -13694,8 +14430,8 @@ void Scene1950::subBDC1E() {
case 102:
// No break on purpose
case 103:
- _exit3._enabled = true;
- _exit6._enabled = true;
+ _eastExit._enabled = true;
+ _westExit._enabled = true;
break;
case 4:
// No break on purpose
@@ -13746,9 +14482,9 @@ void Scene1950::subBDC1E() {
case 100:
// No break on purpose
case 104:
- _exit6._enabled = true;
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(9);
+ _westExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(9);
break;
case 5:
// No break on purpose
@@ -13797,25 +14533,25 @@ void Scene1950::subBDC1E() {
case 99:
// No break on purpose
case 101:
- _exit3._enabled = true;
- R2_GLOBALS._walkRegions.enableRegion(1);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(13);
+ _eastExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(13);
break;
default:
- R2_GLOBALS._walkRegions.enableRegion(1);
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(9);
- R2_GLOBALS._walkRegions.enableRegion(13);
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ R2_GLOBALS._walkRegions.disableRegion(13);
break;
}
- _object1.remove();
- _object1.removeObject();
- _actor1.remove();
+ _northDoorway.remove();
+ _northDoorway.removeObject();
+ _southDoorway.remove();
- switch (R2_GLOBALS._v566A4 - 4) {
+ switch (R2_GLOBALS._flubMazeArea - 4) {
case 0:
// No break on purpose
case 3:
@@ -13853,17 +14589,17 @@ void Scene1950::subBDC1E() {
case 82:
// No break on purpose
case 90:
- _exit1._enabled = true;
- _object1.setup2(1950, (R2_GLOBALS._v566A4 % 2) + 1, 1, 160, 237, 25, 0);
-
- _actor1.postInit();
- _actor1.setVisage(1950);
- _actor1.setStrip((((R2_GLOBALS._v566A4 - 1) / 35) % 2) + 1);
- _actor1.setFrame(2);
- _actor1.setPosition(Common::Point(160, 167));
- _actor1.fixPriority(220);
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(4);
+ _northExit._enabled = true;
+ _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
+ //visage,strip,frame,px,py,priority,effect
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(2);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
break;
case 7:
// No break on purpose
@@ -13902,44 +14638,45 @@ void Scene1950::subBDC1E() {
case 89:
// No break on purpose
case 97:
- _exit5._enabled = true;
- _actor1.postInit();
- _actor1.setVisage(1950);
- _actor1.setStrip((((R2_GLOBALS._v566A4 - 1) / 35) % 2) + 1);
- _actor1.setFrame(3);
- _actor1.setPosition(Common::Point(160, 167));
- _actor1.fixPriority(220);
+ _southExit._enabled = true;
+
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(3);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
break;
case 58:
// No break on purpose
case 74:
// No break on purpose
case 80:
- _exit1._enabled = true;
- _exit5._enabled = true;
+ _northExit._enabled = true;
+ _southExit._enabled = true;
- _object1.setup(1950, (R2_GLOBALS._v566A4 % 2) + 1, 1, 160, 137, 25);
+ _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
- _actor1.postInit();
- _actor1.setVisage(1950);
- _actor1.setStrip((((R2_GLOBALS._v566A4 - 1) / 35) % 2) + 1);
- _actor1.setFrame(3);
- _actor1.setPosition(Common::Point(160, 167));
- _actor1.fixPriority(220);
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(4);
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(3);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
break;
default:
- _actor1.postInit();
- _actor1.setVisage(1950);
- _actor1.setStrip(((R2_GLOBALS._v566A4 - 1) % 35) + 1);
- _actor1.setFrame(2);
- _actor1.setPosition(Common::Point(160, 167));
- _actor1.fixPriority(220);
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip(((R2_GLOBALS._flubMazeArea - 1) / 35) % 2 + 1);
+ _southDoorway.setFrame(2);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
break;
}
- switch (R2_GLOBALS._v566A4 - 3) {
+ switch (R2_GLOBALS._flubMazeArea - 3) {
case 0:
// No break on purpose
case 3:
@@ -13983,7 +14720,8 @@ void Scene1950::subBDC1E() {
case 60:
// No break on purpose
case 63:
- _exit2._enabled = true;
+ _upExit._enabled = true;
+ break;
case 54:
// No break on purpose
case 61:
@@ -13991,7 +14729,7 @@ void Scene1950::subBDC1E() {
case 62:
// No break on purpose
case 65:
- _exit2._enabled = true;
+ _upExit._enabled = true;
// No break on purpose
case 35:
// No break on purpose
@@ -14036,206 +14774,214 @@ void Scene1950::subBDC1E() {
case 98:
// No break on purpose
case 100:
- _exit4._enabled = true;
- R2_GLOBALS._walkRegions.enableRegion(4);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(10);
- R2_GLOBALS._walkRegions.enableRegion(11);
+ _downExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(11);
default:
break;
}
R2_GLOBALS._uiElements.draw();
}
-void Scene1950::subBE59B() {
+void Scene1950::enterArea() {
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- _actor8.remove();
- _actor2.remove();
- _actor3.remove();
+ _vampire.remove();
+ _door.remove();
+ _scrolls.remove();
- _field416 = 0;
- _field41C = 0;
+ _vampireActive = false;
+ _vampireIndex = 0;
- switch (R2_GLOBALS._v566A4) {
+ // Certain areas have a vampire in them
+ switch (R2_GLOBALS._flubMazeArea) {
case 10:
- _field41C = 1;
+ _vampireIndex = 1;
break;
case 13:
- _field41C = 2;
+ _vampireIndex = 2;
break;
case 16:
- _field41C = 3;
+ _vampireIndex = 3;
break;
case 17:
- _field41C = 4;
+ _vampireIndex = 4;
break;
case 24:
- _field41C = 5;
+ _vampireIndex = 5;
break;
case 25:
- _field41C = 6;
+ _vampireIndex = 6;
break;
case 31:
- _field41C = 7;
+ _vampireIndex = 7;
break;
case 40:
- _field41C = 8;
+ _vampireIndex = 8;
break;
case 45:
- _field41C = 9;
+ _vampireIndex = 9;
break;
case 46:
- _field41C = 10;
+ _vampireIndex = 10;
break;
case 73:
- _field41C = 11;
+ _vampireIndex = 11;
break;
case 75:
- _field41C = 12;
+ _vampireIndex = 12;
break;
case 80:
- _field41C = 13;
+ _vampireIndex = 13;
break;
case 87:
- _field41C = 14;
+ _vampireIndex = 14;
break;
case 88:
- _field41C = 15;
+ _vampireIndex = 15;
break;
case 96:
- _field41C = 16;
+ _vampireIndex = 16;
break;
case 97:
- _field41C = 17;
+ _vampireIndex = 17;
break;
case 104:
- _field41C = 18;
+ _vampireIndex = 18;
break;
default:
break;
}
- if (_field41C != 0) {
- _actor8.postInit();
- _actor8._numFrames = 6;
- _actor8._moveRate = 6;
- _actor8._moveDiff = Common::Point(3, 2);
- _actor8._effect = 1;
- if (R2_GLOBALS._v56613[(_field41C - 1) * 4] == 0) {
- _actor8.setPosition(Common::Point(R2_GLOBALS._v56613[((_field41C - 1) * 4) + 2], R2_GLOBALS._v56613[((_field41C - 1) * 4) + 3]));
- _actor8.animate(ANIM_MODE_NONE, NULL);
- _actor8.addMover(NULL);
- _actor8.setVisage(1961);
- _actor8.setStrip(4);
- _actor8.setFrame(10);
- _actor8.fixPriority(10);
- _actor8.setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
+ if (_vampireIndex != 0) {
+ _vampire.postInit();
+ _vampire._numFrames = 6;
+ _vampire._moveRate = 6;
+ _vampire._moveDiff = Common::Point(3, 2);
+ _vampire._effect = EFFECT_SHADED;
+
+ if (!R2_GLOBALS._vampireData[_vampireIndex - 1]._isAlive) {
+ // Show vampire ashes
+ _vampire.setPosition(Common::Point(R2_GLOBALS._vampireData[_vampireIndex - 1]._position));
+ _vampire.animate(ANIM_MODE_NONE, NULL);
+ _vampire.addMover(NULL);
+ _vampire.setVisage(1961);
+ _vampire.setStrip(4);
+ _vampire.setFrame(10);
+ _vampire.fixPriority(10);
+ _vampire.setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
} else {
- _actor8.setVisage(1960);
- _actor8.setPosition(Common::Point(160, 130));
- _actor8.animate(ANIM_MODE_2, NULL);
- _actor8.setDetails(1950, 12, -1, 14, 2, (SceneItem *) NULL);
- _field416 = 1;
+ // Start the vampire
+ _vampire.setVisage(1960);
+ _vampire.setPosition(Common::Point(160, 130));
+ _vampire.animate(ANIM_MODE_2, NULL);
+ _vampire.setDetails(1950, 12, -1, 14, 2, (SceneItem *) NULL);
+ _vampireActive = true;
}
}
- if ((R2_GLOBALS._v566A4 == 1) && (R2_INVENTORY.getObjectScene(31) != 0)) {
- _actor2.postInit();
- _actor2.setVisage(1948);
- _actor2.setStrip(3);
- _actor2.setPosition(Common::Point(278, 155));
- _actor2.fixPriority(100);
- _actor2.setDetails(1950, 19, 20, 23, 2, (SceneItem *) NULL);
+ if ((R2_GLOBALS._flubMazeArea == 1) && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) != 0)) {
+ // Show doorway at the right hand side of the very first flub corridor
+ _door.postInit();
+ _door.setVisage(1948);
+ _door.setStrip(3);
+ _door.setPosition(Common::Point(278, 155));
+ _door.fixPriority(100);
+ _door.setDetails(1950, 19, 20, 23, 2, (SceneItem *) NULL);
}
- if (R2_GLOBALS._v566A4 == 102) {
+ if (R2_GLOBALS._flubMazeArea == 102) {
R2_GLOBALS._walkRegions.load(1951);
- R2_GLOBALS._walkRegions.enableRegion(1);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(7);
-
- _actor6.postInit();
- _actor6.setVisage(1970);
- _actor6.setStrip(1);
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+
+ _cube.postInit();
+ _cube.setVisage(1970);
+ _cube.setStrip(1);
if (R2_GLOBALS.getFlag(37))
- _actor6.setFrame(3);
+ _cube.setFrame(3);
else
- _actor6.setFrame(1);
- _actor6.setPosition(Common::Point(193, 158));
- _actor6.setDetails(1950, 3, 4, 5, 2, (SceneItem *) NULL);
+ _cube.setFrame(1);
+ _cube.setPosition(Common::Point(193, 158));
+ _cube.setDetails(1950, 3, 4, 5, 2, (SceneItem *) NULL);
- _actor7.postInit();
- _actor7.setVisage(1970);
- _actor7.setStrip(3);
- _actor7.animate(ANIM_MODE_2, NULL);
- _actor7._numFrames = 6;
- _actor7.setPosition(Common::Point(194, 158));
- _actor7.fixPriority(159);
+ _pulsingLights.postInit();
+ _pulsingLights.setVisage(1970);
+ _pulsingLights.setStrip(3);
+ _pulsingLights.animate(ANIM_MODE_2, NULL);
+ _pulsingLights._numFrames = 6;
+ _pulsingLights.setPosition(Common::Point(194, 158));
+ _pulsingLights.fixPriority(159);
- _item2.setDetails(Rect(188, 124, 199, 133), 1950, 27, 28, -1, 2, NULL);
+ _keypad.setDetails(Rect(188, 124, 199, 133), 1950, 27, 28, -1, 2, NULL);
- if (R2_INVENTORY.getObjectScene(34) == 1950) {
- _actor5.postInit();
- _actor5.setVisage(1970);
- _actor5.setStrip(1);
- _actor5.setFrame(2);
- _actor5.fixPriority(160);
+ if (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) {
+ _gem.postInit();
+ _gem.setVisage(1970);
+ _gem.setStrip(1);
+ _gem.setFrame(2);
+ _gem.fixPriority(160);
}
if (R2_GLOBALS.getFlag(37)) {
- _actor5.setPosition(Common::Point(192, 118));
- _actor5.setDetails(1950, 9, 4, -1, 2, (SceneItem *) NULL);
+ _gem.setPosition(Common::Point(192, 118));
+ _gem.setDetails(1950, 9, 4, -1, 2, (SceneItem *) NULL);
} else {
- _actor4.postInit();
- _actor4.setVisage(1970);
- _actor4.setStrip(4);
- _actor4._numFrames = 4;
- _actor4.animate(ANIM_MODE_8, NULL);
- _actor4.setPosition(Common::Point(192, 121));
- _actor4.fixPriority(159);
- _actor4.setDetails(1950, 6, 7, 8, 2, (SceneItem *) NULL);
-
- _actor5.setPosition(Common::Point(192, 109));
- _actor5.setDetails(1950, 9, 7, 8, 2, (SceneItem *) NULL);
- }
-
- _actor3.postInit();
- _actor3.setVisage(1972);
- _actor3.setStrip(1);
- _actor3.setPosition(Common::Point(76, 94));
- _actor3.fixPriority(25);
- _actor3.setDetails(1950, 30, -1, -1, 2, (SceneItem *) NULL);
- if (R2_INVENTORY.getObjectScene(35) == 2)
- _actor3.setFrame(2);
+ _containmentField.postInit();
+ _containmentField.setVisage(1970);
+ _containmentField.setStrip(4);
+ _containmentField._numFrames = 4;
+ _containmentField.animate(ANIM_MODE_8, 0, NULL);
+ _containmentField.setPosition(Common::Point(192, 121));
+ _containmentField.fixPriority(159);
+ _containmentField.setDetails(1950, 6, 7, 8, 2, (SceneItem *) NULL);
+
+ _gem.setPosition(Common::Point(192, 109));
+ _gem.setDetails(1950, 9, 7, 8, 2, (SceneItem *) NULL);
+ }
+
+ _scrolls.postInit();
+ _scrolls.setVisage(1972);
+ _scrolls.setStrip(1);
+ _scrolls.setPosition(Common::Point(76, 94));
+ _scrolls.fixPriority(25);
+ _scrolls.setDetails(1950, 30, -1, -1, 2, (SceneItem *) NULL);
+ if (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)
+ _scrolls.setFrame(2);
else
- _actor3.setFrame(1);
+ _scrolls.setFrame(1);
- _field414 = 1;
- } else if (_field414 != 0) {
- _actor6.remove();
- _actor4.remove();
- _actor5.remove();
- _actor7.remove();
- _actor3.remove();
+ _removeFlag = true;
+ } else if (_removeFlag) {
+ _cube.remove();
+ _containmentField.remove();
+ _gem.remove();
+ _pulsingLights.remove();
+ _scrolls.remove();
- _item1.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 2, NULL);
+ R2_GLOBALS._sceneItems.remove(&_background);
+ _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 2, NULL);
+
+ _removeFlag = false;
}
- switch (R2_GLOBALS._v566A5) {
+ switch (R2_GLOBALS._flubMazeEntryDirection) {
case 0:
_sceneMode = 1950;
- if (R2_INVENTORY.getObjectScene(31) == 0) {
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- } else {
+ if (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)
+ // The original uses CURSOR_ARROW. CURSOR_WALK is much more coherent
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ else
setAction(&_sequenceManager, this, 1950, &R2_GLOBALS._player, NULL);
- }
+
break;
case 1: {
- _sceneMode = R2_GLOBALS._v566A5;
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
R2_GLOBALS._player.setPosition(Common::Point(160, 213));
Common::Point pt(160, 160);
NpcMover *mover = new NpcMover();
@@ -14243,30 +14989,30 @@ void Scene1950::subBE59B() {
}
break;
case 2:
- _sceneMode = R2_GLOBALS._v566A5;
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
if (R2_GLOBALS.getFlag(36))
setAction(&_sequenceManager, this, 1957, &R2_GLOBALS._player, NULL);
else
setAction(&_sequenceManager, this, 1974, &R2_GLOBALS._player, NULL);
break;
case 3:
- if (_field416 == 0) {
- _sceneMode = R2_GLOBALS._v566A5;
+ // Entering from the left
+ if (!_vampireActive) {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
Common::Point pt(30, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
} else {
_sceneMode = 18;
- _exit3._enabled = false;
- _field418 = Common::Point(60, 152);
- R2_GLOBALS._v56AAB = 0;
+ _eastExit._enabled = false;
+ _vampireDestPos = Common::Point(60, 152);
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- _actor8.setStrip(2);
+ _vampire.setStrip(2);
NpcMover *mover = new NpcMover();
- _actor8.addMover(mover, &_field418, this);
+ _vampire.addMover(mover, &_vampireDestPos, this);
R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
Common::Point pt2(30, 160);
@@ -14275,8 +15021,8 @@ void Scene1950::subBE59B() {
}
break;
case 4:
- _sceneMode = R2_GLOBALS._v566A5;
- if (_field412 == 0) {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ if (!_upExitStyle) {
if (R2_GLOBALS.getFlag(36))
setAction(&_sequenceManager, this, 1955, &R2_GLOBALS._player, NULL);
else
@@ -14289,7 +15035,7 @@ void Scene1950::subBE59B() {
}
break;
case 5: {
- _sceneMode = R2_GLOBALS._v566A5;
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
R2_GLOBALS._player.setPosition(Common::Point(160, 127));
Common::Point pt(160, 160);
NpcMover *mover = new NpcMover();
@@ -14297,9 +15043,10 @@ void Scene1950::subBE59B() {
}
break;
case 6:
- if (_field416 == 0) {
- _sceneMode = R2_GLOBALS._v566A5;
- if (R2_GLOBALS._v566A4 == 1) {
+ // Entering from the right
+ if (!_vampireActive) {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ if (R2_GLOBALS._flubMazeArea == 1) {
setAction(&_sequenceManager, this, 1961, &R2_GLOBALS._player, NULL);
} else {
R2_GLOBALS._player.setPosition(Common::Point(340, 160));
@@ -14309,16 +15056,15 @@ void Scene1950::subBE59B() {
}
} else {
_sceneMode = 17;
- _exit6._enabled = false;
- _field418 = Common::Point(259, 152);
+ _westExit._enabled = false;
+ _vampireDestPos = Common::Point(259, 152);
- R2_GLOBALS._v56AAB = 0;
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- _actor8.setStrip(1);
+ _vampire.setStrip(1);
NpcMover *mover = new NpcMover();
- _actor8.addMover(mover, &_field418, this);
+ _vampire.addMover(mover, &_vampireDestPos, this);
R2_GLOBALS._player.setPosition(Common::Point(340, 160));
Common::Point pt2(289, 160);
@@ -14331,65 +15077,74 @@ void Scene1950::subBE59B() {
}
}
-void Scene1950::subBF4B4(int indx) {
+void Scene1950::doButtonPress(int indx) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
- int si = indx - 1;
- if ((indx / 4) == (si / 4)) {
- if (si < 0)
- si = 3;
- } else
- si = 4;
- if (_area1._arrActor1[si]._fieldA8 == 0) {
- _area1._arrActor1[si].setFrame(2);
- _area1._arrActor1[si]._fieldA8 = 1;
+ int prevIndex = indx - 1;
+ if ((indx / 4) == (prevIndex / 4)) {
+ if (prevIndex < 0)
+ prevIndex = 3;
} else {
- _area1._arrActor1[si].setFrame(1);
- _area1._arrActor1[si]._fieldA8 = 0;
+ prevIndex += 4;
}
- si = indx + 1;
- if ((indx / 4) == (si / 4)) {
- if (si > 15)
- si = 12;
- } else
- si -= 4;
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
- if (_area1._arrActor1[si]._fieldA8 == 0) {
- _area1._arrActor1[si].setFrame(2);
- _area1._arrActor1[si]._fieldA8 = 1;
+ prevIndex = indx + 1;
+ if ((indx / 4) == (prevIndex / 4)) {
+ if (prevIndex > 15)
+ prevIndex = 12;
} else {
- _area1._arrActor1[si].setFrame(1);
- _area1._arrActor1[si]._fieldA8 = 0;
+ prevIndex -= 4;
}
- si = indx - 4;
- if (si < 0)
- si += 16;
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
+
+ prevIndex = indx - 4;
+ if (prevIndex < 0)
+ prevIndex += 16;
- if (_area1._arrActor1[si]._fieldA8 == 0) {
- _area1._arrActor1[si].setFrame(2);
- _area1._arrActor1[si]._fieldA8 = 1;
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
} else {
- _area1._arrActor1[si].setFrame(1);
- _area1._arrActor1[si]._fieldA8 = 0;
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
}
- si = indx + 4;
- if (si > 15)
- si -= 16;
+ prevIndex = indx + 4;
+ if (prevIndex > 15)
+ prevIndex -= 16;
- if (_area1._arrActor1[si]._fieldA8 == 0) {
- _area1._arrActor1[si].setFrame(2);
- _area1._arrActor1[si]._fieldA8 = 1;
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
} else {
- _area1._arrActor1[si].setFrame(1);
- _area1._arrActor1[si]._fieldA8 = 0;
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
}
+ // Check whether all the buttons are highlighted
int cpt = 0;
- for (si = 0; si < 16; si++) {
- if (_area1._arrActor1[si]._fieldA8 != 0)
+ for (prevIndex = 0; prevIndex < 16; prevIndex++) {
+ if (_KeypadWindow._buttons[prevIndex]._toggled)
++cpt;
}
@@ -14399,59 +15154,57 @@ void Scene1950::subBF4B4(int indx) {
} else {
R2_GLOBALS.setFlag(37);
_sceneMode = 24;
- // TODO: check if correct. The original doesn't countain a sceneActor in
- // this call, but it's extremely unusual
- setAction(&_sequenceManager, this, 1976, NULL);
+ setAction(&_sequenceManager, scene, 1976, NULL);
}
}
void Scene1950::postInit(SceneObjectList *OwnerList) {
- _field412 = 0;
- _field414 = 0;
- _field416 = 0;
- _field41C = 0;
+ _upExitStyle = false;
+ _removeFlag = false;
+ _vampireActive = false;
+ _vampireIndex = 0;
if (R2_GLOBALS._sceneManager._previousScene == 300)
- R2_GLOBALS._v566A4 = 103;
+ R2_GLOBALS._flubMazeArea = 103;
- subBDC1E();
+ initArea();
SceneExt::postInit();
R2_GLOBALS._sound1.play(105);
- _exit1.setDetails(Rect(130, 46, 189, 135), SHADECURSOR_UP, 1950);
- _exit1.setDest(Common::Point(160, 145));
+ _northExit.setDetails(Rect(130, 46, 189, 135), SHADECURSOR_UP, 1950);
+ _northExit.setDest(Common::Point(160, 145));
- _exit2.setDetails(Rect(208, 0, 255, 73), EXITCURSOR_N, 1950);
- _exit2.setDest(Common::Point(200, 151));
+ _upExit.setDetails(Rect(208, 0, 255, 73), EXITCURSOR_N, 1950);
+ _upExit.setDest(Common::Point(200, 151));
- _exit3.setDetails(Rect(305, 95, 320, 147), EXITCURSOR_E, 1950);
- _exit3.setDest(Common::Point(312, 160));
+ _eastExit.setDetails(Rect(305, 95, 320, 147), EXITCURSOR_E, 1950);
+ _eastExit.setDest(Common::Point(312, 160));
- _exit4.setDetails(Rect(208, 99, 255, 143), EXITCURSOR_S, 1950);
- _exit4.setDest(Common::Point(200, 151));
+ _downExit.setDetails(Rect(208, 99, 255, 143), EXITCURSOR_S, 1950);
+ _downExit.setDest(Common::Point(200, 151));
- _exit5.setDetails(Rect(113, 154, 206, 168), SHADECURSOR_DOWN, 1950);
- _exit5.setDest(Common::Point(160, 165));
+ _southExit.setDetails(Rect(113, 154, 206, 168), SHADECURSOR_DOWN, 1950);
+ _southExit.setDest(Common::Point(160, 165));
- _exit6.setDetails(Rect(0, 95, 14, 147), EXITCURSOR_W, 1950);
- _exit6.setDest(Common::Point(7, 160));
+ _westExit.setDetails(Rect(0, 95, 14, 147), EXITCURSOR_W, 1950);
+ _westExit.setDest(Common::Point(7, 160));
- _exit7.setDetails(Rect(72, 54, 120, 128), EXITCURSOR_NW, 1950);
- _exit7.setDest(Common::Point(120, 140));
+ _shaftExit.setDetails(Rect(72, 54, 120, 128), EXITCURSOR_NW, 1950);
+ _shaftExit.setDest(Common::Point(120, 140));
- _exit8.setDetails(Rect(258, 60, 300, 145), EXITCURSOR_NE, 1950);
- _exit8.setDest(Common::Point(268, 149));
+ _doorExit.setDetails(Rect(258, 60, 300, 145), EXITCURSOR_NE, 1950);
+ _doorExit.setDest(Common::Point(268, 149));
R2_GLOBALS._player.postInit();
- if ( (R2_INVENTORY.getObjectScene(32) == 0) && (R2_INVENTORY.getObjectScene(33) == 0)
- && (R2_INVENTORY.getObjectScene(46) == 0) && (!R2_GLOBALS.getFlag(36)) )
+ if ( (R2_INVENTORY.getObjectScene(R2_TANNER_MASK) == 0) && (R2_INVENTORY.getObjectScene(R2_PURE_GRAIN_ALCOHOL) == 0)
+ && (R2_INVENTORY.getObjectScene(R2_SOAKED_FACEMASK) == 0) && (!R2_GLOBALS.getFlag(36)) )
R2_GLOBALS._player.setVisage(22);
else
R2_GLOBALS._player.setVisage(20);
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- _item1.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 1, NULL);
- subBE59B();
+ enterArea();
}
void Scene1950::remove() {
@@ -14463,45 +15216,50 @@ void Scene1950::remove() {
void Scene1950::signal() {
switch (_sceneMode) {
case 11:
- R2_GLOBALS._v566A4 += 7;
- subBDC1E();
- subBE59B();
+ R2_GLOBALS._flubMazeArea += 7;
+ initArea();
+ enterArea();
break;
case 12:
- R2_GLOBALS._v566A4 += 35;
- subBDC1E();
- subBE59B();
+ // Moving up a ladder within the Flub maze
+ R2_GLOBALS._flubMazeArea += 35;
+ initArea();
+ enterArea();
break;
case 1975:
- SceneItem::display(1950, 21, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(1950, 21, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1,
+ SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
// No break on purpose
case 13:
- ++R2_GLOBALS._v566A4;
- subBDC1E();
- subBE59B();
+ // Moving east within the Flub maze
+ ++R2_GLOBALS._flubMazeArea;
+ initArea();
+ enterArea();
break;
case 14:
- R2_GLOBALS._v566A4 += 221;
- subBDC1E();
- subBE59B();
+ // Moving down a ladder within the Flub maze
+ R2_GLOBALS._flubMazeArea -= 35;
+ initArea();
+ enterArea();
break;
case 15:
- R2_GLOBALS._v566A4 += 249;
- subBDC1E();
- subBE59B();
+ R2_GLOBALS._flubMazeArea -= 7;
+ initArea();
+ enterArea();
break;
case 16:
+ // Moving west within the Flub maze
// No break on purpose
case 1961:
- --R2_GLOBALS._v566A4;
- subBDC1E();
- subBE59B();
+ --R2_GLOBALS._flubMazeArea;
+ initArea();
+ enterArea();
break;
case 17: {
_sceneMode = 13;
- R2_GLOBALS._v566A5 = 3;
- _field416 = 0;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._flubMazeEntryDirection = 3;
+ _vampireActive = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
R2_GLOBALS._player._canWalk = true;
R2_GLOBALS._player.setVisage(22);
R2_GLOBALS._player.animate(ANIM_MODE_9, NULL);
@@ -14510,14 +15268,14 @@ void Scene1950::signal() {
R2_GLOBALS._player.addMover(mover, &pt, this);
Common::Point pt2(289, 160);
NpcMover *mover2 = new NpcMover();
- _actor8.addMover(mover2, &pt2, NULL);
+ _vampire.addMover(mover2, &pt2, NULL);
}
break;
case 18: {
_sceneMode = 16;
- R2_GLOBALS._v566A5 = 6;
- _field416 = 0;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._flubMazeEntryDirection = 6;
+ _vampireActive = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
R2_GLOBALS._player._canWalk = true;
R2_GLOBALS._player.setVisage(22);
R2_GLOBALS._player.animate(ANIM_MODE_9, NULL);
@@ -14526,47 +15284,45 @@ void Scene1950::signal() {
R2_GLOBALS._player.addMover(mover, &pt, this);
Common::Point pt2(30, 160);
NpcMover *mover2 = new NpcMover();
- _actor8.addMover(mover2, &pt2, NULL);
+ _vampire.addMover(mover2, &pt2, NULL);
}
break;
case 24:
- _area1.remove();
+ _KeypadWindow.remove();
_sceneMode = 1966;
- _actor6.setFrame(3);
- setAction(&_sequenceManager, this, 1966, &_actor4, &_actor5, NULL);
+ _cube.setFrame(3);
+ setAction(&_sequenceManager, this, 1966, &_containmentField, &_gem, NULL);
break;
case 1951:
R2_GLOBALS._sound1.fadeOut2(NULL);
R2_GLOBALS._sceneManager.changeScene(1945);
break;
case 1958:
- SceneItem::display(1950, 24, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- _exit8._enabled = true;
+ SceneItem::display(1950, 24, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ _doorExit._enabled = true;
break;
case 1959:
- R2_INVENTORY.setObjectScene(46, 0);
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- _exit8._enabled = true;
+ R2_INVENTORY.setObjectScene(R2_SOAKED_FACEMASK, 0);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ _doorExit._enabled = true;
break;
case 1962:
// No break on purpose
case 1963:
R2_GLOBALS._player.enableControl();
- _area1.proc12(1971, 1, 1, 160, 135);
+ _KeypadWindow.setup2(1971, 1, 1, 160, 135);
break;
case 1964:
// No break on purpose
case 1965:
- if (!R2_GLOBALS.getFlag(37)) {
- SceneItem::display(1950, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- R2_GLOBALS._player.enableControl();
- }
+ if (!R2_GLOBALS.getFlag(37))
+ SceneItem::display(1950, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+
+ R2_GLOBALS._player.enableControl();
break;
case 1966:
- _actor4.remove();
+ _containmentField.remove();
if (R2_GLOBALS.getFlag(36)) {
_sceneMode = 1964;
setAction(&_sequenceManager, this, 1964, &R2_GLOBALS._player, NULL);
@@ -14574,26 +15330,28 @@ void Scene1950::signal() {
_sceneMode = 1965;
setAction(&_sequenceManager, this, 1965, &R2_GLOBALS._player, NULL);
}
- _actor5.setDetails(1950, 9, -1, -1, 2, (SceneItem *) NULL);
+ _gem.setDetails(1950, 9, -1, -1, 2, (SceneItem *) NULL);
+ break;
case 1967: {
_sceneMode = 0;
- R2_INVENTORY.setObjectScene(34, 2);
- _actor5.remove();
+ R2_INVENTORY.setObjectScene(R2_SAPPHIRE_BLUE, 2);
+ _gem.remove();
if (R2_GLOBALS.getFlag(36))
R2_GLOBALS._player.setVisage(20);
else
R2_GLOBALS._player.setVisage(22);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- Common::Point pt(218, 165);
+ // This is a hack to work around a pathfinding issue. original destination is (218, 165)
+ Common::Point pt(128, 165);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 1968:
- R2_GLOBALS._player.disableControl();
- R2_INVENTORY.setObjectScene(35, 2);
- _actor3.setFrame(2);
+ R2_GLOBALS._player.enableControl();
+ R2_INVENTORY.setObjectScene(R2_ANCIENT_SCROLLS, 2);
+ _scrolls.setFrame(2);
if (R2_GLOBALS.getFlag(36))
R2_GLOBALS._player.setVisage(20);
else
@@ -14601,25 +15359,25 @@ void Scene1950::signal() {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
break;
default:
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
void Scene1950::process(Event &event) {
if ( (event.eventType == EVENT_BUTTON_DOWN)
- && (R2_GLOBALS._player._uiEnabled)
- && (R2_GLOBALS._events.getCursor() == R2_LIGHT_BULB)
- && (R2_GLOBALS._player._bounds.contains(event.mousePos))
- && (R2_INVENTORY.getObjectScene(31) == 0)) {
+ && (R2_GLOBALS._player._uiEnabled)
+ && (R2_GLOBALS._events.getCursor() == R2_SOAKED_FACEMASK)
+ && (R2_GLOBALS._player._bounds.contains(event.mousePos))
+ && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)) {
event.handled = true;
R2_GLOBALS._player.disableControl();
- _exit7._enabled = false;
- _exit8._enabled = false;
+ _shaftExit._enabled = false;
+ _doorExit._enabled = false;
_sceneMode = 1959;
setAction(&_sequenceManager, this, 1959, &R2_GLOBALS._player, NULL);
}
+
Scene::process(event);
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h
index f65a89972d..28b82b4045 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.h
@@ -39,6 +39,24 @@ namespace Ringworld2 {
using namespace TsAGE;
+class Scene1000 : public SceneExt {
+public:
+ SequenceManager _sequenceManager1;
+ SequenceManager _sequenceManager2;
+ SpeakerGameText _gameTextSpeaker;
+ AnimationPlayer _animationPlayer;
+
+ int _animCounter;
+ bool _forceCheckAnimationFl;
+public:
+ Scene1000();
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
+};
+
class Scene1010 : public SceneExt {
public:
SequenceManager _sequenceManager;
@@ -57,52 +75,52 @@ public:
};
class Scene1100 : public SceneExt {
- class Actor16 : public SceneActor {
+ class Seeker : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor17 : public SceneActor {
+ class Trooper : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor18 : public SceneActor {
+ class Chief : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412, _field414;
+ int _nextStripNum, _paletteRefreshStatus;
SpeakerSeeker1100 _seekerSpeaker;
SpeakerQuinn1100 _quinnSpeaker;
SpeakerChief1100 _chiefSpeaker;
ScenePalette _palette1;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- NamedHotspot _item7;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
- SceneActor _actor10;
- SceneActor _actor11;
- SceneActor _actor12;
- SceneActor _actor13;
- SceneActor _actor14;
- SceneActor _actor15;
- BackgroundSceneObject _object1;
- BackgroundSceneObject _object2;
- Actor16 _actor16;
- Actor17 _actor17;
- Actor18 _actor18;
+ NamedHotspot _background;
+ NamedHotspot _sky;
+ NamedHotspot _fuana1;
+ NamedHotspot _fauna2;
+ NamedHotspot _bouldersBlockingCave;
+ NamedHotspot _boulders;
+ NamedHotspot _trail;
+ SceneActor _ship;
+ SceneActor _cloud;
+ SceneActor _shipFormation;
+ SceneActor _shipFormationShadow;
+ SceneActor _shotImpact1;
+ SceneActor _shotImpact2;
+ SceneActor _shotImpact3;
+ SceneActor _shotImpact4;
+ SceneActor _shotImpact5;
+ SceneActor _laserShot;
+ SceneActor _animation; // Used for cliff collapse and ship theft
+ SceneActor _leftImpacts;
+ SceneActor _runningGuy1;
+ SceneActor _runningGuy2;
+ SceneActor _runningGuy3;
+ BackgroundSceneObject _rightLandslide;
+ BackgroundSceneObject _purplePlant;
+ Seeker _seeker;
+ Trooper _trooper;
+ Chief _chief;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
SequenceManager _sequenceManager3;
@@ -118,49 +136,44 @@ 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;
+ int _nextCrawlDirection;
int _field414;
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();
@@ -172,10 +185,10 @@ public:
class Scene1337 : public SceneExt {
class unkObj1337sub1: public SceneHotspot {
public:
- SceneObject _object1;
+ SceneObject _card;
- int _field34;
- Common::Point _field36;
+ int _cardId;
+ Common::Point _stationPos;
unkObj1337sub1();
void synchronize(Serializer &s);
@@ -183,9 +196,9 @@ class Scene1337 : public SceneExt {
class unkObj1337_1: public SceneHotspot {
public:
- unkObj1337sub1 _arr1[4];
- unkObj1337sub1 _arr2[8];
- unkObj1337sub1 _arr3[1];
+ unkObj1337sub1 _handCard[4];
+ unkObj1337sub1 _outpostStation[8];
+ unkObj1337sub1 _delayPile[1];
unkObj1337sub1 _arr4[1];
Common::Point _fieldB94;
@@ -200,8 +213,7 @@ class Scene1337 : public SceneExt {
class Action1337: public Action {
public:
- void subD18B5(int resNum, int stripNum, int frameNum);
- void skipFrames(int32 skipCount);
+ void waitFrames(int32 frameCount);
};
class Action1: public Action1337 {
@@ -264,9 +276,9 @@ public:
ASound _aSound2;
BackgroundSceneObject _background1;
bool _autoplay;
- unkObj1337_1 _arrunkObj1337[4];
+ unkObj1337_1 _gameBoardSide[4];
SceneItem _item1;
- SceneObject _object1;
+ SceneObject _currentPlayerArrow;
Action1 _action1;
Action2 _action2;
Action3 _action3;
@@ -280,33 +292,33 @@ public:
Action11 _action11;
Action12 _action12;
Action13 _action13;
- unkObj1337sub1 _item2;
- unkObj1337sub1 _item3;
+ unkObj1337sub1 _animatedCard;
+ unkObj1337sub1 _shuffleAnimation;
unkObj1337sub1 _item4;
BackgroundSceneObject _background2;
- int _field3E24;
+ int _cardsAvailableNumb;
int _field3E26;
- int _field3E28[100];
+ int _availableCardsPile[100];
unkObj1337sub1 *_field3EF0;
unkObj1337sub1 *_field3EF4;
unkObj1337sub1 *_field3EF8;
unkObj1337sub1 _item5;
unkObj1337sub1 _item6;
- unkObj1337sub1 _item7;
+ unkObj1337sub1 _discardPile;
unkObj1337sub1 _item8;
- int _field423C;
- int _field423E;
+ bool _shuffleEndedFl;
+ int _currentPlayerNumb;
int _field4240;
int _field4242;
- int _field4244;
- int _field4246;
+ bool _field4244;
+ bool _field4246;
int _field4248;
int _field424A;
- int _field424C;
- int _field424E;
+ int _instructionsDisplayedFl;
+ int _instructionsWaitCount;
- SceneObject _arrObject1[8];
- SceneObject _arrObject2[8];
+ SceneObject _upperDisplayCard[8];
+ SceneObject _lowerDisplayCard[8];
Scene1337();
virtual void synchronize(Serializer &s);
@@ -345,10 +357,10 @@ public:
void subC51A0(unkObj1337sub1 *subObj1, unkObj1337sub1 *subObj2);
void displayDialog(int dialogNumb);
void subPostInit();
- void subCB59B();
+ void displayInstructions();
void suggestInstructions();
void shuffleCards();
- void subCCF26();
+ void firstShuffle();
void subCD193();
void subCDB90(int arg1, Common::Point pt);
void subCF31D();
@@ -357,10 +369,10 @@ public:
void subD0281();
void subD02CA();
void subD183F(int arg1, int arg2);
- void subD18B5(int resNum, int rlbNum, int arg3);
- int subD18F5();
- int subD1917();
- int subD1940(bool flag);
+ void setCursorData(int resNum, int rlbNum, int frameNum);
+ void subD18F5();
+ void subD1917();
+ void subD1940(bool flag);
void subD195F(int arg1, int arg2);
void subD1975(int arg1, int arg2);
void subD1A48(int arg1);
@@ -373,10 +385,10 @@ public:
class Scene1500 : public SceneExt {
public:
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
+ SceneActor _starship;
+ SceneActor _starshipShadow;
+ SceneActor _smallShip;
+ SceneActor _smallShipShadow;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -397,9 +409,9 @@ class Scene1530 : public SceneExt {
public:
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
+ SceneActor _seeker;
+ SceneActor _leftReactor;
+ SceneActor _rightReactor;
SequenceManager _sequenceManager;
@@ -409,151 +421,136 @@ public:
};
class Scene1550 : public SceneExt {
- class SceneActor1550 : public SceneActor {
+ class Wall : public SceneActor {
public:
- void subA4D14(int frameNumber, int strip);
+ void setupWall(int frameNumber, int strip);
};
- class UnkObj15501 : public SceneActor {
+ class Junk : public SceneActor {
public:
- int _fieldA4;
- int _fieldA6;
+ int _junkNumber;
- UnkObj15501();
+ Junk();
void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
};
- class UnkObj15502 : public SceneActor {
+ class ShipComponent : public SceneActor {
public:
- int _fieldA4;
+ int _componentId;
- UnkObj15502();
+ ShipComponent();
void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
- void subA5CDF(int strip);
+ void setupShipComponent(int componentId);
};
- class UnkObj15503 : public SceneActor {
- public:
- int _fieldA4;
-
- UnkObj15503();
- void synchronize(Serializer &s);
+ class DishControlsWindow : public ModalWindow {
+ class DishControl : public SceneActor {
+ public:
+ int _controlId;
- virtual bool startAction(CursorType action, Event &event);
- };
+ DishControl();
+ void synchronize(Serializer &s);
- class UnkArea1550 : public SceneArea {
+ virtual bool startAction(CursorType action, Event &event);
+ };
public:
byte _field20;
SceneActor _areaActor;
- UnkObj15503 _unkObj155031;
- UnkObj15503 _unkObj155032;
+ DishControl _button;
+ DishControl _lever;
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);
- };
-
- class Hotspot1 : public NamedHotspot {
- public:
- virtual bool startAction(CursorType action, Event &event);
+ virtual void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY);
};
- class Hotspot3 : public NamedHotspot {
+ class WorkingShip : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class Wreckage : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class Companion : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor8 : public SceneActor {
+ class AirBag : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor9 : public SceneActor {
+ class Joystick : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor10 : public SceneActor {
+ class Gyroscope : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor11 : public SceneActor {
+ class DiagnosticsDisplay : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor12 : public SceneActor {
+ class DishTower : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor13 : public SceneActor {
+ class Dish : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor14 : public SceneActor1550 {
- // Nothing specific found in the original
- // TODO: check if it's an useless class
- };
-
public:
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- Hotspot1 _item1;
- Hotspot1 _item2;
- Hotspot3 _item3;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
- Actor8 _actor8;
- Actor9 _actor9;
- Actor10 _actor10;
- Actor11 _actor11;
- Actor12 _actor12;
- Actor13 _actor13;
- UnkObj15501 _arrUnkObj15501[8];
- Actor14 _actor14;
- Actor14 _actor15;
- Actor14 _actor16;
- Actor14 _actor17;
- Actor14 _actor18;
- Actor14 _actor19;
- UnkObj15502 _arrUnkObj15502[8];
- UnkArea1550 _unkArea1;
+ WorkingShip _intactHull1, _intactHull2;
+ SceneHotspot _background;
+ SceneActor _wreckage2; // also used for Lance of Truth landing strut
+ SceneActor _wreckage3;
+ SceneActor _wreckage4;
+ SceneActor _walkway;
+ SceneActor _dishTowerShadow;
+ Wreckage _wreckage;
+ Companion _companion;
+ AirBag _airbag;
+ Joystick _joystick;
+ Gyroscope _gyroscope;
+ DiagnosticsDisplay _diagnosticsDisplay;
+ DishTower _dishTower;
+ Dish _dish;
+ Junk _junk[8];
+ Wall _wallCorner1;
+ Wall _northWall; // Is also reused for landing strip
+ Wall _wallCorner2;
+ Wall _westWall; // Is also reused for left hand space
+ Wall _eastWall;
+ Wall _southWall;
+ ShipComponent _shipComponents[8];
+ DishControlsWindow _dishControlsWindow;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
- int _field412;
- byte _field414;
- int _field415;
- int _field417;
- int _field419;
+ bool _dontExit;
+ int _wallType;
+ int _dishMode;
+ int _sceneResourceId;
+ int _walkRegionsId;
Scene1550();
void synchronize(Serializer &s);
- void subA2B2F();
+ void enterArea();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
@@ -563,14 +560,14 @@ public:
};
class Scene1575 : public SceneExt {
- class Hotspot1 : public NamedHotspot {
+ class Button : public NamedHotspot {
public:
- int _field34;
- int _field36;
+ int _buttonId;
+ bool _pressed;
- Hotspot1();
+ Button();
void synchronize(Serializer &s);
- void subA910D(int indx);
+ void initButton(int buttonId);
virtual void process(Event &event);
virtual bool startAction(CursorType action, Event &event);
@@ -581,12 +578,12 @@ public:
int _field416;
int _field418;
int _field41A;
- Hotspot1 _item1;
- Hotspot1 _item2;
- Hotspot1 _item3;
- Hotspot1 _item4;
- Hotspot1 _item5;
- Hotspot1 _item6;
+ Button _button1;
+ Button _button2;
+ Button _button3;
+ Button _button4;
+ Button _button5;
+ Button _button6;
SceneActor _actor1;
SceneActor _actor2;
SceneActor _actor3;
@@ -616,54 +613,53 @@ public:
};
class Scene1580 : public SceneExt {
- class Hotspot1 : public NamedHotspot {
+ class JoystickPlug : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Hotspot2 : public NamedHotspot {
+ class ScreenSlot : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Joystick : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Screen : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class StorageCompartment : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class HatchButton : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class ThrusterValve : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class Ignitor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412;
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- Hotspot1 _item1;
- Hotspot2 _item2;
- NamedHotspot _item3;
- SceneActor _actor1;
+ JoystickPlug _joystickPlug;
+ ScreenSlot _screenSlot;
+ NamedHotspot _background;
+ SceneActor _screenDisplay;
SceneActor _arrActor[8];
- Actor2 _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
+ Joystick _joystick;
+ Screen _screen;
+ StorageCompartment _storageCompartment;
+ HatchButton _hatchButton;
+ ThrusterValve _thrusterValve;
+ Ignitor _ignitor;
SequenceManager _sequenceManager;
Scene1580();
@@ -674,23 +670,22 @@ public:
};
class Scene1625 : public SceneExt {
- class Actor7 : public SceneActor {
+ class Wire : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412;
SpeakerMiranda1625 _mirandaSpeaker;
SpeakerTeal1625 _tealSpeaker;
SpeakerSoldier1625 _soldierSpeaker;
- NamedHotspot _item1;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- Actor7 _actor7;
+ NamedHotspot _background;
+ SceneActor _teal;
+ SceneActor _tealHead;
+ SceneActor _mirandaMouth;
+ SceneActor _glass;
+ SceneActor _wristRestraints;
+ SceneActor _tealRightArm;
+ Wire _wire;
SequenceManager _sequenceManager;
Scene1625();
@@ -703,60 +698,54 @@ public:
};
class Scene1700 : public SceneExt {
- class Item2 : public NamedHotspot {
+ class RimTransport : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
-
- class Actor11 : public SceneActor {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
- class Actor12 : public SceneActor {
+ class Companion : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
public:
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- NamedHotspot _item1;
- Item2 _item2;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
- SceneActor _actor10;
- Actor11 _actor11;
- Actor12 _actor12;
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
+ NamedHotspot _surface;
+ NamedHotspot _background;
+ SceneActor _playerShadow;
+ SceneActor _companionShadow;
+ SceneActor _slabWest;
+ SceneActor _slabEast;
+ SceneActor _slabShadowWest;
+ SceneActor _slabShadowEast;
+ SceneActor _westPlatform;
+ SceneActor _rimTransportDoor;
+ SceneActor _ledgeHopper;
+ SceneActor _hatch;
+ RimTransport _rimTransport;
+ Companion _companion;
+ NorthExit _northExit;
+ SouthExit _southExit;
+ WestExit _westExit;
SequenceManager _sequenceManager;
- int _field77A;
- int _field77C;
+ bool _walkFlag;
Scene1700();
void synchronize(Serializer &s);
- void subAF3F8();
+ void enterArea();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
@@ -764,58 +753,57 @@ public:
};
class Scene1750 : public SceneExt {
- class Actor4 : public SceneActor {
+ class SpeedSlider : public SceneActor {
public:
- int _fieldA4;
- int _fieldA6;
- int _fieldA8;
- int _fieldAA;
- int _fieldAC;
- int _fieldAE;
+ int _incrAmount;
+ int _xp;
+ int _ys;
+ int _height;
+ int _thumbHeight;
+ bool _mouseDown;
- Actor4();
+ SpeedSlider();
virtual void synchronize(Serializer &s);
- void subB1A76(int arg1, int arg2, int arg3, int arg4, int arg5);
- void subB1B27();
+ void setupSlider(int incrAmount, int xp, int ys, int height, int thumbHeight);
+ void calculateSlider();
- virtual void remove();
virtual void process(Event &event);
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class Button : public SceneActor {
public:
- int _fieldA4;
+ int _buttonId;
- Actor5();
+ Button();
virtual void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Actor4 _actor4;
- Actor5 _actor5;
- Actor5 _actor6;
- Actor5 _actor7;
+ NamedHotspot _background;
+ NamedHotspot _redLightsDescr;
+ NamedHotspot _greenLights;
+ NamedHotspot _frontView;
+ NamedHotspot _rearView;
+ SceneActor _scannerIcon;
+ SceneActor _redLights;
+ SceneActor _radarSweep;
+ SpeedSlider _speedSlider;
+ Button _forwardButton;
+ Button _backwardButton;
+ Button _exitButton;
SequenceManager _sequenceManager;
PaletteRotation *_rotation;
- int _field412;
- int _field413;
- int _field415;
- int _field417;
- int _field419;
- int _field41B;
- int _field41D;
+ int _direction;
+ int _speedCurrent;
+ int _speed;
+ int _speedDelta;
+ int _rotationSegment;
+ int _rotationSegCurrent;
+ int _newRotation;
Scene1750();
virtual void synchronize(Serializer &s);
@@ -828,47 +816,47 @@ public:
};
class Scene1800 : public SceneExt {
- class Hotspot5 : public NamedHotspot {
+ class Background : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class Lever : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class Doors : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor8 : public SceneActor {
+ class PassengerDoor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- int _field412;
+ int _locationMode;
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- Hotspot5 _item5;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
- Actor8 _actor8;
- Actor8 _actor9;
- Exit1 _exit1;
+ NamedHotspot _elevator;
+ NamedHotspot _elevatorContents;
+ NamedHotspot _surface;
+ NamedHotspot _secBackground;
+ Background _background;
+ SceneActor _playerShadow;
+ SceneActor _companion;
+ SceneActor _companionShadow;
+ SceneActor _leftStaircase;
+ SceneActor _rightStaircase;
+ Lever _lever;
+ Doors _doors;
+ PassengerDoor _leftDoor;
+ PassengerDoor _rightDoor;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
Scene1800();
@@ -880,44 +868,44 @@ public:
};
class Scene1850 : public SceneExt {
- class Hotspot2 : public NamedHotspot {
+ class Button : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class Robot : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class Door : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor8 : public SceneActor {
+ class DisplayScreen : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
public:
- int _field412;
- int _field414;
- int _field416;
- int _field418;
- Common::Point _field41A;
- int _field41E;
+ int _sceneMode;
+ int _shadeCountdown;
+ int _shadeDirection;
+ bool _shadeChanging;
+ Common::Point _playerDest;
+ int _seqNumber;
ScenePalette _palette1;
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- NamedHotspot _item1;
- Hotspot2 _item2;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor6 _actor7;
- Actor8 _actor8;
+ NamedHotspot _background;
+ Button _button;
+ SceneActor _companion;
+ SceneActor _airbag;
+ SceneActor _screen;
+ SceneActor _helmet;
+ Robot _robot;
+ Door _leftDoor;
+ Door _rightDoor;
+ DisplayScreen _displayScreen;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
@@ -932,31 +920,31 @@ public:
};
class Scene1875 : public SceneExt {
- class Actor1875 : public SceneActor {
+ class Button : public SceneActor {
public:
- int _fieldA4;
- int _fieldA6;
+ int _buttonId;
+ bool _buttonDown;
- Actor1875();
- void subB84AB();
- void subB8271(int indx);
+ Button();
+ void doButtonPress();
+ void initButton(int buttonId);
+ virtual Common::String getClassName() { return "Scene1875_Button"; }
void synchronize(Serializer &s);
virtual void process(Event &event);
};
public:
SpeakerQuinn _quinnSpeaker;
SpeakerSeeker _seekerSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Actor1875 _actor4;
- Actor1875 _actor5;
- Actor1875 _actor6;
- Actor1875 _actor7;
- Actor1875 _actor8;
+ NamedHotspot _background;
+ NamedHotspot _screen;
+ SceneActor _map;
+ SceneActor _rimPosition;
+ Button _button1;
+ Button _button2;
+ Button _button3;
+ Button _button4;
+ Button _button5;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -965,30 +953,29 @@ public:
};
class Scene1900 : public SceneExt {
- class Actor2 : public SceneActor {
+ class LiftDoor : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
public:
SpeakerSeeker1900 _seekerSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- SceneActor _actor1;
- BackgroundSceneObject _object1;
- BackgroundSceneObject _object2;
- Actor2 _actor2;
- Actor2 _actor3;
- Exit1 _exit1;
- Exit2 _exit2;
+ NamedHotspot _background;
+ NamedHotspot _elevator;
+ SceneActor _companion;
+ BackgroundSceneObject _leftDoorFrame;
+ BackgroundSceneObject _rightDoorFrame;
+ LiftDoor _leftDoor, _rightDoor;
+ WestExit _westExit;
+ EastExit _eastExit;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
@@ -998,11 +985,11 @@ public:
};
class Scene1925 : public SceneExt {
- class Hotspot2 : public NamedHotspot {
+ class Button : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Hotspot3 : public NamedHotspot {
+ class Ladder : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -1011,30 +998,30 @@ class Scene1925 : public SceneExt {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class ExitDown : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit4 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- Hotspot2 _item2;
- Hotspot3 _item3;
- SceneActor _actor1;
+ NamedHotspot _background;
+ Button _button;
+ Ladder _ladder;
+ SceneActor _door;
ExitUp _exitUp;
- Exit2 _exit2;
- Exit3 _exit3;
- Exit4 _exit4;
+ ExitDown _exitDown;
+ WestExit _westExit;
+ EastExit _eastExit;
SequenceManager _sequenceManager;
- int _field9B8;
+ int _newSceneMode;
int _levelResNum[5];
Scene1925();
@@ -1047,16 +1034,16 @@ public:
};
class Scene1945 : public SceneExt {
- class Hotspot3 : public NamedHotspot {
+ class Ice : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Hotspot4 : public NamedHotspot {
+ class Ladder : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Gunpowder : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -1065,26 +1052,26 @@ class Scene1945 : public SceneExt {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class CorridorExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- Hotspot3 _item3;
- Hotspot4 _item4;
- SceneActor _actor1;
- SceneActor _actor2;
- Actor3 _actor3;
+ NamedHotspot _hole;
+ NamedHotspot _ice2;
+ Ice _ice;
+ Ladder _ladder;
+ SceneActor _coveringIce;
+ SceneActor _alcoholLamp;
+ Gunpowder _gunpowder;
ExitUp _exitUp;
- Exit2 _exit2;
+ CorridorExit _corridorExit;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
- int _fieldEAA;
- int _fieldEAC;
- CursorType _fieldEAE;
+ int _nextSceneMode1;
+ int _nextSceneMode2;
+ CursorType _lampUsed;
Scene1945();
void synchronize(Serializer &s);
@@ -1095,15 +1082,16 @@ public:
};
class Scene1950 : public SceneExt {
- class Area1: public SceneArea {
+ /* Windows */
+ class KeypadWindow: public ModalWindow {
public:
- class Actor10 : public SceneActor {
+ class KeypadButton : public SceneActor {
public:
- int _fieldA4;
- int _fieldA6;
- int _fieldA8;
+ int _buttonIndex;
+ bool _pressed;
+ bool _toggled;
- Actor10();
+ KeypadButton();
void synchronize(Serializer &s);
void init(int indx);
@@ -1112,130 +1100,124 @@ class Scene1950 : public SceneExt {
};
SceneActor _areaActor;
- Actor10 _arrActor1[16];
+ KeypadButton _buttons[16];
- byte _field20;
- int _fieldB65;
-
- Area1();
- void synchronize(Serializer &s);
+ int _buttonIndex;
+ KeypadWindow();
+ virtual void synchronize(Serializer &s);
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);
+ virtual void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY);
+ virtual void setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
};
- class Hotspot2 : public NamedHotspot {
+ class Keypad : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ /* Actors */
+ class Door : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Scrolls : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Gem : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class Vampire : public SceneActor {
public:
- virtual bool startAction(CursorType action, Event &event);
- };
- class Actor8 : public SceneActor {
- public:
- int _fieldA4;
- int _fieldA6;
- int _fieldA8;
- int _fieldAA;
- int _fieldAC;
- byte _fieldAE;
- byte _fieldAF;
+ Common::Point _deadPosition;
+ int _deltaX;
+ int _deltaY;
+ int _vampireMode;
- Actor8();
+ Vampire();
void synchronize(Serializer &s);
virtual void signal();
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ /* Exits */
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class UpExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit4 : public SceneExit {
+ class DownExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit5 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit6 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit7 : public SceneExit {
+ class ShaftExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit8 : public SceneExit {
+ class DoorExit : public SceneExit {
public:
virtual void changeScene();
};
+private:
+ void initArea();
+ void enterArea();
+ void doButtonPress(int indx);
public:
- NamedHotspot _item1;
- Hotspot2 _item2;
- SceneActor _actor1;
- BackgroundSceneObject _object1;
- Actor2 _actor2;
- Actor3 _actor3;
- SceneActor _actor4;
- Actor5 _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- Actor8 _actor8;
- Area1 _area1;
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
- Exit4 _exit4;
- Exit5 _exit5;
- Exit6 _exit6;
- Exit7 _exit7;
- Exit8 _exit8;
+ NamedHotspot _background;
+ Keypad _keypad;
+ SceneActor _southDoorway;
+ SceneObject _northDoorway;
+ Door _door;
+ Scrolls _scrolls;
+ SceneActor _containmentField;
+ Gem _gem;
+ SceneActor _cube;
+ SceneActor _pulsingLights;
+ Vampire _vampire;
+ KeypadWindow _KeypadWindow;
+ NorthExit _northExit;
+ UpExit _upExit;
+ EastExit _eastExit;
+ DownExit _downExit;
+ SouthExit _southExit;
+ WestExit _westExit;
+ ShaftExit _shaftExit;
+ DoorExit _doorExit;
SequenceManager _sequenceManager;
- int _field412;
- int _field414;
- int _field416;
- Common::Point _field418;
- int _field41C;
+ bool _upExitStyle;
+ bool _removeFlag;
+ bool _vampireActive;
+ Common::Point _vampireDestPos;
+ int _vampireIndex;
Scene1950();
void synchronize(Serializer &s);
- void subBDC1E();
- void subBE59B();
- void subBF4B4(int indx);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void signal();
virtual void process(Event &event);
};
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
index 6a030e5b44..f928f3635c 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
@@ -30,17 +30,19 @@ namespace TsAGE {
namespace Ringworld2 {
/*--------------------------------------------------------------------------
- * Scene 2000 - Ice Maze
+ * Scene 2000 - Spill Mountains
*
*--------------------------------------------------------------------------*/
+
void Scene2000::initPlayer() {
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._player.disableControl();
switch (_mazePlayerMode) {
case 0:
R2_GLOBALS._player.setStrip(5);
- if (_exit1._enabled) {
- if (_exit2._enabled)
+ if (_westExit._enabled) {
+ if (_eastExit._enabled)
R2_GLOBALS._player.setPosition(Common::Point(140, 129));
else
R2_GLOBALS._player.setPosition(Common::Point(20, 129));
@@ -49,77 +51,77 @@ void Scene2000::initPlayer() {
R2_GLOBALS._player.enableControl();
break;
case 1:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2001;
else
_sceneMode = 2021;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 2:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2002;
else
_sceneMode = 2022;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 3:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2000;
else
_sceneMode = 2020;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 4:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2005;
else
_sceneMode = 2025;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 5:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2004;
else
_sceneMode = 2024;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 6:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2009;
else
_sceneMode = 2029;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 7:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2008;
else
_sceneMode = 2028;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 8:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2013;
else
_sceneMode = 2033;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 9:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2012;
else
_sceneMode = 2032;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 10:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2016;
else
_sceneMode = 2036;
setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, NULL);
break;
case 11:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2038;
else
_sceneMode = 2040;
@@ -129,77 +131,80 @@ void Scene2000::initPlayer() {
break;
}
for (int i = 0; i < 11; i++) {
- if (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] == R2_GLOBALS._v56605[3 + i])
- _objList1[i].show();
+ if (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] == R2_GLOBALS._spillLocation[3 + i])
+ _persons[i].show();
}
- if ((R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) && (R2_GLOBALS._v56605[1] == R2_GLOBALS._v56605[2])) {
- _object1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _object1.setup(20, 5, 1);
- _object1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if ((R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER])
+ && (R2_GLOBALS._spillLocation[R2_QUINN] == R2_GLOBALS._spillLocation[R2_SEEKER])) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ // Seeker is in room with Quinn
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _object1.setup(2008, 5, 1);
- _object1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ // Quinn is in room with Seeker
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- if (_exit1._enabled) {
- if (_exit2._enabled)
- _object1.setPosition(Common::Point(180, 128));
+ if (_westExit._enabled) {
+ if (_eastExit._enabled)
+ _companion.setPosition(Common::Point(180, 128));
else
- _object1.setPosition(Common::Point(75, 128));
+ _companion.setPosition(Common::Point(75, 128));
} else
- _object1.setPosition(Common::Point(300, 128));
+ _companion.setPosition(Common::Point(300, 128));
}
}
void Scene2000::initExits() {
- _exit1._enabled = true;
- _exit2._enabled = true;
- _exit3._enabled = false;
- _exit4._enabled = false;
- _exit5._enabled = false;
-
- _exit1._insideArea = false;
- _exit2._insideArea = false;
- _exit3._insideArea = false;
- _exit4._insideArea = false;
- _exit5._insideArea = false;
-
- _exit1._moving = false;
- _exit2._moving = false;
- _exit3._moving = false;
- _exit4._moving = false;
- _exit5._moving = false;
+ _westExit._enabled = true;
+ _eastExit._enabled = true;
+ _southExit._enabled = false;
+ _northExit._enabled = false;
+ _doorExit._enabled = false;
+
+ _westExit._insideArea = false;
+ _eastExit._insideArea = false;
+ _southExit._insideArea = false;
+ _northExit._insideArea = false;
+ _doorExit._insideArea = false;
+
+ _westExit._moving = false;
+ _eastExit._moving = false;
+ _southExit._moving = false;
+ _northExit._moving = false;
+ _doorExit._moving = false;
for (int i = 0; i < 11; i++)
- _objList1[i].hide();
+ _persons[i].hide();
- _object1.remove();
+ _companion.remove();
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex]) {
case 3:
case 10:
case 16:
case 21:
- _exit5._enabled = true;
- _exit5._bounds.set(61, 68, 90, 125);
- _exit5.setDest(Common::Point(92, 129));
- _exit5._cursorNum = EXITCURSOR_W;
+ _doorExit._enabled = true;
+ _doorExit._bounds.set(61, 68, 90, 125);
+ _doorExit.setDest(Common::Point(92, 129));
+ _doorExit._cursorNum = EXITCURSOR_W;
break;
case 4:
case 12:
case 25:
case 34:
- _exit5._enabled = true;
- _exit5._bounds.set(230, 68, 259, 125);
- _exit5.setDest(Common::Point(244, 129));
- _exit5._cursorNum = EXITCURSOR_E;
+ _doorExit._enabled = true;
+ _doorExit._bounds.set(230, 68, 259, 125);
+ _doorExit.setDest(Common::Point(244, 129));
+ _doorExit._cursorNum = EXITCURSOR_E;
break;
default:
break;
}
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] - 1) {
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] - 1) {
case 0:
case 6:
case 13:
@@ -207,7 +212,7 @@ void Scene2000::initExits() {
case 22:
case 27:
case 30:
- _exit1._enabled = false;
+ _westExit._enabled = false;
loadScene(2225);
R2_GLOBALS._walkRegions.load(2225);
if (!_exitingFlag)
@@ -216,10 +221,10 @@ void Scene2000::initExits() {
break;
case 1:
case 19:
- _exit3._enabled = true;
- _exit3._bounds.set(71, 130, 154, 168);
- _exit3.setDest(Common::Point(94, 129));
- _exit3._cursorNum = EXITCURSOR_SE;
+ _southExit._enabled = true;
+ _southExit._bounds.set(71, 130, 154, 168);
+ _southExit.setDest(Common::Point(94, 129));
+ _southExit._cursorNum = EXITCURSOR_SE;
loadScene(2300);
if (!_exitingFlag)
_mazePlayerMode = 0;
@@ -283,8 +288,8 @@ void Scene2000::initExits() {
case 21:
case 26:
loadScene(2200);
- R2_GLOBALS._walkRegions.load(2000);
- _exit2._enabled = false;
+ R2_GLOBALS._walkRegions.load(2200);
+ _eastExit._enabled = false;
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1900)
_mazePlayerMode = 2;
else if (!_exitingFlag)
@@ -294,10 +299,10 @@ void Scene2000::initExits() {
break;
case 7:
case 29:
- _exit4._enabled = true;
- _exit4._bounds.set(138, 83, 211, 125);
- _exit4.setDest(Common::Point(129, 188));
- _exit4._cursorNum = EXITCURSOR_NW;
+ _northExit._enabled = true;
+ _northExit._bounds.set(138, 83, 211, 125);
+ _northExit.setDest(Common::Point(188, 129));
+ _northExit._cursorNum = EXITCURSOR_NW;
loadScene(2250);
R2_GLOBALS._walkRegions.load(2000);
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2500)
@@ -309,10 +314,10 @@ void Scene2000::initExits() {
break;
case 10:
case 25:
- _exit3._enabled = true;
- _exit3._bounds.set(78, 130, 148, 168);
- _exit3.setDest(Common::Point(100, 129));
- _exit3._cursorNum = EXITCURSOR_SE;
+ _southExit._enabled = true;
+ _southExit._bounds.set(78, 130, 148, 168);
+ _southExit.setDest(Common::Point(100, 129));
+ _southExit._cursorNum = EXITCURSOR_SE;
loadScene(2075);
R2_GLOBALS._walkRegions.load(2000);
if (!_exitingFlag)
@@ -320,10 +325,10 @@ void Scene2000::initExits() {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2000;
break;
case 14:
- _exit3._enabled = true;
- _exit3._bounds.set(160, 130, 248, 168);
- _exit3.setDest(Common::Point(225, 129));
- _exit3._cursorNum = EXITCURSOR_SW;
+ _southExit._enabled = true;
+ _southExit._bounds.set(160, 130, 248, 168);
+ _southExit.setDest(Common::Point(225, 129));
+ _southExit._cursorNum = EXITCURSOR_SW;
loadScene(2325);
R2_GLOBALS._walkRegions.load(2000);
if (!_exitingFlag)
@@ -332,10 +337,10 @@ void Scene2000::initExits() {
break;
case 16:
case 31:
- _exit4._enabled = true;
- _exit4._bounds.set(122, 83, 207, 125);
- _exit4.setDest(Common::Point(210, 129));
- _exit4._cursorNum = EXITCURSOR_NW;
+ _northExit._enabled = true;
+ _northExit._bounds.set(122, 83, 207, 125);
+ _northExit.setDest(Common::Point(210, 129));
+ _northExit._cursorNum = EXITCURSOR_NW;
loadScene(2125);
R2_GLOBALS._walkRegions.load(2000);
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2400)
@@ -346,10 +351,10 @@ void Scene2000::initExits() {
R2_GLOBALS._sceneManager._previousScene = 2000;
break;
case 23:
- _exit4._enabled = true;
- _exit4._bounds.set(108, 83, 128, 184);
- _exit4.setDest(Common::Point(135, 129));
- _exit4._cursorNum = CURSOR_INVALID;
+ _northExit._enabled = true;
+ _northExit._bounds.set(108, 83, 184, 125);
+ _northExit.setDest(Common::Point(135, 129));
+ _northExit._cursorNum = EXITCURSOR_NE;
loadScene(2275);
R2_GLOBALS._walkRegions.load(2000);
if (!_exitingFlag)
@@ -357,10 +362,10 @@ void Scene2000::initExits() {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2000;
break;
case 28:
- _exit3._enabled = true;
- _exit3._bounds.set(171, 130, 241, 168);
- _exit3.setDest(Common::Point(218, 129));
- _exit3._cursorNum = EXITCURSOR_SW;
+ _southExit._enabled = true;
+ _southExit._bounds.set(171, 130, 241, 168);
+ _southExit.setDest(Common::Point(218, 129));
+ _southExit._cursorNum = EXITCURSOR_SW;
loadScene(2050);
R2_GLOBALS._walkRegions.load(2000);
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2350)
@@ -391,42 +396,42 @@ void Scene2000::Action1::signal() {
_actionIndex = 1;
Common::Point pt(-20, 127);
NpcMover *mover = new NpcMover();
- scene->_objList1[_state].addMover(mover, &pt, scene);
+ scene->_persons[_state].addMover(mover, &pt, scene);
break;
}
case 1:
- scene->_objList1[_state].setPosition(Common::Point(340, 127));
- --R2_GLOBALS._v56605[4 + _state];
+ scene->_persons[_state].setPosition(Common::Point(340, 127));
+ --R2_GLOBALS._spillLocation[4 + _state];
_actionIndex = 0;
switch (_state - 1) {
case 0:
- if (R2_GLOBALS._v56605[4] == 1)
+ if (R2_GLOBALS._spillLocation[4] == 1)
_actionIndex = 10;
break;
case 2:
- if (R2_GLOBALS._v56605[6] == 7)
+ if (R2_GLOBALS._spillLocation[6] == 7)
_actionIndex = 10;
break;
case 4:
- if (R2_GLOBALS._v56605[8] == 14)
+ if (R2_GLOBALS._spillLocation[8] == 14)
_actionIndex = 10;
break;
case 6:
- if (R2_GLOBALS._v56605[10] == 19)
+ if (R2_GLOBALS._spillLocation[10] == 19)
_actionIndex = 10;
break;
case 7:
- if (R2_GLOBALS._v56605[11] == 23)
+ if (R2_GLOBALS._spillLocation[11] == 23)
_actionIndex = 10;
break;
default:
break;
}
- if (R2_GLOBALS._v56605[3 + _state] == R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex])
- scene->_objList1[_state].show();
+ if (R2_GLOBALS._spillLocation[3 + _state] == R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex])
+ scene->_persons[_state].show();
else
- scene->_objList1[_state].hide();
+ scene->_persons[_state].hide();
signal();
break;
@@ -434,96 +439,96 @@ void Scene2000::Action1::signal() {
_actionIndex = 6;
Common::Point pt(340, 127);
NpcMover *mover = new NpcMover();
- scene->_objList1[_state].addMover(mover, &pt, this);
+ scene->_persons[_state].addMover(mover, &pt, this);
break;
}
case 6:
- scene->_objList1[_state].setPosition(Common::Point(-20, 127));
- ++R2_GLOBALS._v56605[3 + _state];
+ scene->_persons[_state].setPosition(Common::Point(-20, 127));
+ ++R2_GLOBALS._spillLocation[3 + _state];
_actionIndex = 5;
switch (_state - 1) {
case 0:
- if (R2_GLOBALS._v56605[4] == 5)
+ if (R2_GLOBALS._spillLocation[4] == 5)
_actionIndex = 15;
break;
case 2:
- if (R2_GLOBALS._v56605[6] == 13)
+ if (R2_GLOBALS._spillLocation[6] == 13)
_actionIndex = 15;
break;
case 4:
- if (R2_GLOBALS._v56605[8] == 16)
+ if (R2_GLOBALS._spillLocation[8] == 16)
_actionIndex = 15;
break;
case 6:
- if (R2_GLOBALS._v56605[10] == 22)
+ if (R2_GLOBALS._spillLocation[10] == 22)
_actionIndex = 15;
break;
case 7:
- if (R2_GLOBALS._v56605[11] == 27)
+ if (R2_GLOBALS._spillLocation[11] == 27)
_actionIndex = 15;
break;
default:
break;
}
- if (R2_GLOBALS._v56605[3 + _state] == R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex])
- scene->_objList1[_state].show();
+ if (R2_GLOBALS._spillLocation[3 + _state] == R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex])
+ scene->_persons[_state].show();
else
- scene->_objList1[_state].hide();
+ scene->_persons[_state].hide();
signal();
break;
case 10: {
Common::Point pt(290, 127);
NpcMover *mover = new NpcMover();
- scene->_objList1[_state].addMover(mover, &pt, this);
+ scene->_persons[_state].addMover(mover, &pt, this);
_actionIndex = 11;
break;
}
case 11:
if (_state == 1)
- scene->_objList1[0].setStrip(1);
+ scene->_persons[0].setStrip(1);
else if (_state == 5)
- scene->_objList1[4].setStrip(1);
+ scene->_persons[4].setStrip(1);
setDelay(600);
_actionIndex = 12;
break;
case 12:
if (_state == 1)
- scene->_objList1[0].setStrip(2);
+ scene->_persons[0].setStrip(2);
else if (_state == 5)
- scene->_objList1[4].setStrip(2);
- scene->_objList1[_state].setStrip(1);
+ scene->_persons[4].setStrip(2);
+ scene->_persons[_state].setStrip(1);
_actionIndex = 5;
signal();
break;
case 15:
- if ((R2_GLOBALS._v56605[3 + _state] == 13) || (R2_GLOBALS._v56605[3 + _state] == 22) || (R2_GLOBALS._v56605[3 + _state] == 27)) {
+ if ((R2_GLOBALS._spillLocation[3 + _state] == 13) || (R2_GLOBALS._spillLocation[3 + _state] == 22) || (R2_GLOBALS._spillLocation[3 + _state] == 27)) {
Common::Point pt(30, 127);
NpcMover *mover = new NpcMover();
- scene->_objList1[_state].addMover(mover, &pt, this);
+ scene->_persons[_state].addMover(mover, &pt, this);
_actionIndex = 16;
} else {
Common::Point pt(120, 127);
NpcMover *mover = new NpcMover();
- scene->_objList1[_state].addMover(mover, &pt, this);
+ scene->_persons[_state].addMover(mover, &pt, this);
_actionIndex = 16;
}
break;
case 16:
if (_state == 1)
- scene->_objList1[2].setStrip(2);
+ scene->_persons[2].setStrip(2);
else if (_state == 8)
- scene->_objList1[9].setStrip(2);
+ scene->_persons[9].setStrip(2);
setDelay(600);
_actionIndex = 17;
break;
case 17:
if (_state == 1)
- scene->_objList1[2].setStrip(1);
+ scene->_persons[2].setStrip(1);
else if (_state == 8)
- scene->_objList1[9].setStrip(1);
- scene->_objList1[_state].setStrip(2);
+ scene->_persons[9].setStrip(1);
+ scene->_persons[_state].setStrip(2);
_actionIndex = 0;
break;
case 99:
@@ -534,26 +539,24 @@ void Scene2000::Action1::signal() {
}
}
-void Scene2000::Exit1::changeScene() {
+void Scene2000::WestExit::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
scene->_exitingFlag = true;
- scene->_sceneMode = 0;
+ _enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 10;
Common::Point pt(-10, 129);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, scene);
-
- scene->setAction(&scene->_sequenceManager, scene, 206, &R2_GLOBALS._player, NULL);
}
-void Scene2000::Exit2::changeScene() {
+void Scene2000::EastExit::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
scene->_exitingFlag = true;
- scene->_sceneMode = 0;
+ _enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 11;
@@ -562,38 +565,38 @@ void Scene2000::Exit2::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene2000::Exit3::changeScene() {
+void Scene2000::SouthExit::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
scene->_exitingFlag = true;
- scene->_sceneMode = 0;
+ _enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 12;
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex]) {
case 2:
scene->_mazePlayerMode = 4;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 8;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 8;
break;
case 11:
scene->_mazePlayerMode = 6;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 17;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 17;
break;
case 15:
scene->_mazePlayerMode = 8;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 24;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 24;
break;
case 20:
scene->_mazePlayerMode = 4;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 30;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 30;
break;
case 26:
scene->_mazePlayerMode = 6;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 32;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 32;
break;
case 29:
scene->_mazePlayerMode = 11;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 29;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 29;
break;
default:
break;
@@ -601,25 +604,25 @@ void Scene2000::Exit3::changeScene() {
switch (scene->_mazePlayerMode) {
case 4:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2003, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2023, &R2_GLOBALS._player, NULL);
break;
case 6:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2007, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2027, &R2_GLOBALS._player, NULL);
break;
case 8:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2011, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2031, &R2_GLOBALS._player, NULL);
break;
case 11:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->_sceneMode = 2039;
else
scene->_sceneMode = 2041;
@@ -630,34 +633,35 @@ void Scene2000::Exit3::changeScene() {
break;
}
}
-void Scene2000::Exit4::changeScene() {
+
+void Scene2000::NorthExit::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
scene->_exitingFlag = true;
- scene->_sceneMode = 0;
+ _enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 13;
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex]) {
case 8:
scene->_mazePlayerMode = 5;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 2;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 2;
break;
case 17:
scene->_mazePlayerMode = 7;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 11;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 11;
break;
case 24:
scene->_mazePlayerMode = 9;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 15;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 15;
break;
case 30:
scene->_mazePlayerMode = 5;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 20;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 20;
break;
case 32:
scene->_mazePlayerMode = 7;
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 26;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 26;
break;
default:
break;
@@ -665,19 +669,19 @@ void Scene2000::Exit4::changeScene() {
switch (scene->_mazePlayerMode) {
case 5:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2006, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2026, &R2_GLOBALS._player, NULL);
break;
case 7:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2010, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2030, &R2_GLOBALS._player, NULL);
break;
case 9:
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2014, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2034, &R2_GLOBALS._player, NULL);
@@ -687,66 +691,66 @@ void Scene2000::Exit4::changeScene() {
}
}
-void Scene2000::Exit5::changeScene() {
+void Scene2000::DoorExit::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
- scene->_sceneMode = 0;
+ _enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 14;
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex]) {
case 3:
scene->_mazePlayerMode = 1;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2015, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2035, &R2_GLOBALS._player, NULL);
break;
case 4:
scene->_mazePlayerMode = 7;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2017, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2037, &R2_GLOBALS._player, NULL);
break;
case 10:
scene->_mazePlayerMode = 8;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2015, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2035, &R2_GLOBALS._player, NULL);
break;
case 12:
scene->_mazePlayerMode = 3;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2017, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2037, &R2_GLOBALS._player, NULL);
break;
case 16:
scene->_mazePlayerMode = 4;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2015, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2035, &R2_GLOBALS._player, NULL);
break;
case 21:
scene->_mazePlayerMode = 5;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2015, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2035, &R2_GLOBALS._player, NULL);
break;
case 25:
scene->_mazePlayerMode = 2;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2017, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2037, &R2_GLOBALS._player, NULL);
break;
case 34:
scene->_mazePlayerMode = 6;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2017, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2037, &R2_GLOBALS._player, NULL);
@@ -756,29 +760,32 @@ void Scene2000::Exit5::changeScene() {
}
}
-void Scene2000::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
- loadScene(2000);
-
- if (R2_GLOBALS._sceneManager._previousScene != -1) {
- R2_GLOBALS._v56605[1] = 21;
- R2_GLOBALS._v56605[2] = 21;
+Scene2000::Scene2000(): SceneExt() {
+ if (R2_GLOBALS._sceneManager._previousScene == -1) {
+ R2_GLOBALS._spillLocation[R2_QUINN] = 21;
+ R2_GLOBALS._spillLocation[R2_SEEKER] = 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;
+ _mazePlayerMode = 0;
+}
- _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);
- _exit2.setDest(Common::Point(315, 129));
- _exit3.setDetails(Rect(71, 130, 154, 168), EXITCURSOR_S, 2000);
- _exit3.setDest(Common::Point(94, 129));
- _exit4.setDetails(Rect(138, 83, 211, 125), EXITCURSOR_N, 2000);
- _exit4.setDest(Common::Point(188, 128));
- _exit5.setDetails(Rect(61, 68, 90, 125), EXITCURSOR_W, 2000);
- _exit5.setDest(Common::Point(92, 129));
+void Scene2000::postInit(SceneObjectList *OwnerList) {
+ _westExit.setDetails(Rect(0, 100, 14, 140), EXITCURSOR_W, 2000);
+ _westExit.setDest(Common::Point(14, 129));
+ _eastExit.setDetails(Rect(305, 100, 320, 140), EXITCURSOR_E, 2000);
+ _eastExit.setDest(Common::Point(315, 129));
+ _southExit.setDetails(Rect(71, 130, 154, 168), EXITCURSOR_S, 2000);
+ _southExit.setDest(Common::Point(94, 129));
+ _northExit.setDetails(Rect(138, 83, 211, 125), EXITCURSOR_N, 2000);
+ _northExit.setDest(Common::Point(188, 129));
+ _doorExit.setDetails(Rect(61, 68, 90, 125), EXITCURSOR_W, 2000);
+ _doorExit.setDest(Common::Point(92, 129));
R2_GLOBALS._sound1.play(200);
initExits();
@@ -787,7 +794,7 @@ void Scene2000::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(2008, 3, 1);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -802,92 +809,92 @@ void Scene2000::postInit(SceneObjectList *OwnerList) {
_action5._state = 3;
for (int i = 0; i < 11; i++)
- _objList1[i].postInit();
+ _persons[i].postInit();
- _objList1[0].setVisage(2000);
- _objList1[0].setStrip(2);
- _objList1[0].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[0].setVisage(2000);
+ _persons[0].setStrip(2);
+ _persons[0].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[1].setVisage(2001);
- _objList1[1].setStrip(2);
- _objList1[1].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[1].setVisage(2001);
+ _persons[1].setStrip(2);
+ _persons[1].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[2].setVisage(2003);
- _objList1[2].setStrip(1);
- _objList1[2].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[2].setVisage(2003);
+ _persons[2].setStrip(1);
+ _persons[2].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[3].setVisage(2007);
- _objList1[3].setStrip(2);
- _objList1[3].setDetails(2001, 12, -1, -1, 1, (SceneItem *)NULL);
+ _persons[3].setVisage(2007);
+ _persons[3].setStrip(2);
+ _persons[3].setDetails(2001, 12, -1, -1, 1, (SceneItem *)NULL);
- _objList1[4].setVisage(2004);
- _objList1[4].setStrip(2);
- _objList1[4].setDetails(2001, 19, -1, -1, 1, (SceneItem *)NULL);
+ _persons[4].setVisage(2004);
+ _persons[4].setStrip(2);
+ _persons[4].setDetails(2001, 19, -1, -1, 1, (SceneItem *)NULL);
- _objList1[5].setVisage(2003);
- _objList1[5].setStrip(2);
- _objList1[5].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[5].setVisage(2003);
+ _persons[5].setStrip(2);
+ _persons[5].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[6].setVisage(2000);
- _objList1[6].setStrip(1);
- _objList1[6].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[6].setVisage(2000);
+ _persons[6].setStrip(1);
+ _persons[6].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[7].setVisage(2000);
- _objList1[7].setStrip(2);
- _objList1[7].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[7].setVisage(2000);
+ _persons[7].setStrip(2);
+ _persons[7].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[8].setVisage(2000);
- _objList1[8].setStrip(2);
- _objList1[8].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _persons[8].setVisage(2000);
+ _persons[8].setStrip(2);
+ _persons[8].setDetails(2001, 0, -1, -1, 1, (SceneItem *)NULL);
- _objList1[9].setVisage(2006);
- _objList1[9].setStrip(1);
- _objList1[9].setDetails(2001, 6, -1, -1, 1, (SceneItem *)NULL);
+ _persons[9].setVisage(2006);
+ _persons[9].setStrip(1);
+ _persons[9].setDetails(2001, 6, -1, -1, 1, (SceneItem *)NULL);
- _objList1[10].setVisage(2007);
- _objList1[10].setStrip(1);
- _objList1[10].setDetails(2001, 12, -1, -1, 1, (SceneItem *)NULL);
+ _persons[10].setVisage(2007);
+ _persons[10].setStrip(1);
+ _persons[10].setDetails(2001, 12, -1, -1, 1, (SceneItem *)NULL);
for (int i = 0; i < 11; i++) {
- _objList1[i].animate(ANIM_MODE_1, NULL);
- _objList1[i]._moveDiff.x = 3;
- _objList1[i]._moveRate = 8;
- _objList1[i].hide();
+ _persons[i].animate(ANIM_MODE_1, NULL);
+ _persons[i]._moveDiff.x = 3;
+ _persons[i]._moveRate = 8;
+ _persons[i].hide();
switch (i - 1) {
case 0:
- if (R2_GLOBALS._v56605[3 + i] == 1)
- ++R2_GLOBALS._v56605[3 + i];
- else if (R2_GLOBALS._v56605[3 + i] == 5)
- --R2_GLOBALS._v56605[3 + i];
+ if (R2_GLOBALS._spillLocation[3 + i] == 1)
+ ++R2_GLOBALS._spillLocation[3 + i];
+ else if (R2_GLOBALS._spillLocation[3 + i] == 5)
+ --R2_GLOBALS._spillLocation[3 + i];
break;
case 2:
- if (R2_GLOBALS._v56605[3 + i] == 7)
- ++R2_GLOBALS._v56605[3 + i];
- else if (R2_GLOBALS._v56605[3 + i] == 13)
- --R2_GLOBALS._v56605[3 + i];
+ if (R2_GLOBALS._spillLocation[3 + i] == 7)
+ ++R2_GLOBALS._spillLocation[3 + i];
+ else if (R2_GLOBALS._spillLocation[3 + i] == 13)
+ --R2_GLOBALS._spillLocation[3 + i];
break;
case 4:
- if (R2_GLOBALS._v56605[3 + i] == 14)
- ++R2_GLOBALS._v56605[3 + i];
- else if (R2_GLOBALS._v56605[3 + i] == 16)
- --R2_GLOBALS._v56605[3 + i];
+ if (R2_GLOBALS._spillLocation[3 + i] == 14)
+ ++R2_GLOBALS._spillLocation[3 + i];
+ else if (R2_GLOBALS._spillLocation[3 + i] == 16)
+ --R2_GLOBALS._spillLocation[3 + i];
break;
case 6:
- if (R2_GLOBALS._v56605[3 + i] == 19)
- ++R2_GLOBALS._v56605[3 + i];
- else if (R2_GLOBALS._v56605[3 + i] == 22)
- --R2_GLOBALS._v56605[3 + i];
+ if (R2_GLOBALS._spillLocation[3 + i] == 19)
+ ++R2_GLOBALS._spillLocation[3 + i];
+ else if (R2_GLOBALS._spillLocation[3 + i] == 22)
+ --R2_GLOBALS._spillLocation[3 + i];
break;
case 8:
- if (R2_GLOBALS._v56605[3 + i] == 23)
- ++R2_GLOBALS._v56605[3 + i];
- else if (R2_GLOBALS._v56605[3 + i] == 27)
- --R2_GLOBALS._v56605[3 + i];
+ if (R2_GLOBALS._spillLocation[3 + i] == 23)
+ ++R2_GLOBALS._spillLocation[3 + i];
+ else if (R2_GLOBALS._spillLocation[3 + i] == 27)
+ --R2_GLOBALS._spillLocation[3 + i];
break;
default:
break;
}
- switch (R2_GLOBALS._v56605[3 + i] - 1) {
+ switch (R2_GLOBALS._spillLocation[3 + i] - 1) {
case 0:
case 6:
case 13:
@@ -895,31 +902,34 @@ void Scene2000::postInit(SceneObjectList *OwnerList) {
case 22:
case 27:
case 30:
- _objList1[i].setPosition(Common::Point(265, 127));
+ _persons[i].setPosition(Common::Point(265, 127));
break;
case 5:
case 12:
case 17:
case 21:
case 26:
- _objList1[i].setPosition(Common::Point(55, 127));
+ _persons[i].setPosition(Common::Point(55, 127));
break;
default:
- _objList1[i].setPosition(Common::Point(160, 127));
+ _persons[i].setPosition(Common::Point(160, 127));
break;
}
}
- _objList1[1].setAction(&_action2);
- _objList1[3].setAction(&_action5);
- _objList1[5].setAction(&_action4);
- _objList1[8].setAction(&_action1);
+ _persons[1].setAction(&_action2);
+ _persons[3].setAction(&_action5);
+ _persons[5].setAction(&_action4);
+ _persons[8].setAction(&_action1);
initPlayer();
- _item1.setDetails(Rect(0, 0, 320, 200), 2000, 0, -1, 23, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2000, 0, -1, 23, 1, NULL);
+
+ SceneExt::postInit();
}
void Scene2000::remove() {
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._sound1.fadeOut(NULL);
SceneExt::remove();
}
@@ -927,17 +937,19 @@ void Scene2000::remove() {
void Scene2000::signal() {
switch (_sceneMode) {
case 10:
- if (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] == 6)
+ // Leaving left-hand side of scene
+ if (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] == 6)
g_globals->_sceneManager.changeScene(1900);
else {
_mazePlayerMode = 1;
- --R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex];
+ --R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex];
initExits();
initPlayer();
}
break;
case 11:
- switch (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex]) {
+ // Leaving right-hand side of scene
+ switch (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex]) {
case 5:
g_globals->_sceneManager.changeScene(1900);
break;
@@ -949,7 +961,7 @@ void Scene2000::signal() {
break;
default:
_mazePlayerMode = 2;
- ++R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex];
+ ++R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex];
initExits();
initPlayer();
break;
@@ -957,6 +969,7 @@ void Scene2000::signal() {
break;
case 12:
case 13:
+ // Top/bottom scene exits
initExits();
initPlayer();
break;
@@ -987,9 +1000,7 @@ void Scene2000::signal() {
g_globals->_sceneManager.changeScene(2535);
break;
default:
- if (R2_GLOBALS._v56AAB != 0)
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
break;
@@ -998,6 +1009,7 @@ void Scene2000::signal() {
g_globals->_sceneManager.changeScene(2350);
break;
default:
+ R2_GLOBALS._player.enableControl();
break;
}
}
@@ -1026,20 +1038,21 @@ void Scene2000::synchronize(Serializer &s) {
* Scene 2350 - Balloon Launch Platform
*
*--------------------------------------------------------------------------*/
-bool Scene2350::Actor2::startAction(CursorType action, Event &event) {
+
+bool Scene2350::Companion::startAction(CursorType action, Event &event) {
if (action != R2_SENSOR_PROBE)
return(SceneActor::startAction(action, event));
return true;
}
-bool Scene2350::Actor3::startAction(CursorType action, Event &event) {
- Scene2350 *scene = (Scene2350 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2350::Balloon::startAction(CursorType action, Event &event) {
if ((action == R2_REBREATHER_TANK) && (R2_GLOBALS.getFlag(74))) {
+ Scene2350 *scene = (Scene2350 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
+ scene->_person.postInit();
scene->_sceneMode = 2355;
- scene->setAction(&scene->_sequenceManager, scene, 2355, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2355, &R2_GLOBALS._player, &scene->_person, NULL);
return true;
}
@@ -1048,10 +1061,11 @@ bool Scene2350::Actor3::startAction(CursorType action, Event &event) {
void Scene2350::ExitUp::changeScene() {
Scene2350 *scene = (Scene2350 *)R2_GLOBALS._sceneManager._scene;
+ _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
scene->_sceneMode = 12;
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 2350, &R2_GLOBALS._player, NULL);
else
scene->setAction(&scene->_sequenceManager, scene, 2352, &R2_GLOBALS._player, NULL);
@@ -1077,7 +1091,7 @@ void Scene2350::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_quinnSpeaker);
if (R2_GLOBALS._sceneManager._previousScene == -1)
- R2_GLOBALS._player._characterScene[2] = 2350;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 2350;
_exitUp.setDetails(Rect(25, 83, 93, 125), EXITCURSOR_NW, 2350);
_exitUp.setDest(Common::Point(80, 129));
@@ -1087,7 +1101,7 @@ void Scene2350::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(2008, 3, 1);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -1095,39 +1109,39 @@ void Scene2350::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
}
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor2.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor2.setup(20, 5, 1);
- _actor2.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor2.setup(2008, 5, 1);
- _actor2.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor2.setPosition(Common::Point(135, 128));
+ _companion.setPosition(Common::Point(135, 128));
}
- _actor3.postInit();
- _actor4.postInit();
+ _balloon.postInit();
+ _harness.postInit();
- if (R2_INVENTORY.getObjectScene(20) == 2350) {
- _actor3.hide();
- _actor4.hide();
+ if (R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 2350) {
+ _balloon.hide();
+ _harness.hide();
} else {
- _actor3.setup(2350, 0, 1);
- _actor3.setPosition(Common::Point(197, 101));
- _actor3.setDetails(2000, 12, -1, -1, 1, (SceneItem *)NULL);
- _actor3.fixPriority(10);
- _actor4.setup(2350, 1, 2);
- _actor4.setPosition(Common::Point(199, 129));
- _actor4.setDetails(2000, 12, -1, -1, 1, (SceneItem *)NULL);
- _actor4.fixPriority(10);
- }
- _item1.setDetails(Rect(0, 0, 320, 200), 2000, 9, -1, -1, 1, NULL);
+ _balloon.setup(2350, 0, 1);
+ _balloon.setPosition(Common::Point(197, 101));
+ _balloon.setDetails(2000, 12, -1, -1, 1, (SceneItem *)NULL);
+ _balloon.fixPriority(10);
+ _harness.setup(2350, 1, 2);
+ _harness.setPosition(Common::Point(199, 129));
+ _harness.setDetails(2000, 12, -1, -1, 1, (SceneItem *)NULL);
+ _harness.fixPriority(10);
+ }
+ _background.setDetails(Rect(0, 0, 320, 200), 2000, 9, -1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
- if (R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] == 34) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] != 34) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_sceneMode = 2351;
else
_sceneMode = 2353;
@@ -1156,11 +1170,11 @@ void Scene2350::remove() {
void Scene2350::signal() {
switch (_sceneMode) {
case 11:
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 34;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 34;
g_globals->_sceneManager.changeScene(2000);
break;
case 12:
- R2_GLOBALS._v56605[R2_GLOBALS._player._characterIndex] = 29;
+ R2_GLOBALS._spillLocation[R2_GLOBALS._player._characterIndex] = 29;
g_globals->_sceneManager.changeScene(2000);
break;
case 20:
@@ -1169,12 +1183,12 @@ void Scene2350::signal() {
break;
case 21:
R2_GLOBALS._player.disableControl();
- R2_INVENTORY.setObjectScene(36, 1);
+ R2_INVENTORY.setObjectScene(R2_FLUTE, 1);
_sceneMode = 2354;
setAction(&_sequenceManager, this, 2354, &R2_GLOBALS._player, NULL);
break;
case 2354:
- R2_INVENTORY.setObjectScene(20, 2350);
+ R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 2350);
g_globals->_sceneManager.changeScene(2900);
break;
case 2355:
@@ -1188,22 +1202,12 @@ void Scene2350::signal() {
}
}
-void Scene2350::process(Event &event) {
- if ((R2_GLOBALS._player._canWalk) && (event.eventType != EVENT_BUTTON_DOWN) &&
- (R2_GLOBALS._events.getCursor() == CURSOR_CROSSHAIRS)){
- Common::Point pt(event.mousePos.x, 129);
- PlayerMover *mover = new PlayerMover();
- R2_GLOBALS._player.addMover(mover, &pt);
- event.handled = true;
- }
- Scene::process(event);
-}
-
/*--------------------------------------------------------------------------
- * Scene 2400 - Ice Maze: Large empty room
+ * Scene 2400 - Spill Mountains: Large empty room
*
*--------------------------------------------------------------------------*/
-void Scene2400::Exit1::changeScene() {
+
+void Scene2400::WestExit::changeScene() {
Scene2400 *scene = (Scene2400 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
@@ -1215,7 +1219,7 @@ void Scene2400::Exit1::changeScene() {
}
-void Scene2400::Exit2::changeScene() {
+void Scene2400::EastExit::changeScene() {
Scene2400 *scene = (Scene2400 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
@@ -1229,14 +1233,14 @@ void Scene2400::Exit2::changeScene() {
void Scene2400::postInit(SceneObjectList *OwnerList) {
loadScene(2400);
SceneExt::postInit();
- _exit1.setDetails(Rect(0, 125, 14, 165), EXITCURSOR_W, 2000);
- _exit1.setDest(Common::Point(14, 150));
- _exit2.setDetails(Rect(305, 125, 320, 165), EXITCURSOR_E, 2000);
- _exit2.setDest(Common::Point(315, 150));
+ _westExit.setDetails(Rect(0, 125, 14, 165), EXITCURSOR_W, 2000);
+ _westExit.setDest(Common::Point(14, 150));
+ _eastExit.setDetails(Rect(305, 125, 320, 165), EXITCURSOR_E, 2000);
+ _eastExit.setDest(Common::Point(315, 150));
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._v56605[1] == 16) {
+ if (R2_GLOBALS._spillLocation[R2_QUINN] == 16) {
_sceneMode = 2400;
setAction(&_sequenceManager, this, 2400, &R2_GLOBALS._player, NULL);
} else {
@@ -1248,11 +1252,11 @@ void Scene2400::postInit(SceneObjectList *OwnerList) {
void Scene2400::signal() {
switch (_sceneMode) {
case 10:
- R2_GLOBALS._v56605[1] = 16;
+ R2_GLOBALS._spillLocation[R2_QUINN] = 16;
g_globals->_sceneManager.changeScene(2000);
break;
case 11:
- R2_GLOBALS._v56605[1] = 17;
+ R2_GLOBALS._spillLocation[R2_QUINN] = 17;
g_globals->_sceneManager.changeScene(2000);
break;
default:
@@ -1262,102 +1266,102 @@ void Scene2400::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2425 - Ice Maze:
+ * Scene 2425 - Spill Mountains: The Hall Of Records
*
*--------------------------------------------------------------------------*/
-bool Scene2425::Item1::startAction(CursorType action, Event &event) {
- Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2425::RopeDest1::startAction(CursorType action, Event &event) {
+ if ((action == R2_CURSOR_ROPE) && (!R2_GLOBALS.getFlag(84))) {
+ Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
- if ((action == R2_GUNPOWDER) && (!R2_GLOBALS.getFlag(84))) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2426;
- scene->setAction(&scene->_sequenceManager, scene, 2426, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2426, &R2_GLOBALS._player, &scene->_rope, NULL);
R2_GLOBALS.setFlag(84);
return true;
- } else if (action == R2_GUNPOWDER) {
- R2_GLOBALS._events.setCursor(R2_STEPPING_DISKS);
- R2_GLOBALS._player.enableControl(R2_STEPPING_DISKS);
- return NamedHotspot::startAction(R2_STEPPING_DISKS, event);
+ } else if (action == R2_CURSOR_ROPE) {
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ return NamedHotspot::startAction(CURSOR_USE, event);
} else
return NamedHotspot::startAction(action, event);
}
-bool Scene2425::Item2::startAction(CursorType action, Event &event) {
- Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2425::RopeDest2::startAction(CursorType action, Event &event) {
+ if ((action == R2_CURSOR_ROPE) && (R2_GLOBALS.getFlag(84))) {
+ Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
- if ((action == R2_GUNPOWDER) && (R2_GLOBALS.getFlag(84))) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2427;
- scene->setAction(&scene->_sequenceManager, scene, 2427, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2427, &R2_GLOBALS._player, &scene->_rope, NULL);
R2_GLOBALS.clearFlag(84);
return true;
- } else if (action == R2_GUNPOWDER) {
- R2_GLOBALS._events.setCursor(R2_STEPPING_DISKS);
- R2_GLOBALS._player.enableControl(R2_STEPPING_DISKS);
- return NamedHotspot::startAction(R2_STEPPING_DISKS, event);
+ } else if (action == R2_CURSOR_ROPE) {
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ return NamedHotspot::startAction(CURSOR_USE, event);
} else
return NamedHotspot::startAction(action, event);
}
-bool Scene2425::Item3::startAction(CursorType action, Event &event) {
- Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
-
- if (action != R2_GUNPOWDER)
+bool Scene2425::Crevasse::startAction(CursorType action, Event &event) {
+ if (action != R2_CURSOR_ROPE)
return NamedHotspot::startAction(action, event);
else {
+ Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS.getFlag(84)) {
scene->_sceneMode = 20;
- scene->setAction(&scene->_sequenceManager, scene, 2427, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2427, &R2_GLOBALS._player, &scene->_rope, NULL);
R2_GLOBALS.clearFlag(84);
} else {
scene->_sceneMode = 2425;
- scene->setAction(&scene->_sequenceManager, scene, 2425, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2425, &R2_GLOBALS._player, &scene->_rope, NULL);
}
return true;
}
}
-bool Scene2425::Item4::startAction(CursorType action, Event &event) {
- if (action != R2_GUNPOWDER)
+bool Scene2425::Background::startAction(CursorType action, Event &event) {
+ if (action != R2_CURSOR_ROPE)
return NamedHotspot::startAction(action, event);
else {
- R2_GLOBALS._events.setCursor(R2_STEPPING_DISKS);
- R2_GLOBALS._player.enableControl(R2_STEPPING_DISKS);
- return NamedHotspot::startAction(R2_STEPPING_DISKS, event);
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ return NamedHotspot::startAction(CURSOR_USE, event);
}
}
-bool Scene2425::Actor1::startAction(CursorType action, Event &event) {
- if (action == R2_STEPPING_DISKS) {
- if (R2_GLOBALS._player._characterIndex == 2) {
- R2_GLOBALS._events.setCursor(R2_GUNPOWDER);
+bool Scene2425::Rope::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ R2_GLOBALS._events.setCursor(R2_CURSOR_ROPE);
return true;
} else {
return SceneActor::startAction(action, event);
}
- } else if (R2_GLOBALS._events.getCursor() == R2_GUNPOWDER)
+ } else if (R2_GLOBALS._events.getCursor() == R2_CURSOR_ROPE)
return false;
else
return SceneActor::startAction(action, event);
}
-bool Scene2425::Actor2::startAction(CursorType action, Event &event) {
- if (action != R2_GUNPOWDER)
+bool Scene2425::Pictographs::startAction(CursorType action, Event &event) {
+ if (action != R2_CURSOR_ROPE)
return SceneActor::startAction(action, event);
else {
- R2_GLOBALS._events.setCursor(R2_STEPPING_DISKS);
- R2_GLOBALS._player.enableControl(R2_STEPPING_DISKS);
- return SceneActor::startAction(R2_STEPPING_DISKS, event);
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ return SceneActor::startAction(CURSOR_USE, event);
}
}
-void Scene2425::Exit1::changeScene() {
+void Scene2425::SouthEastExit::changeScene() {
Scene2425 *scene = (Scene2425 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._events.setCursor(R2_NEGATOR_GUN);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 11;
@@ -1376,11 +1380,11 @@ void Scene2425::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._sound1.play(200);
- _exit1.setDetails(Rect(270, 136, 319, 168), EXITCURSOR_SE, 2000);
+ _southEastExit.setDetails(Rect(270, 136, 319, 168), EXITCURSOR_SE, 2000);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -1388,41 +1392,39 @@ void Scene2425::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
}
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor2.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor2.setup(20, 5, 1);
- _actor2.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _pictographs1.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _pictographs1.setup(20, 5, 1);
+ _pictographs1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor2.setup(2008, 5, 1);
- _actor2.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _pictographs1.setup(2008, 5, 1);
+ _pictographs1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor2.setPosition(Common::Point(250, 185));
+ _pictographs1.setPosition(Common::Point(250, 185));
}
- _actor1.postInit();
+ _rope.postInit();
if (R2_GLOBALS._sceneManager._previousScene == 2455)
- _actor1.setup(2426, 1, 1);
+ _rope.setup(2426, 1, 1);
else
- _actor1.setup(2426, 1, 2);
-
- _actor1.setPosition(Common::Point(290, 9));
- _actor1.fixPriority(20);
- _actor1.setDetails(2455, 12, -1, -1, 1, (SceneItem *)NULL);
- _item1.setDetails(Rect(225, 52, 248, 65), 2425, -1, -1, -1, 1, NULL);
- _item2.setDetails(Rect(292, 81, 316, 94), 2425, -1, -1, -1, 1, NULL);
-
-// CHECKME: SceneActor using a SceneItem function??
-// _actor3.setDetails(11, 2425, 3, -1, 6);
- _actor3._sceneRegionId = 11;
- _actor3._resNum = 2425;
- _actor3._lookLineNum = 3;
- _actor3._talkLineNum = -1;
- _actor3._useLineNum = 6;
- g_globals->_sceneItems.push_back(&_actor3);
-
- _item3.setDetails(12, 2425, 7, -1, 9);
- _item4.setDetails(Rect(0, 0, 320, 200), 2425, 0, -1, -1, 1, NULL);
+ _rope.setup(2426, 1, 2);
+
+ _rope.setPosition(Common::Point(290, 9));
+ _rope.fixPriority(20);
+ _rope.setDetails(2455, 12, -1, -1, 1, (SceneItem *)NULL);
+ _ropeDest1.setDetails(Rect(225, 52, 248, 65), 2425, -1, -1, -1, 1, NULL);
+ _ropeDest2.setDetails(Rect(292, 81, 316, 94), 2425, -1, -1, -1, 1, NULL);
+
+ _pictographs2._sceneRegionId = 11;
+ _pictographs2._resNum = 2425;
+ _pictographs2._lookLineNum = 3;
+ _pictographs2._talkLineNum = -1;
+ _pictographs2._useLineNum = 6;
+ g_globals->_sceneItems.push_back(&_pictographs2);
+
+ _crevasse.setDetails(12, 2425, 7, -1, 9);
+ _background.setDetails(Rect(0, 0, 320, 200), 2425, 0, -1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
switch (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) {
@@ -1442,7 +1444,7 @@ void Scene2425::postInit(SceneObjectList *OwnerList) {
break;
case 2455:
_sceneMode = 2428;
- setAction(&_sequenceManager, this, 2428, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2428, &R2_GLOBALS._player, &_rope, NULL);
break;
default:
R2_GLOBALS._player.setPosition(Common::Point(280, 150));
@@ -1465,7 +1467,7 @@ void Scene2425::signal() {
break;
case 20:
_sceneMode = 2425;
- setAction(&_sequenceManager, this, 2425, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2425, &R2_GLOBALS._player, &_rope, NULL);
break;
case 2425:
g_globals->_sceneManager.changeScene(2455);
@@ -1477,43 +1479,43 @@ void Scene2425::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2430 - Ice Maze: Bedroom
+ * Scene 2430 - Spill Mountains: Bedroom
*
*--------------------------------------------------------------------------*/
-bool Scene2430::Actor1::startAction(CursorType action, Event &event) {
+bool Scene2430::Companion::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene2430::Actor2::startAction(CursorType action, Event &event) {
- Scene2430 *scene = (Scene2430 *)R2_GLOBALS._sceneManager._scene;
-
- if ((action != R2_STEPPING_DISKS) || (R2_GLOBALS._player._characterIndex != 2))
+bool Scene2430::GunPowder::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (R2_GLOBALS._player._characterIndex != 2))
return SceneActor::startAction(action, event);
+ Scene2430 *scene = (Scene2430 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2430;
- scene->setAction(&scene->_sequenceManager, scene, 2430, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2430, &R2_GLOBALS._player, &scene->_gunPowder, NULL);
return true;
}
-bool Scene2430::Actor3::startAction(CursorType action, Event &event) {
- Scene2430 *scene = (Scene2430 *)R2_GLOBALS._sceneManager._scene;
-
- if ((action != R2_STEPPING_DISKS) || (R2_GLOBALS._player._characterIndex != 2))
+bool Scene2430::OilLamp::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (R2_GLOBALS._player._characterIndex != 2))
return SceneActor::startAction(action, event);
+ Scene2430 *scene = (Scene2430 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2435;
- scene->setAction(&scene->_sequenceManager, scene, 2435, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2435, &R2_GLOBALS._player, &scene->_oilLamp, NULL);
return true;
}
-void Scene2430::Exit1::changeScene() {
+void Scene2430::SouthExit::changeScene() {
Scene2430 *scene = (Scene2430 *)R2_GLOBALS._sceneManager._scene;
scene->_sceneMode = 0;
- R2_GLOBALS._events.setCursor(R2_NEGATOR_GUN);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 11;
Common::Point pt(108, 200);
@@ -1524,27 +1526,27 @@ void Scene2430::Exit1::changeScene() {
void Scene2430::postInit(SceneObjectList *OwnerList) {
loadScene(2430);
SceneExt::postInit();
- _exit1.setDetails(Rect(68, 155, 147, 168), EXITCURSOR_S, 2000);
- _exit1.setDest(Common::Point(108, 160));
-
- if (R2_INVENTORY.getObjectScene(37) == 2430) {
- _actor2.postInit();
- _actor2.setup(2435, 1, 5);
- _actor2.setPosition(Common::Point(205, 119));
- _actor2.fixPriority(152);
- _actor2.setDetails(2430, 51, -1, 53, 1, (SceneItem *)NULL);
+ _southExit.setDetails(Rect(68, 155, 147, 168), EXITCURSOR_S, 2000);
+ _southExit.setDest(Common::Point(108, 160));
+
+ if (R2_INVENTORY.getObjectScene(R2_GUNPOWDER) == 2430) {
+ _gunPowder.postInit();
+ _gunPowder.setup(2435, 1, 5);
+ _gunPowder.setPosition(Common::Point(205, 119));
+ _gunPowder.fixPriority(152);
+ _gunPowder.setDetails(2430, 51, -1, 53, 1, (SceneItem *)NULL);
}
- if (R2_INVENTORY.getObjectScene(50) == 2435) {
- _actor3.postInit();
- _actor3.setup(2435, 1, 1);
- _actor3.setPosition(Common::Point(31, 65));
- _actor3.setDetails(2430, 48, -1, -1, 1, (SceneItem *)NULL);
+ if (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_3) == 2435) {
+ _oilLamp.postInit();
+ _oilLamp.setup(2435, 1, 1);
+ _oilLamp.setPosition(Common::Point(31, 65));
+ _oilLamp.setDetails(2430, 48, -1, -1, 1, (SceneItem *)NULL);
}
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -1553,34 +1555,32 @@ void Scene2430::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._player.setPosition(Common::Point(100, 200));
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(189, 137));
- R2_GLOBALS._walkRegions.enableRegion(4);
- }
-
- _item2.setDetails(Rect(11, 30, 37, 45), 2430, 3, -1, 5, 1, NULL);
- _item3.setDetails(Rect(9, 58, 63, 92), 2430, 6, -1, -1, 1, NULL);
- _item4.setDetails(Rect(20, 89, 127, 107), 2430, 9, -1, 11, 1, NULL);
- _item5.setDetails(Rect(49, 7, 60, 27), 2430, 12, 13, 14, 1, NULL);
- _item6.setDetails(Rect(69, 10, 95, 72), 2430, 15, -1, 14, 1, NULL);
- _item10.setDetails(Rect(198, 4, 222, 146), 2430, 30, 31, 32, 1, NULL);
- _item7.setDetails(Rect(155, 40, 304, 120), 2430, 21, -1, 23, 1, NULL);
- _item8.setDetails(Rect(249, 3, 261, 39), 2430, 24, 25, -1, 1, NULL);
- _item9.setDetails(Rect(279, 13, 305, 34), 2430, 33, -1, 18, 1, NULL);
- // CHECKME: initialized for the 2nd time??
- _item2.setDetails(Rect(11, 30, 37, 45), 2430, 33, -1, 18, 1, NULL);
- _item11.setDetails(Rect(116, 104, 148, 111), 2430, 39, -1, -1, 1, NULL);
- _item12.setDetails(Rect(66, 77, 84, 83), 2430, 39, -1, -1, 1, NULL);
- _item13.setDetails(Rect(117, 118, 201, 141), 2430, 9, -1, 11, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+ _companion.setPosition(Common::Point(189, 137));
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ }
+
+ _furnishings.setDetails(Rect(9, 58, 63, 92), 2430, 6, -1, -1, 1, NULL);
+ _rug1.setDetails(Rect(20, 89, 127, 107), 2430, 9, -1, 11, 1, NULL);
+ _mirror.setDetails(Rect(49, 7, 60, 27), 2430, 12, 13, 14, 1, NULL);
+ _garments.setDetails(Rect(69, 10, 95, 72), 2430, 15, -1, 14, 1, NULL);
+ _post.setDetails(Rect(198, 4, 222, 146), 2430, 30, 31, 32, 1, NULL);
+ _bed.setDetails(Rect(155, 40, 304, 120), 2430, 21, -1, 23, 1, NULL);
+ _towel.setDetails(Rect(249, 3, 261, 39), 2430, 24, 25, -1, 1, NULL);
+ _bottles1.setDetails(Rect(279, 13, 305, 34), 2430, 33, -1, 18, 1, NULL);
+ _bottles2.setDetails(Rect(11, 30, 37, 45), 2430, 33, -1, 18, 1, NULL);
+ _clothesPile1.setDetails(Rect(116, 104, 148, 111), 2430, 39, -1, -1, 1, NULL);
+ _clothesPile2.setDetails(Rect(66, 77, 84, 83), 2430, 39, -1, -1, 1, NULL);
+ _rug2.setDetails(Rect(117, 118, 201, 141), 2430, 9, -1, 11, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2430;
@@ -1600,12 +1600,12 @@ void Scene2430::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 2430:
- _actor2.remove();
+ _gunPowder.remove();
R2_INVENTORY.setObjectScene(R2_GUNPOWDER, 2);
R2_GLOBALS._player.enableControl();
break;
case 2435:
- _actor3.remove();
+ _oilLamp.remove();
R2_INVENTORY.setObjectScene(R2_ALCOHOL_LAMP_3, 2);
R2_GLOBALS._player.enableControl();
break;
@@ -1616,14 +1616,15 @@ void Scene2430::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2435 - Ice Maze: Throne room
+ * Scene 2435 - Spill Mountains: Throne room
*
*--------------------------------------------------------------------------*/
-bool Scene2435::Actor1::startAction(CursorType action, Event &event) {
+
+bool Scene2435::Companion::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene2435::Actor2::startAction(CursorType action, Event &event) {
+bool Scene2435::Astor::startAction(CursorType action, Event &event) {
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -1644,7 +1645,7 @@ bool Scene2435::Actor2::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 20;
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
- if ((R2_GLOBALS._player._characterIndex == 1) || (R2_GLOBALS.getFlag(82))) {
+ if ((R2_GLOBALS._player._characterIndex == R2_QUINN) || (R2_GLOBALS.getFlag(82))) {
scene->_stripManager.start(605, scene);
return true;
} else if (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2) {
@@ -1660,11 +1661,11 @@ bool Scene2435::Actor2::startAction(CursorType action, Event &event) {
}
}
-void Scene2435::Exit1::changeScene() {
+void Scene2435::SouthExit::changeScene() {
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._events.setCursor(R2_NEGATOR_GUN);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 11;
Common::Point pt(175, 200);
@@ -1680,38 +1681,40 @@ void Scene2435::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
_stripManager.addSpeaker(&_pharishaSpeaker);
- _exit1.setDetails(Rect(142, 155, 207, 167), EXITCURSOR_S, 2000);
- _exit1.setDest(Common::Point(175, 160));
- _actor2.postInit();
- _actor2.setup(2005, 3, 1);
- _actor2.setPosition(Common::Point(219, 106));
- _actor2.setDetails(2001, 25, 26, -1, 1, (SceneItem *)NULL);
+ _southExit.setDetails(Rect(142, 155, 207, 167), EXITCURSOR_S, 2000);
+ _southExit.setDest(Common::Point(175, 160));
+ _astor.postInit();
+ _astor.setup(2005, 3, 1);
+ _astor.setPosition(Common::Point(219, 106));
+ _astor.setDetails(2001, 25, 26, -1, 1, (SceneItem *)NULL);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
R2_GLOBALS._player.setVisage(20);
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
}
- R2_GLOBALS._player.setPosition(Common::Point(715, 200));
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ R2_GLOBALS._player.setPosition(Common::Point(175, 200));
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(107, 145));
- R2_GLOBALS._walkRegions.enableRegion(2);
+ _companion.setPosition(Common::Point(107, 145));
+ R2_GLOBALS._walkRegions.disableRegion(2);
}
- _item2.setDetails(Rect(52, 44, 96, 82), 2430, 3, -1, 5, 1, NULL);
- _item3.setDetails(Rect(117, 36, 161, 74), 2430, 3, -1, 5, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+ _leftWindow.setDetails(Rect(52, 44, 96, 82), 2430, 3, -1, 5, 1, NULL);
+ _rightWindow.setDetails(Rect(117, 36, 161, 74), 2430, 3, -1, 5, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
_sceneMode = 10;
@@ -1729,7 +1732,7 @@ void Scene2435::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.enableControl();
}
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2435;
- R2_GLOBALS._v56605[1 + R2_GLOBALS._player._characterIndex] = 12;
+ R2_GLOBALS._spillLocation[1 + R2_GLOBALS._player._characterIndex] = 12;
}
void Scene2435::remove() {
@@ -1746,27 +1749,28 @@ void Scene2435::signal() {
R2_GLOBALS._player.enableControl(CURSOR_TALK);
break;
case 30:
- R2_GLOBALS._player._characterScene[1] = 2435;
- R2_GLOBALS._player._characterScene[2] = 2435;
- R2_GLOBALS._player._oldCharacterScene[1] = 2435;
- R2_GLOBALS._player._oldCharacterScene[2] = 2435;
- R2_GLOBALS._v56605[1] = 12;
- R2_GLOBALS._v56605[2] = 12;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 2435;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 2435;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 2435;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 2435;
+ R2_GLOBALS._spillLocation[R2_QUINN] = 12;
+ R2_GLOBALS._spillLocation[R2_SEEKER] = 12;
R2_GLOBALS.setFlag(81);
_sceneMode = 2436;
R2_GLOBALS._player.setStrip(7);
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1)
- _actor1.setVisage(20);
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ _companion.setVisage(20);
else
- _actor1.setVisage(2008);
- setAction(&_sequenceManager, this, 2436, &_actor1, NULL);
+ _companion.setVisage(2008);
+ setAction(&_sequenceManager, this, 2436, &_companion, NULL);
break;
case 2436:
- R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(2);
_sceneMode = 20;
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
_stripManager.start(709, this);
+ break;
default:
R2_GLOBALS._player.enableControl();
break;
@@ -1774,28 +1778,28 @@ void Scene2435::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2440 - Ice Maze: Another bedroom
+ * Scene 2440 - Spill Mountains: Another bedroom
*
*--------------------------------------------------------------------------*/
-bool Scene2440::Actor1::startAction(CursorType action, Event &event) {
+bool Scene2440::Companion::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene2440::Actor2::startAction(CursorType action, Event &event) {
- Scene2440 *scene = (Scene2440 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2440::OilLamp::startAction(CursorType action, Event &event) {
+ if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_SEEKER)) {
+ Scene2440 *scene = (Scene2440 *)R2_GLOBALS._sceneManager._scene;
- if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == 2)){
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2440;
- scene->setAction(&scene->_sequenceManager, scene, 2440, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2440, &R2_GLOBALS._player, &scene->_oilLamp, NULL);
return true;
}
return SceneActor::startAction(action, event);
}
-void Scene2440::Exit1::changeScene() {
+void Scene2440::SouthEastExit::changeScene() {
Scene2440 *scene = (Scene2440 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -1811,20 +1815,20 @@ void Scene2440::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
R2_GLOBALS._sound1.play(200);
// Fix exit cursor, the original was using NW
- _exit1.setDetails(Rect(172, 155, 250, 167), EXITCURSOR_SE, 2000);
- _exit1.setDest(Common::Point(210, 160));
- if (R2_INVENTORY.getObjectScene(49) == 2440) {
- _actor2.postInit();
- _actor2.setup(2435, 1, 1);
- _actor2.setPosition(Common::Point(94, 80));
- _actor2.fixPriority(106);
- _actor2.setDetails(2430, 48, -1, -1, 1, (SceneItem *)NULL);
+ _southEastExit.setDetails(Rect(172, 155, 250, 167), EXITCURSOR_SE, 2000);
+ _southEastExit.setDest(Common::Point(210, 160));
+ if (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_2) == 2440) {
+ _oilLamp.postInit();
+ _oilLamp.setup(2435, 1, 1);
+ _oilLamp.setPosition(Common::Point(94, 80));
+ _oilLamp.fixPriority(106);
+ _oilLamp.setDetails(2430, 48, -1, -1, 1, (SceneItem *)NULL);
}
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -1832,25 +1836,25 @@ void Scene2440::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
}
R2_GLOBALS._player.setPosition(Common::Point(210, 200));
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9002, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9002, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(38, 119));
+ _companion.setPosition(Common::Point(38, 119));
}
- _item2.setDetails(Rect(125, 25, 142, 73), 2430, 15, -1, 14, 1, NULL);
- _item3.setDetails(Rect(124, 78, 237, 120), 2430, 36, -1, 38, 1, NULL);
- _item4.setDetails(Rect(250, 3, 265, 133), 2430, 30, 31, 32, 1, NULL);
- _item5.setDetails(Rect(91, 117, 203, 140), 2430, 9, -1, 11, 1, NULL);
- _item6.setDetails(Rect(48, 78, 103, 112), 2430, 6, -1, -1, 1, NULL);
- _item7.setDetails(Rect(48, 31, 73, 52), 2430, 33, -1, 18, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+ _garments.setDetails(Rect(125, 25, 142, 73), 2430, 15, -1, 14, 1, NULL);
+ _bedspread.setDetails(Rect(124, 78, 237, 120), 2430, 36, -1, 38, 1, NULL);
+ _post.setDetails(Rect(250, 3, 265, 133), 2430, 30, 31, 32, 1, NULL);
+ _rug.setDetails(Rect(91, 117, 203, 140), 2430, 9, -1, 11, 1, NULL);
+ _furnishings.setDetails(Rect(48, 78, 103, 112), 2430, 6, -1, -1, 1, NULL);
+ _bottles.setDetails(Rect(48, 31, 73, 52), 2430, 33, -1, 18, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
@@ -1877,8 +1881,8 @@ void Scene2440::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 2440:
- _actor2.remove();
- R2_INVENTORY.setObjectScene(49, 2);
+ _oilLamp.remove();
+ R2_INVENTORY.setObjectScene(R2_ALCOHOL_LAMP_2, 2);
// No break on purpose
default:
R2_GLOBALS._player.enableControl();
@@ -1887,9 +1891,10 @@ void Scene2440::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2445 - Ice Maze:
+ * Scene 2445 - Spill Mountains:
*
*--------------------------------------------------------------------------*/
+
void Scene2445::postInit(SceneObjectList *OwnerList) {
loadScene(2445);
SceneExt::postInit();
@@ -1905,45 +1910,46 @@ void Scene2445::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2450 - Ice Maze: Another bedroom
+ * Scene 2450 - Spill Mountains: Another bedroom
*
*--------------------------------------------------------------------------*/
-bool Scene2450::Actor2::startAction(CursorType action, Event &event) {
- Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2450::Parker::startAction(CursorType action, Event &event) {
+ if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
+ Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
- if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == 1)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2452;
- scene->setAction(&scene->_sequenceManager, scene, 2452, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2452, &R2_GLOBALS._player, &scene->_parker, NULL);
return true;
}
return SceneActor::startAction(action, event);
}
-bool Scene2450::Actor3::startAction(CursorType action, Event &event) {
- Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2450::CareTaker::startAction(CursorType action, Event &event) {
if (action == CURSOR_TALK) {
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._v565AE < 3) {
- ++R2_GLOBALS._v565AE;
+ if (R2_GLOBALS._stripModifier < 3) {
+ Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
+
+ ++R2_GLOBALS._stripModifier;
scene->_sceneMode = 20;
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- if (R2_GLOBALS._player._characterIndex == 1)
- scene->_stripManager.start(699 + (R2_GLOBALS._v565AE * 2), scene);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ scene->_stripManager.start(699 + (R2_GLOBALS._stripModifier * 2), scene);
else
- scene->_stripManager.start(700 + (R2_GLOBALS._v565AE * 2), scene);
+ scene->_stripManager.start(700 + (R2_GLOBALS._stripModifier * 2), scene);
}
- return true;} else {
+ return true;
+ } else {
return SceneActor::startAction(action, event);
}
}
-void Scene2450::Exit1::changeScene() {
- Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
+void Scene2450::SouthWestExit::changeScene() {
+ if ((R2_GLOBALS._player._characterIndex == R2_SEEKER) || (R2_GLOBALS.getFlag(61))) {
+ Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
- if ((R2_GLOBALS._player._characterIndex == 2) || (R2_GLOBALS.getFlag(61))) {
_enabled = false;
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
R2_GLOBALS._player.disableControl();
@@ -1953,7 +1959,7 @@ void Scene2450::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
} else {
_moving = false;
- SceneItem::display(2450, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2450, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
Common::Point pt(60, 140);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, NULL);
@@ -1966,66 +1972,66 @@ void Scene2450::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(200);
if (R2_GLOBALS._sceneManager._previousScene == -1) {
R2_GLOBALS._sceneManager._previousScene = 1900;
- R2_GLOBALS._player._oldCharacterScene[1] = 1900;
- R2_GLOBALS._player._oldCharacterScene[2] = 1900;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1900;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 1900;
}
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
_stripManager.addSpeaker(&_caretakerSpeaker);
if (R2_GLOBALS.getFlag(72)) {
- _exit1.setDetails(Rect(0, 143, 47, 168), EXITCURSOR_SW, 2000);
- _exit1.setDest(Common::Point(10, 160));
+ _southWestExit.setDetails(Rect(0, 143, 47, 168), EXITCURSOR_SW, 2000);
+ _southWestExit.setDest(Common::Point(10, 160));
}
if (!R2_GLOBALS.getFlag(61)) {
- _actor2.postInit();
- _actor2.setVisage(2009);
- _actor2.setPosition(Common::Point(190, 119));
- _actor2.fixPriority(50);
- _actor2.setDetails(2450, 0, -1, -1, 1, (SceneItem *)NULL);
+ _parker.postInit();
+ _parker.setVisage(2009);
+ _parker.setPosition(Common::Point(190, 119));
+ _parker.fixPriority(50);
+ _parker.setDetails(2450, 0, -1, -1, 1, (SceneItem *)NULL);
}
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
switch (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) {
case 1900:
- R2_GLOBALS._v565AE = 0;
- R2_GLOBALS._player._characterScene[1] = 2450;
- R2_GLOBALS._player._characterScene[2] = 2450;
- R2_GLOBALS._player._oldCharacterScene[1] = 2450;
- R2_GLOBALS._player._oldCharacterScene[2] = 2450;
+ R2_GLOBALS._stripModifier = 0;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 2450;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 2450;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 2450;
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 2450;
R2_GLOBALS._player.setup(2450, 1, 1);
R2_GLOBALS._player.setPosition(Common::Point(126, 101));
setAction(&_sequenceManager, this, 2450, &R2_GLOBALS._player, NULL);
break;
case 2000:
_sceneMode = 2451;
- if (R2_GLOBALS._player._characterIndex == 1) {
- if (R2_GLOBALS._player._characterScene[2] == 2450) {
- _actor1.postInit();
- _actor1.setup(20, 6, 1);
- _actor1.setPosition(Common::Point(240, 120));
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ if (R2_GLOBALS._player._characterScene[R2_SEEKER] == 2450) {
+ _companion.postInit();
+ _companion.setup(20, 6, 1);
+ _companion.setPosition(Common::Point(240, 120));
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
}
setAction(&_sequenceManager, this, 2451, &R2_GLOBALS._player, NULL);
} else {
- R2_GLOBALS._player._oldCharacterScene[2] = 2450;
- R2_GLOBALS._player._characterScene[2] = 2450;
- if (R2_GLOBALS._player._characterScene[1] == 2450) {
- _actor1.postInit();
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 2450;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 2450;
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == 2450) {
+ _companion.postInit();
if (R2_GLOBALS.getFlag(61))
- _actor1.setup(2008, 6, 1);
+ _companion.setup(2008, 6, 1);
else
- _actor1.setup(10, 6, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
- _actor1.setPosition(Common::Point(106, 111));
+ _companion.setup(10, 6, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setPosition(Common::Point(106, 111));
}
setAction(&_sequenceManager, this, 2456, &R2_GLOBALS._player, NULL);
}
break;
case 2450:
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.postInit();
if (R2_GLOBALS.getFlag(61)) {
R2_GLOBALS._player.setup(2008, 6, 1);
@@ -2035,24 +2041,24 @@ void Scene2450::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setPosition(Common::Point(106, 111));
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
if (R2_GLOBALS.getFlag(72)) {
- if (R2_GLOBALS._player._characterScene[2] == 2450) {
- _actor1.postInit();
- _actor1.setup(20, 6, 1);
- _actor1.setPosition(Common::Point(240, 120));
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_SEEKER] == 2450) {
+ _companion.postInit();
+ _companion.setup(20, 6, 1);
+ _companion.setPosition(Common::Point(240, 120));
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
}
} else {
- _actor1.postInit();
- _actor1.setup(20, 8, 1);
- _actor1.setPosition(Common::Point(93, 158));
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ _companion.postInit();
+ _companion.setup(20, 8, 1);
+ _companion.setPosition(Common::Point(93, 158));
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
- _actor3.postInit();
- _actor3.setup(2001, 7, 1);
- _actor3.setPosition(Common::Point(34, 153));
- _actor3.setDetails(2001, 40, -1, -1, 1, (SceneItem *)NULL);
+ _careTaker.postInit();
+ _careTaker.setup(2001, 7, 1);
+ _careTaker.setPosition(Common::Point(34, 153));
+ _careTaker.setDetails(2001, 40, -1, -1, 1, (SceneItem *)NULL);
- _exit1._enabled = false;
+ _southWestExit._enabled = false;
}
} else {
R2_GLOBALS._player.postInit();
@@ -2060,32 +2066,32 @@ void Scene2450::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.setPosition(Common::Point(93, 158));
if (R2_GLOBALS.getFlag(72)) {
- if (R2_GLOBALS._player._characterScene[1] == 2450) {
- _actor1.postInit();
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == 2450) {
+ _companion.postInit();
if (R2_GLOBALS.getFlag(61)) {
- _actor1.setup(2008, 6, 1);
+ _companion.setup(2008, 6, 1);
} else {
- _actor1.setup(10, 6, 1);
+ _companion.setup(10, 6, 1);
}
- _actor1.setPosition(Common::Point(106, 111));
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setPosition(Common::Point(106, 111));
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
} else {
- _actor1.postInit();
+ _companion.postInit();
if (R2_GLOBALS.getFlag(61)) {
- _actor1.setup(2008, 6, 1);
+ _companion.setup(2008, 6, 1);
} else {
- _actor1.setup(10, 6, 1);
+ _companion.setup(10, 6, 1);
}
- _actor1.setPosition(Common::Point(106, 111));
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setPosition(Common::Point(106, 111));
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
- _actor3.postInit();
- _actor3.setup(2001, 7, 1);
- _actor3.setPosition(Common::Point(34, 153));
- _actor3.setDetails(2001, 40, -1, -1, 1, (SceneItem *)NULL);
+ _careTaker.postInit();
+ _careTaker.setup(2001, 7, 1);
+ _careTaker.setPosition(Common::Point(34, 153));
+ _careTaker.setDetails(2001, 40, -1, -1, 1, (SceneItem *)NULL);
- _exit1._enabled = false;
+ _southWestExit._enabled = false;
}
}
R2_GLOBALS._player.enableControl();
@@ -2095,7 +2101,7 @@ void Scene2450::postInit(SceneObjectList *OwnerList) {
break;
default:
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(61)) {
R2_GLOBALS._player.setup(2008, 3, 1);
} else {
@@ -2110,9 +2116,9 @@ void Scene2450::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.enableControl();
break;
}
- _item2.setDetails(Rect(174, 4, 199, 123), 2430, 30, 31, 32, 1, NULL);
- _item3.setDetails(Rect(67, 73, 207, 121), 2430, 36, -1, 38, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+ _post.setDetails(Rect(174, 4, 199, 123), 2430, 30, 31, 32, 1, NULL);
+ _bedspread.setDetails(Rect(67, 73, 207, 121), 2430, 36, -1, 38, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
}
void Scene2450::remove() {
@@ -2126,21 +2132,21 @@ void Scene2450::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 20:
- if (R2_GLOBALS._v565AE == 3) {
+ if (R2_GLOBALS._stripModifier == 3) {
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._v565AE = 4;
+ R2_GLOBALS._stripModifier = 4;
_sceneMode = 2454;
- setAction(&_sequenceManager, this, 2454, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 2454, &_careTaker, NULL);
} else {
R2_GLOBALS._player.enableControl(CURSOR_TALK);
- if (R2_GLOBALS._v565AE < 4)
+ if (R2_GLOBALS._stripModifier < 4)
R2_GLOBALS._player._canWalk = false;
}
break;
case 30:
R2_GLOBALS._player.disableControl();
_sceneMode = 2455;
- setAction(&_sequenceManager, this, 2455, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2455, &_companion, NULL);
break;
case 31:
R2_GLOBALS.setFlag(61);
@@ -2151,7 +2157,7 @@ void Scene2450::signal() {
break;
case 2452:
R2_GLOBALS.setFlag(61);
- _actor2.remove();
+ _parker.remove();
R2_GLOBALS._player.enableControl();
if (!R2_GLOBALS.getFlag(72)) {
R2_GLOBALS._player.setStrip(6);
@@ -2164,55 +2170,55 @@ void Scene2450::signal() {
_stripManager.start(700, this);
break;
case 2454:
- _exit1._enabled = true;
+ _southWestExit._enabled = true;
R2_GLOBALS.setFlag(72);
- _actor3.remove();
+ _careTaker.remove();
if (R2_GLOBALS.getFlag(61)) {
g_globals->_sceneManager.changeScene(2435);
} else {
_sceneMode = 31;
- if (R2_GLOBALS._player._characterIndex == 1) {
- setAction(&_sequenceManager, this, 2452, &R2_GLOBALS._player, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ setAction(&_sequenceManager, this, 2452, &R2_GLOBALS._player, &_parker, NULL);
} else {
- setAction(&_sequenceManager, this, 2452, &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 2452, &_companion, &_parker, NULL);
}
}
break;
case 2455:
- R2_GLOBALS._player._oldCharacterScene[2] = 2450;
- R2_GLOBALS._player._characterScene[2] = 2000;
- R2_GLOBALS._v56605[2] = 3;
- _actor1.remove();
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 2450;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 2000;
+ R2_GLOBALS._spillLocation[R2_SEEKER] = 3;
+ _companion.remove();
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
default:
- _actor1.postInit();
- _actor1.setDetails(9002, 0, 4, 3, 2, (SceneItem *)NULL);
- _actor3.postInit();
- _actor3.setDetails(2001, 40, -1, -1, 2, (SceneItem *)NULL);
+ _companion.postInit();
+ _companion.setDetails(9002, 0, 4, 3, 2, (SceneItem *)NULL);
+ _careTaker.postInit();
+ _careTaker.setDetails(2001, 40, -1, -1, 2, (SceneItem *)NULL);
_sceneMode = 2453;
- setAction(&_sequenceManager, this, 2453, &_actor3, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2453, &_careTaker, &_companion, NULL);
break;
}
}
/*--------------------------------------------------------------------------
- * Scene 2455 - Ice Maze: Inside crevasse
+ * Scene 2455 - Spill Mountains: Inside crevasse
*
*--------------------------------------------------------------------------*/
-bool Scene2455::Actor1::startAction(CursorType action, Event &event) {
- Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2455::Lamp::startAction(CursorType action, Event &event) {
if (action == R2_GLASS_DOME) {
- if ((R2_INVENTORY.getObjectScene(49) == 2455) || (R2_INVENTORY.getObjectScene(50) == 2455)) {
+ if ((R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_2) == 2455) || (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_3) == 2455)) {
+ Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2458;
- scene->_actor2._lookLineNum = 9;
- scene->_actor1.remove();
- scene->_actor3.postInit();
- scene->_actor3.setDetails(2455, 16, 1, -1, 2, (SceneItem *)NULL);
- scene->setAction(&scene->_sequenceManager, scene, 2458, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor3, NULL);
+ scene->_pool._lookLineNum = 9;
+ scene->_lamp.remove();
+ scene->_scrithKey.postInit();
+ scene->_scrithKey.setDetails(2455, 16, 1, -1, 2, (SceneItem *)NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2458, &R2_GLOBALS._player, &scene->_pool, &scene->_scrithKey, NULL);
return true;
}
}
@@ -2220,31 +2226,31 @@ bool Scene2455::Actor1::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene2455::Actor2::startAction(CursorType action, Event &event) {
+bool Scene2455::Pool::startAction(CursorType action, Event &event) {
Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case R2_ALCOHOL_LAMP_2:
- if (R2_INVENTORY.getObjectScene(50) != 2455) {
+ if (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_3) != 2455) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- scene->_actor1.setup(2456, 3, 3);
- scene->_actor1.setPosition(Common::Point(162, 165));
- scene->_actor1.setDetails(2455, 15, 1, -1, 2, (SceneItem *)NULL);
+ scene->_lamp.postInit();
+ scene->_lamp.setup(2456, 3, 3);
+ scene->_lamp.setPosition(Common::Point(162, 165));
+ scene->_lamp.setDetails(2455, 15, 1, -1, 2, (SceneItem *)NULL);
scene->_sceneMode = 11;
- scene->setAction(&scene->_sequenceManager, scene, 2457, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2457, &R2_GLOBALS._player, &scene->_pool, NULL);
return true;
}
break;
case R2_ALCOHOL_LAMP_3:
- if (R2_INVENTORY.getObjectScene(49) != 2455) {
+ if (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_2) != 2455) {
R2_GLOBALS._player.disableControl();
- scene->_actor1.postInit();
- scene->_actor1.setup(2456, 3, 3);
- scene->_actor1.setPosition(Common::Point(162, 165));
- scene->_actor1.setDetails(2455, 15, 1, -1, 2, (SceneItem *)NULL);
+ scene->_lamp.postInit();
+ scene->_lamp.setup(2456, 3, 3);
+ scene->_lamp.setPosition(Common::Point(162, 165));
+ scene->_lamp.setDetails(2455, 15, 1, -1, 2, (SceneItem *)NULL);
scene->_sceneMode = 12;
- scene->setAction(&scene->_sequenceManager, scene, 2457, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2457, &R2_GLOBALS._player, &scene->_pool, NULL);
return true;
}
break;
@@ -2255,20 +2261,20 @@ bool Scene2455::Actor2::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene2455::Actor3::startAction(CursorType action, Event &event) {
- Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2455::ScrithKey::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE) {
+ Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2459;
- scene->setAction(&scene->_sequenceManager, scene, 2459, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2459, &R2_GLOBALS._player, &scene->_scrithKey, NULL);
return true;
}
return SceneActor::startAction(action, event);
}
-void Scene2455::Exit1::changeScene() {
+void Scene2455::NorthExit::changeScene() {
Scene2455 *scene = (Scene2455 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -2283,45 +2289,44 @@ void Scene2455::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
if (R2_GLOBALS._sceneManager._previousScene == -1) {
- R2_INVENTORY.setObjectScene(29, 2);
- R2_INVENTORY.setObjectScene(50, 2);
+ R2_INVENTORY.setObjectScene(R2_GLASS_DOME, 2);
+ R2_INVENTORY.setObjectScene(R2_ALCOHOL_LAMP_3, 2);
}
R2_GLOBALS._sound1.play(200);
- _exit1.setDetails(Rect(0, 0, 320, 15), EXITCURSOR_N, 2425);
-
- if (R2_INVENTORY.getObjectScene(29) == 2455) {
- if ((R2_INVENTORY.getObjectScene(50) == 2455) || (R2_INVENTORY.getObjectScene(49) == 2455)) {
- _actor1.postInit();
- _actor1.setup(2456, 3, 3);
- _actor1.setPosition(Common::Point(162, 165));
- _actor1.setDetails(2455, 15, 1, -1, 1, (SceneItem *)NULL);
- }
- } else {
- _actor3.postInit();
- _actor3.setup(2456, 3, 1);
- _actor3.setPosition(Common::Point(176, 165));
- _actor3.setDetails(2455, 16, 1, -1, 1, (SceneItem *)NULL);
+ _northExit.setDetails(Rect(0, 0, 320, 15), EXITCURSOR_N, 2425);
+
+ if (R2_INVENTORY.getObjectScene(R2_GLASS_DOME) == 2455) {
+ _scrithKey.postInit();
+ _scrithKey.setup(2456, 3, 1);
+ _scrithKey.setPosition(Common::Point(176, 165));
+ _scrithKey.setDetails(2455, 16, 1, -1, 1, (SceneItem *)NULL);
+ } else if ((R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_3) == 2455) ||
+ (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_2) == 2455)) {
+ _lamp.postInit();
+ _lamp.setup(2456, 3, 3);
+ _lamp.setPosition(Common::Point(162, 165));
+ _lamp.setDetails(2455, 15, 1, -1, 1, (SceneItem *)NULL);
}
- _actor2.postInit();
- if (R2_INVENTORY.getObjectScene(29) == 2455) {
- _actor2.setup(2456, 3, 2);
- _actor2.setDetails(2455, 9, 1, -1, 1, (SceneItem *)NULL);
+ _pool.postInit();
+ if (R2_INVENTORY.getObjectScene(R2_GLASS_DOME) == 2455) {
+ _pool.setup(2456, 3, 2);
+ _pool.setDetails(2455, 9, 1, -1, 1, (SceneItem *)NULL);
} else {
- if ((R2_INVENTORY.getObjectScene(50) != 2455) && (R2_INVENTORY.getObjectScene(49) != 2455))
- _actor2.setup(2455, 1, 1);
+ if ((R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_3) != 2455) && (R2_INVENTORY.getObjectScene(R2_ALCOHOL_LAMP_2) != 2455))
+ _pool.setup(2455, 1, 1);
else
- _actor2.setup(2456, 1, 1);
- _actor2.setDetails(2455, 3, 1, -1, 1, (SceneItem *)NULL);
+ _pool.setup(2456, 1, 1);
+ _pool.setDetails(2455, 3, 1, -1, 1, (SceneItem *)NULL);
}
- _actor2.setPosition(Common::Point(162, 165));
- _actor2.fixPriority(20);
- if (R2_INVENTORY.getObjectScene(29) != 2455)
- _actor2.animate(ANIM_MODE_2, NULL);
+ _pool.setPosition(Common::Point(162, 165));
+ _pool.fixPriority(20);
+ if (R2_INVENTORY.getObjectScene(R2_GLASS_DOME) != 2455)
+ _pool.animate(ANIM_MODE_2, NULL);
R2_GLOBALS._player.postInit();
- _item1.setDetails(Rect(0, 0, 320, 200), 2455, 0, 1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2455, 0, 1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2425) {
@@ -2349,23 +2354,23 @@ void Scene2455::signal() {
g_globals->_sceneManager.changeScene(2425);
break;
case 11:
- R2_INVENTORY.setObjectScene(49, 2455);
+ R2_INVENTORY.setObjectScene(R2_ALCOHOL_LAMP_2, 2455);
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
break;
case 12:
- R2_INVENTORY.setObjectScene(50, 2455);
+ R2_INVENTORY.setObjectScene(R2_ALCOHOL_LAMP_3, 2455);
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
break;
case 2458:
- R2_INVENTORY.setObjectScene(29, 2455);
+ R2_INVENTORY.setObjectScene(R2_GLASS_DOME, 2455);
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
break;
case 2459:
- _actor3.remove();
- R2_INVENTORY.setObjectScene(31, 2);
+ _scrithKey.remove();
+ R2_INVENTORY.setObjectScene(R2_SCRITH_KEY, 2);
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
break;
@@ -2377,11 +2382,11 @@ void Scene2455::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2500 - Ice Maze: Large Cave
+ * Scene 2500 - Spill Mountains: Large Ledge
*
*--------------------------------------------------------------------------*/
-void Scene2500::Exit1::changeScene() {
+void Scene2500::WestExit::changeScene() {
Scene2500 *scene = (Scene2500 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -2409,12 +2414,12 @@ void Scene2500::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene == -1)
R2_GLOBALS._sceneManager._previousScene = 2000;
- _exit1.setDetails(Rect(30, 50, 85, 105), EXITCURSOR_W, 2000);
- _exit1.setDest(Common::Point(84, 104));
+ _westExit.setDetails(Rect(30, 50, 85, 105), EXITCURSOR_W, 2000);
+ _westExit.setDest(Common::Point(84, 104));
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(11);
R2_GLOBALS._player._moveDiff = Common::Point(2, 1);
} else {
@@ -2422,20 +2427,20 @@ void Scene2500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
}
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(21, 3, 1);
- _actor1.setDetails(9002, 1, -1, -1, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(21, 3, 1);
+ _companion.setDetails(9002, 1, -1, -1, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 3, 1);
- _actor1.changeZoom(50);
- _actor1.setDetails(9001, 0, -1, -1, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 3, 1);
+ _companion.changeZoom(50);
+ _companion.setDetails(9001, 0, -1, -1, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(141, 94));
+ _companion.setPosition(Common::Point(141, 94));
}
- _item1.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2430, 0, -1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
@@ -2446,9 +2451,9 @@ void Scene2500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.addMover(mover, &pt, this);
} else if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 3100) {
_sceneMode = 2500;
- _actor2.postInit();
- _actor3.postInit();
- setAction(&_sequenceManager, this, 2500, &R2_GLOBALS._player, &_actor2, &_actor3, NULL);
+ _quinn.postInit();
+ _ship.postInit();
+ setAction(&_sequenceManager, this, 2500, &R2_GLOBALS._player, &_quinn, &_ship, NULL);
} else {
R2_GLOBALS._player.setPosition(Common::Point(160, 150));
R2_GLOBALS._player.setStrip(3);
@@ -2465,7 +2470,7 @@ void Scene2500::signal() {
case 20:
R2_GLOBALS._player.disableControl();
_sceneMode = 2501;
- setAction(&_sequenceManager, this, 2501, &R2_GLOBALS._player, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 2501, &R2_GLOBALS._player, &_quinn, &_ship, NULL);
break;
case 2500:
_sceneMode = 20;
@@ -2485,10 +2490,11 @@ void Scene2500::signal() {
* Scene 2525 - Furnace room
*
*--------------------------------------------------------------------------*/
-bool Scene2525::Item5::startAction(CursorType action, Event &event) {
- Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2525::StopCock::startAction(CursorType action, Event &event) {
if ((action == R2_REBREATHER_TANK) && (!R2_GLOBALS.getFlag(74))) {
+ Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2526;
scene->setAction(&scene->_sequenceManager, scene, 2526, &R2_GLOBALS._player, NULL);
@@ -2498,23 +2504,23 @@ bool Scene2525::Item5::startAction(CursorType action, Event &event) {
return SceneItem::startAction(action, event);
}
-bool Scene2525::Actor3::startAction(CursorType action, Event &event) {
- Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2525::GlassDome::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2525;
- scene->setAction(&scene->_sequenceManager, scene, 2525, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2525, &R2_GLOBALS._player, &scene->_glassDome, NULL);
} else {
- SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
return true;
}
-void Scene2525::Exit1::changeScene() {
+void Scene2525::SouthExit::changeScene() {
Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -2533,26 +2539,26 @@ void Scene2525::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(200);
R2_GLOBALS._sound2.play(207);
- _exit1.setDetails(Rect(86, 155, 228, 168), EXITCURSOR_S, 2000);
+ _southExit.setDetails(Rect(86, 155, 228, 168), EXITCURSOR_S, 2000);
- if (R2_INVENTORY.getObjectScene(29) == 2525) {
- _actor3.postInit();
- _actor3.setup(2435, 1, 2);
- _actor3.setPosition(Common::Point(78, 155));
- _actor3.fixPriority(155);
- _actor3.setDetails(2525, 27, -1, -1, 1, (SceneItem *)NULL);
+ if (R2_INVENTORY.getObjectScene(R2_GLASS_DOME) == 2525) {
+ _glassDome.postInit();
+ _glassDome.setup(2435, 1, 2);
+ _glassDome.setPosition(Common::Point(78, 155));
+ _glassDome.fixPriority(155);
+ _glassDome.setDetails(2525, 27, -1, -1, 1, (SceneItem *)NULL);
}
- _actor2.postInit();
- _actor2.setup(2525, 1, 1);
- _actor2.setPosition(Common::Point(183, 114));
- _actor2.setDetails(2525, 15, -1, -1, 1, (SceneItem *)NULL);
- _actor2.animate(ANIM_MODE_2, NULL);
- _actor2._numFrames = 3;
+ _compressor.postInit();
+ _compressor.setup(2525, 1, 1);
+ _compressor.setPosition(Common::Point(183, 114));
+ _compressor.setDetails(2525, 15, -1, -1, 1, (SceneItem *)NULL);
+ _compressor.animate(ANIM_MODE_2, NULL);
+ _compressor._numFrames = 3;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setup(2008, 3, 1);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -2560,25 +2566,25 @@ void Scene2525::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
}
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(209, 162));
+ _companion.setPosition(Common::Point(209, 162));
- R2_GLOBALS._walkRegions.enableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(4);
}
- _item5.setDetails(Rect(125, 73, 140, 86), 2525, 6, -1, -1, 1, NULL);
- _item3.setDetails(Rect(137, 11, 163, 72), 2525, 12, -1, -1, 1, NULL);
- _item4.setDetails(Rect(204, 20, 234, 78), 2525, 12, -1, -1, 1, NULL);
- _item2.setDetails(Rect(102, 62, 230, 134), 2525, 0, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2525, 24, -1, -1, 1, NULL);
+ _stopcock.setDetails(Rect(125, 73, 140, 86), 2525, 6, -1, -1, 1, NULL);
+ _pipes1.setDetails(Rect(137, 11, 163, 72), 2525, 12, -1, -1, 1, NULL);
+ _pipes2.setDetails(Rect(204, 20, 234, 78), 2525, 12, -1, -1, 1, NULL);
+ _machine.setDetails(Rect(102, 62, 230, 134), 2525, 0, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2525, 24, -1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
@@ -2607,8 +2613,8 @@ void Scene2525::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 2525:
- _actor3.remove();
- R2_INVENTORY.setObjectScene(29, 2);
+ _glassDome.remove();
+ R2_INVENTORY.setObjectScene(R2_GLASS_DOME, 2);
R2_GLOBALS._player.enableControl();
break;
case 2526:
@@ -2622,56 +2628,57 @@ void Scene2525::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2530 - Ice Maze: Well
+ * Scene 2530 - Spill Mountains: Well
*
*--------------------------------------------------------------------------*/
-bool Scene2530::Actor2::startAction(CursorType action, Event &event) {
- Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+bool Scene2530::Flask::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2530;
- scene->setAction(&scene->_sequenceManager, scene, 2530, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2530, &R2_GLOBALS._player, &scene->_flask, NULL);
} else {
- SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
return true;
}
-bool Scene2530::Actor3::startAction(CursorType action, Event &event) {
- Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2530::Crank::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
if (R2_GLOBALS.getFlag(73))
- SceneItem::display(2530, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2530, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2532;
- scene->setAction(&scene->_sequenceManager, scene, 2532, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2532, &R2_GLOBALS._player, &scene->_crank, NULL);
}
} else {
if (R2_GLOBALS.getFlag(73)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2533;
- scene->setAction(&scene->_sequenceManager, scene, 2533, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2533, &R2_GLOBALS._player, &scene->_crank, NULL);
} else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2531;
- scene->setAction(&scene->_sequenceManager, scene, 2531, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2531, &R2_GLOBALS._player, &scene->_crank, NULL);
}
}
return true;
}
-void Scene2530::Exit1::changeScene() {
+void Scene2530::SouthExit::changeScene() {
Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -2688,31 +2695,31 @@ void Scene2530::postInit(SceneObjectList *OwnerList) {
loadScene(2530);
SceneExt::postInit();
- _exit1.setDetails(Rect(68, 155, 147, 168), EXITCURSOR_S, 2000);
- _exit1.setDest(Common::Point(108, 160));
+ _southExit.setDetails(Rect(68, 155, 147, 168), EXITCURSOR_S, 2000);
+ _southExit.setDest(Common::Point(108, 160));
- if (R2_INVENTORY.getObjectScene(33) == 2530) {
- _actor2.postInit();
- _actor2.setup(2435, 1, 3);
- _actor2.setPosition(Common::Point(299, 80));
- _actor2.fixPriority(80);
- _actor2.setDetails(2530, 28, -1, -1, 1, (SceneItem *)NULL);
+ if (R2_INVENTORY.getObjectScene(R2_PURE_GRAIN_ALCOHOL) == 2530) {
+ _flask.postInit();
+ _flask.setup(2435, 1, 3);
+ _flask.setPosition(Common::Point(299, 80));
+ _flask.fixPriority(80);
+ _flask.setDetails(2530, 28, -1, -1, 1, (SceneItem *)NULL);
}
- _actor3.postInit();
+ _crank.postInit();
if (R2_GLOBALS.getFlag(73)) {
- _actor3.setup(2531, 4, 2);
- _actor3.setPosition(Common::Point(154, 130));
+ _crank.setup(2531, 4, 2);
+ _crank.setPosition(Common::Point(154, 130));
} else {
- _actor3.setup(2531, 4, 1);
- _actor3.setPosition(Common::Point(173, 131));
+ _crank.setup(2531, 4, 1);
+ _crank.setPosition(Common::Point(173, 131));
}
- _actor3.setDetails(2530, 22, -1, -1, 1, (SceneItem *)NULL);
+ _crank.setDetails(2530, 22, -1, -1, 1, (SceneItem *)NULL);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -2721,23 +2728,23 @@ void Scene2530::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._player.setPosition(Common::Point(100, 200));
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(20, 130));
- R2_GLOBALS._walkRegions.enableRegion(1);
+ _companion.setPosition(Common::Point(20, 130));
+ R2_GLOBALS._walkRegions.disableRegion(1);
}
- _item2.setDetails(Rect(108, 90, 135, 205), 2530, 22, -1, -1, 1, NULL);
- _item5.setDetails(Rect(115, 112, 206, 130), 2530, 25, -1, 27, 1, NULL);
- _item3.setDetails(Rect(256, 64, 311, 85), 2530, 31, -1, 33, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2530, 0, 1, -1, 1, NULL);
+ _crank2.setDetails(Rect(108, 90, 135, 205), 2530, 22, -1, -1, 1, NULL);
+ _rope.setDetails(Rect(115, 112, 206, 130), 2530, 25, -1, 27, 1, NULL);
+ _shelf.setDetails(Rect(256, 64, 311, 85), 2530, 31, -1, 33, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2530, 0, 1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
@@ -2759,8 +2766,9 @@ void Scene2530::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 2530:
- R2_INVENTORY.setObjectScene(33, 2);
- _actor2.remove();
+ R2_INVENTORY.setObjectScene(R2_PURE_GRAIN_ALCOHOL, 2);
+ _flask.remove();
+ R2_GLOBALS._player.enableControl();
break;
case 2531:
// No break on purpose
@@ -2779,50 +2787,47 @@ void Scene2530::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2535 - Ice Maze: Tannery
+ * Scene 2535 - Spill Mountains: Tannery
*
*--------------------------------------------------------------------------*/
-bool Scene2535::Actor3::startAction(CursorType action, Event &event) {
- Scene2535 *scene = (Scene2535 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2535::RebreatherTank::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ Scene2535 *scene = (Scene2535 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- if (R2_INVENTORY.getObjectScene(20) == 2535) {
- scene->_sceneMode = 2536;
- scene->setAction(&scene->_sequenceManager, scene, 2536, &R2_GLOBALS._player, &scene->_actor3, NULL);
- } else {
- scene->_sceneMode = 2537;
- scene->setAction(&scene->_sequenceManager, scene, 2537, &R2_GLOBALS._player, &scene->_actor3, NULL);
- }
+
+ scene->_sceneMode = (R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 2535) ? 2536 : 2537;
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode,
+ &R2_GLOBALS._player, &scene->_rebreatherTank, NULL);
} else {
- SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
return true;
}
-bool Scene2535::Actor4::startAction(CursorType action, Event &event) {
- Scene2535 *scene = (Scene2535 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2535::TannerMask::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ Scene2535 *scene = (Scene2535 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2535;
- scene->setAction(&scene->_sequenceManager, scene, 2535, &R2_GLOBALS._player, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2535, &R2_GLOBALS._player, &scene->_tannerMask, NULL);
} else {
- SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
return true;
}
-void Scene2535::Exit1::changeScene() {
+void Scene2535::SouthExit::changeScene() {
Scene2535 *scene = (Scene2535 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -2839,45 +2844,45 @@ void Scene2535::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
if (R2_GLOBALS._sceneManager._previousScene == -1) {
R2_GLOBALS.setFlag(73);
- R2_INVENTORY.setObjectScene(20, 2535);
+ R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 2535);
}
- _exit1.setDetails(Rect(172, 155, 250, 167), EXITCURSOR_S, 2000);
- _exit1.setDest(Common::Point(210, 160));
-
- if (R2_INVENTORY.getObjectScene(32) == 2535) {
- _actor4.postInit();
- _actor4.setup(2435, 1, 4);
- _actor4.setPosition(Common::Point(47, 74));
- _actor4.fixPriority(74);
- _actor4.setDetails(2535, 21, -1, -1, 1, (SceneItem *)NULL);
+ _southExit.setDetails(Rect(172, 155, 250, 167), EXITCURSOR_S, 2000);
+ _southExit.setDest(Common::Point(210, 160));
+
+ if (R2_INVENTORY.getObjectScene(R2_TANNER_MASK) == 2535) {
+ _tannerMask.postInit();
+ _tannerMask.setup(2435, 1, 4);
+ _tannerMask.setPosition(Common::Point(47, 74));
+ _tannerMask.fixPriority(74);
+ _tannerMask.setDetails(2535, 21, -1, -1, 1, (SceneItem *)NULL);
}
- if (R2_INVENTORY.getObjectScene(20) == 2535) {
- _actor3.postInit();
- _actor3.setup(2535, 3, 1);
- _actor3.setPosition(Common::Point(203, 131));
- _actor3.setDetails(3, 20, -1, -1, 1, (SceneItem *)NULL);
- R2_GLOBALS._walkRegions.enableRegion(6);
+ if (R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 2535) {
+ _rebreatherTank.postInit();
+ _rebreatherTank.setup(2535, 3, 1);
+ _rebreatherTank.setPosition(Common::Point(203, 131));
+ _rebreatherTank.setDetails(3, 20, -1, -1, 1, (SceneItem *)NULL);
+ R2_GLOBALS._walkRegions.disableRegion(6);
}
- if ((R2_INVENTORY.getObjectScene(20) == 0) && (R2_GLOBALS.getFlag(73))) {
- _actor3.postInit();
- _actor3.setup(2536, 1, 2);
- _actor3.setPosition(Common::Point(164, 133));
- _actor3.setDetails(3, 20, -1, -1, 1, (SceneItem *)NULL);
+ if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 0) && (R2_GLOBALS.getFlag(73))) {
+ _rebreatherTank.postInit();
+ _rebreatherTank.setup(2536, 1, 2);
+ _rebreatherTank.setPosition(Common::Point(164, 133));
+ _rebreatherTank.setDetails(3, 20, -1, -1, 1, (SceneItem *)NULL);
}
if (R2_GLOBALS.getFlag(73)) {
- _actor2.postInit();
- _actor2.setup(2536, 1, 1);
- _actor2.setPosition(Common::Point(160, 130));
- _actor2.fixPriority(122);
- _actor2.setDetails(2535, 37, -1, -1, 1, (SceneItem *)NULL);
+ _rope.postInit();
+ _rope.setup(2536, 1, 1);
+ _rope.setPosition(Common::Point(160, 130));
+ _rope.fixPriority(122);
+ _rope.setDetails(2535, 37, -1, -1, 1, (SceneItem *)NULL);
}
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
R2_GLOBALS._player.setVisage(2008);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
} else {
@@ -2886,26 +2891,26 @@ void Scene2535::postInit(SceneObjectList *OwnerList) {
}
R2_GLOBALS._player.setPosition(Common::Point(210, 200));
- if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 1) {
- _actor1.setup(20, 5, 1);
- _actor1.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
+ if (R2_GLOBALS._player._characterScene[R2_QUINN] == R2_GLOBALS._player._characterScene[R2_SEEKER]) {
+ _companion.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _companion.setup(20, 5, 1);
+ _companion.setDetails(9002, 0, 4, 3, 1, (SceneItem *)NULL);
} else {
- _actor1.setup(2008, 5, 1);
- _actor1.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
+ _companion.setup(2008, 5, 1);
+ _companion.setDetails(9001, 0, 5, 3, 1, (SceneItem *)NULL);
}
- _actor1.setPosition(Common::Point(245, 115));
- R2_GLOBALS._walkRegions.enableRegion(2);
+ _companion.setPosition(Common::Point(245, 115));
+ R2_GLOBALS._walkRegions.disableRegion(2);
}
- _item2.setDetails(Rect(96, 3, 215, 33), 2535, 3, 6, 5, 1, NULL);
- _item3.setDetails(Rect(4, 43, 40, 101), 2535, 6, 7, 8, 1, NULL);
- _item4.setDetails(Rect(55, 13, 140, 89), 2535, 6, 7, 8, 1, NULL);
- _item5.setDetails(Rect(144, 23, 216, 76), 2535, 6, 7, 8, 1, NULL);
- _item6.setDetails(Rect(227, 8, 307, 99), 2535, 6, 7, 8, 1, NULL);
- _item7.setDetails(Rect(116, 111, 201, 132), 2535, 18, 19, 20, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2535, 0, 1, -1, 1, NULL);
+ _roof.setDetails(Rect(96, 3, 215, 33), 2535, 3, 6, 5, 1, NULL);
+ _skin1.setDetails(Rect(4, 43, 40, 101), 2535, 6, 7, 8, 1, NULL);
+ _skin2.setDetails(Rect(55, 13, 140, 89), 2535, 6, 7, 8, 1, NULL);
+ _skin3.setDetails(Rect(144, 23, 216, 76), 2535, 6, 7, 8, 1, NULL);
+ _skin4.setDetails(Rect(227, 8, 307, 99), 2535, 6, 7, 8, 1, NULL);
+ _depression.setDetails(Rect(116, 111, 201, 132), 2535, 18, 19, 20, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2535, 0, 1, -1, 1, NULL);
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
@@ -2926,32 +2931,31 @@ void Scene2535::signal() {
g_globals->_sceneManager.changeScene(2000);
break;
case 2535:
- R2_INVENTORY.setObjectScene(32, 2);
- _actor4.remove();
+ R2_INVENTORY.setObjectScene(R2_TANNER_MASK, R2_SEEKER);
+ _tannerMask.remove();
R2_GLOBALS._player.enableControl();
break;
case 2536:
- R2_INVENTORY.setObjectScene(20, 0);
- R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 0);
+ R2_GLOBALS._walkRegions.enableRegion(6);
if (!R2_GLOBALS.getFlag(73)) {
- _actor3.remove();
+ _rebreatherTank.remove();
R2_GLOBALS._player.enableControl();
} else {
_sceneMode = 20;
- _actor3.show();
- _actor3.setup(2536, 1, 2);
- _actor3.setDetails(3, 20, -1, -1, 3, (SceneItem *)NULL);
- _actor3.setPosition(Common::Point(164, 150));
- _actor3.fixPriority(130);
- _actor3._moveDiff.y = 1;
- Common::Point pt(164, 133);
- PlayerMover *mover = new PlayerMover();
- _actor3.addMover(mover, &pt, this);
+ _rebreatherTank.show();
+ _rebreatherTank.setup(2536, 1, 2);
+ _rebreatherTank.setDetails(3, 20, -1, -1, 3, (SceneItem *)NULL);
+ _rebreatherTank.setPosition(Common::Point(164, 150));
+ _rebreatherTank.fixPriority(130);
+
+ _rebreatherTank._moveDiff.y = 1;
+ ADD_MOVER(_rebreatherTank, 164, 133);
}
break;
case 2537:
- _actor3.remove();
- R2_INVENTORY.setObjectScene(20, 1);
+ _rebreatherTank.remove();
+ R2_INVENTORY.setObjectScene(R2_REBREATHER_TANK, 1);
R2_GLOBALS._player.enableControl();
break;
case 20:
@@ -2963,9 +2967,10 @@ void Scene2535::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2600 - Ice Maze: Exit
+ * Scene 2600 - Spill Mountains: Exit
*
*--------------------------------------------------------------------------*/
+
Scene2600::Scene2600(): SceneExt() {
_rotation = NULL;
}
@@ -2980,6 +2985,8 @@ void Scene2600::postInit(SceneObjectList *OwnerList) {
loadScene(2600);
R2_GLOBALS._uiElements._active = false;
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
R2_GLOBALS._sound1.fadeSound(214);
R2_GLOBALS._sound2.play(215);
_rotation = R2_GLOBALS._scenePalette.addRotation(176, 191, 1);
@@ -2994,6 +3001,7 @@ void Scene2600::postInit(SceneObjectList *OwnerList) {
void Scene2600::remove() {
R2_GLOBALS._sound1.fadeOut2(NULL);
R2_GLOBALS._sound2.fadeOut2(NULL);
+ R2_GLOBALS._uiElements._visible = true;
// _rotation->remove();
SceneExt::remove();
}
@@ -3004,57 +3012,65 @@ void Scene2600::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 2700 - Forest Maze
+ * Scene 2700 - Outer Forest
*
*--------------------------------------------------------------------------*/
+
Scene2700::Scene2700(): SceneExt() {
- _field412 = _field414 = _field416 = 0;
+ _areaMode = _moveMode = _stripNumber = 0;
+
+ _walkRect1.set(70, 122, 90, 132);
+ _walkRect2.set(150, 122, 160, 132);
+ _walkRect3.set(90, 142, 130, 157);
+ _walkRect4.set(175, 137, 200, 147);
+ _walkRect5.set(280, 127, 300, 137);
+ _walkRect6.set(240, 157, 265, 167);
}
void Scene2700::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
+ s.syncAsSint16LE(_areaMode);
+ s.syncAsSint16LE(_moveMode);
+ s.syncAsSint16LE(_stripNumber);
}
void Scene2700::Action1::signal() {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor2.animate(ANIM_MODE_5, NULL);
+ scene->_ghoulHome6.animate(ANIM_MODE_5, NULL);
}
void Scene2700::Action2::signal() {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
setDelay(300 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor3.animate(ANIM_MODE_5, NULL);
+ scene->_ghoulHome7.animate(ANIM_MODE_5, NULL);
}
void Scene2700::Action3::signal() {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
setDelay(450 + R2_GLOBALS._randomSource.getRandomNumber(450));
- scene->_actor4.animate(ANIM_MODE_8, 1, NULL);
+ scene->_ghoulHome8.animate(ANIM_MODE_8, 1, NULL);
}
void Scene2700::Action4::signal() {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
setDelay(300 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor5.animate(ANIM_MODE_8, 1, NULL);
+ scene->_ghoulHome9.animate(ANIM_MODE_8, 1, NULL);
}
-void Scene2700::Area1::process(Event &event) {
+void Scene2700::SouthExit::process(Event &event) {
SceneArea::process(event);
- if ((event.eventType == 1) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 10;
- scene->_field414 = 2703;
- switch (scene->_field412) {
+ scene->_moveMode = 2703;
+ switch (scene->_areaMode) {
case 0:
// No break on purpose
case 6:
@@ -3097,14 +3113,14 @@ void Scene2700::Area1::process(Event &event) {
}
}
-void Scene2700::Area2::process(Event &event) {
+void Scene2700::EastExit::process(Event &event) {
SceneArea::process(event);
- if ((event.eventType == 1) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 10;
- scene->_field414 = 2704;
- switch (scene->_field412) {
+ scene->_moveMode = 2704;
+ switch (scene->_areaMode) {
case 0: {
Common::Point pt(140, 162);
NpcMover *mover = new NpcMover();
@@ -3157,41 +3173,35 @@ void Scene2700::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.stop();
R2_GLOBALS._sound2.stop();
- _area1.setDetails(Rect(135, 160, 185, 168), SHADECURSOR_DOWN);
- _area2.setDetails(Rect(300, 90, 320, 135), EXITCURSOR_E);
- _rect1.set(70, 122, 90, 132);
- _rect2.set(150, 122, 160, 132);
- _rect3.set(90, 142, 130, 157);
- _rect4.set(175, 137, 200, 147);
- _rect5.set(280, 127, 300, 137);
- _rect6.set(240, 157, 265, 167);
-
- _actor2.postInit();
- _actor2.setup(2700, 1, 1);
- _actor2.setPosition(Common::Point(140, 29));
- _actor2.setAction(&_action1);
-
- _actor3.postInit();
- _actor3.setup(2700, 2, 1);
- _actor3.setPosition(Common::Point(213, 32));
- _actor3.setAction(&_action2);
-
- _actor4.postInit();
- _actor4.setup(2700, 3, 1);
- _actor4.setPosition(Common::Point(17, 39));
- _actor4.setAction(&_action3);
-
- _actor5.postInit();
- _actor5.setup(2700, 5, 1);
- _actor5.setPosition(Common::Point(17, 71));
- _actor5.setAction(&_action4);
-
- _item2.setDetails(Rect(52, 38, 68, 60), 2700, 4, -1, 6, 1, NULL);
- _item3.setDetails(Rect(113, 22, 127, 33), 2700, 4, -1, 6, 1, NULL);
- _item4.setDetails(Rect(161, 44, 170, 52), 2700, 4, -1, 6, 1, NULL);
- _item5.setDetails(Rect(221, 19, 233, 31), 2700, 4, -1, 6, 1, NULL);
- _item6.setDetails(Rect(235, 59, 250, 75), 2700, 4, -1, 6, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2700, 4, -1, 6, 1, NULL);
+ _southExit.setDetails(Rect(135, 160, 185, 168), SHADECURSOR_DOWN);
+ _eastExit.setDetails(Rect(300, 90, 320, 135), EXITCURSOR_E);
+
+ _ghoulHome6.postInit();
+ _ghoulHome6.setup(2700, 1, 1);
+ _ghoulHome6.setPosition(Common::Point(140, 29));
+ _ghoulHome6.setAction(&_action1);
+
+ _ghoulHome7.postInit();
+ _ghoulHome7.setup(2700, 2, 1);
+ _ghoulHome7.setPosition(Common::Point(213, 32));
+ _ghoulHome7.setAction(&_action2);
+
+ _ghoulHome8.postInit();
+ _ghoulHome8.setup(2700, 3, 1);
+ _ghoulHome8.setPosition(Common::Point(17, 39));
+ _ghoulHome8.setAction(&_action3);
+
+ _ghoulHome9.postInit();
+ _ghoulHome9.setup(2700, 5, 1);
+ _ghoulHome9.setPosition(Common::Point(17, 71));
+ _ghoulHome9.setAction(&_action4);
+
+ _ghoulHome1.setDetails(Rect(52, 38, 68, 60), 2700, 4, -1, 6, 1, NULL);
+ _ghoulHome2.setDetails(Rect(113, 22, 127, 33), 2700, 4, -1, 6, 1, NULL);
+ _ghoulHome3.setDetails(Rect(161, 44, 170, 52), 2700, 4, -1, 6, 1, NULL);
+ _ghoulHome4.setDetails(Rect(221, 19, 233, 31), 2700, 4, -1, 6, 1, NULL);
+ _ghoulHome5.setDetails(Rect(235, 59, 250, 75), 2700, 4, -1, 6, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2700, 4, -1, 6, 1, NULL);
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
@@ -3204,15 +3214,15 @@ void Scene2700::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(2, 2);
R2_GLOBALS._player.disableControl();
- if (R2_INVENTORY.getObjectScene(36) == 0)
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) == 0)
R2_GLOBALS._sound1.changeSound(234);
if (R2_GLOBALS._sceneManager._previousScene == 2750) {
_sceneMode = 2702;
- _field412 = 5;
+ _areaMode = 5;
setAction(&_sequenceManager, this, 2702, &R2_GLOBALS._player, NULL);
} else {
- _field412 = 0;
+ _areaMode = 0;
if (R2_GLOBALS._sceneManager._previousScene == 3900) {
_sceneMode = 2701;
setAction(&_sequenceManager, this, 2701, &R2_GLOBALS._player, NULL);
@@ -3227,26 +3237,26 @@ void Scene2700::postInit(SceneObjectList *OwnerList) {
void Scene2700::signal() {
switch (_sceneMode) {
case 10:
- switch (_field414) {
+ switch (_moveMode) {
case 1:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 2:
case 4:
case 6:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2705, &R2_GLOBALS._player, NULL);
break;
case 3: {
- _sceneMode = _field414;
- _field412 = 1;
+ _sceneMode = _moveMode;
+ _areaMode = 1;
Common::Point pt(80, 127);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
break;
}
case 5:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default: // includes case 1
@@ -3254,24 +3264,24 @@ void Scene2700::signal() {
}
break;
case 2:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 6:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2706, &R2_GLOBALS._player, NULL);
break;
case 3:
case 4: {
- _sceneMode = _field414;
- _field412 = 2;
+ _sceneMode = _moveMode;
+ _areaMode = 2;
Common::Point pt(155, 127);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
break;
}
case 5:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default: // includes case 2
@@ -3279,21 +3289,21 @@ void Scene2700::signal() {
}
break;
case 3:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 2:
case 4:
case 6: {
- _sceneMode = _field414;
- _field412 = 3;
+ _sceneMode = _moveMode;
+ _areaMode = 3;
Common::Point pt(115, 152);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
break;
}
case 5:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default: // includes case 3
@@ -3301,21 +3311,21 @@ void Scene2700::signal() {
}
break;
case 4:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 6:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2706, &R2_GLOBALS._player, NULL);
break;
case 2:
case 3:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2709, &R2_GLOBALS._player, NULL);
break;
case 4:
case 5:
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2704, &R2_GLOBALS._player, NULL);
break;
default:
@@ -3323,21 +3333,21 @@ void Scene2700::signal() {
}
break;
case 5:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 6:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2706, &R2_GLOBALS._player, NULL);
break;
case 2:
case 3:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2709, &R2_GLOBALS._player, NULL);
break;
case 4: {
- _sceneMode = _field414;
- _field412 = 5;
+ _sceneMode = _moveMode;
+ _areaMode = 5;
Common::Point pt(285, 132);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3348,11 +3358,11 @@ void Scene2700::signal() {
}
break;
case 6:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 3: {
- _sceneMode = _field414;
- _field412 = 6;
+ _sceneMode = _moveMode;
+ _areaMode = 6;
Common::Point pt(250, 162);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3361,11 +3371,11 @@ void Scene2700::signal() {
case 1:
case 2:
case 4:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2707, &R2_GLOBALS._player, NULL);
break;
case 5:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default:
@@ -3373,21 +3383,21 @@ void Scene2700::signal() {
}
break;
case 2703:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 3:
case 6:
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
setAction(&_sequenceManager, this, 2703, &R2_GLOBALS._player, NULL);
break;
case 1:
case 2:
case 4:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2707, &R2_GLOBALS._player, NULL);
break;
case 5:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default:
@@ -3395,21 +3405,21 @@ void Scene2700::signal() {
}
break;
case 2704:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 6:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2706, &R2_GLOBALS._player, NULL);
break;
case 2:
case 3:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2709, &R2_GLOBALS._player, NULL);
break;
case 4:
case 5:
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2704, &R2_GLOBALS._player, NULL);
break;
default:
@@ -3417,23 +3427,23 @@ void Scene2700::signal() {
}
break;
case 2710:
- switch (_field412) {
+ switch (_areaMode) {
case 0:
case 1:
case 3:
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2707, &R2_GLOBALS._player, NULL);
break;
case 2:
case 5: {
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
Common::Point pt(164, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
break;
}
case 4:
- _field412 = 4;
+ _areaMode = 4;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2708, &R2_GLOBALS._player, NULL);
break;
default:
@@ -3445,36 +3455,36 @@ void Scene2700::signal() {
}
break;
case 11:
- R2_INVENTORY.setObjectScene(36, 0);
+ R2_INVENTORY.setObjectScene(R2_FLUTE, 0);
R2_GLOBALS._player.disableControl();
- _field412 = 0;
+ _areaMode = 0;
_sceneMode = 2700;
- setAction(&_sequenceManager, this, 2700, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2700, &_nej, NULL);
break;
case 12:
R2_GLOBALS._sound1.play(234);
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_sceneMode = 2711;
- _stripManager.start(_field416, this);
+ _stripManager.start(_stripNumber, this);
break;
case 13:
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_sceneMode = 2712;
- _stripManager.start(_field416, this);
+ _stripManager.start(_stripNumber, this);
break;
case 14:
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_sceneMode = 2713;
- _stripManager.start(_field416, this);
+ _stripManager.start(_stripNumber, this);
break;
case 15:
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
_sceneMode = 11;
- _stripManager.start(_field416, this);
+ _stripManager.start(_stripNumber, this);
break;
case 2700:
- _actor1.remove();
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ _nej.remove();
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 2703:
g_globals->_sceneManager.changeScene(3900);
@@ -3483,31 +3493,32 @@ void Scene2700::signal() {
g_globals->_sceneManager.changeScene(2750);
break;
case 2710:
- _field416 = 1200;
+ // Start of Nej assault
+ _stripNumber = 1200;
_sceneMode = 12;
- _actor1.postInit();
- setAction(&_sequenceManager, this, 2710, &R2_GLOBALS._player, &_actor1, NULL);
+ _nej.postInit();
+ setAction(&_sequenceManager, this, 2710, &R2_GLOBALS._player, &_nej, NULL);
break;
case 2711:
R2_GLOBALS._player.disableControl();
- _field416 = 1201;
+ _stripNumber = 1201;
_sceneMode = 13;
- setAction(&_sequenceManager, this, 2711, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2711, &R2_GLOBALS._player, &_nej, NULL);
break;
case 2712:
R2_GLOBALS._player.disableControl();
- _field416 = 1202;
+ _stripNumber = 1202;
_sceneMode = 14;
- setAction(&_sequenceManager, this, 2712, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2712, &R2_GLOBALS._player, &_nej, NULL);
break;
case 2713:
R2_GLOBALS._player.disableControl();
- _field416 = 1203;
- _sceneMode = 14;
- setAction(&_sequenceManager, this, 2713, &R2_GLOBALS._player, &_actor1, NULL);
+ _stripNumber = 1203;
+ _sceneMode = 15;
+ setAction(&_sequenceManager, this, 2713, &R2_GLOBALS._player, &_nej, NULL);
break;
default:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
@@ -3516,10 +3527,11 @@ void Scene2700::process(Event &event) {
if (R2_GLOBALS._events.getCursor() == R2_FLUTE) {
if (R2_GLOBALS._player._bounds.contains(event.mousePos)) {
_sceneMode = 10;
- _field414 = 2710;
+ _moveMode = 2710;
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- switch (_field412) {
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
+
+ switch (_areaMode) {
case 0: {
_sceneMode = 2710;
Common::Point pt(164, 160);
@@ -3566,46 +3578,47 @@ void Scene2700::process(Event &event) {
default:
break;
}
- event.handled = true;
} else {
- SceneItem::display(2700, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(2700, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
- } else if (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN) {
- if (_rect1.contains(event.mousePos)) {
- if (!_rect1.contains(R2_GLOBALS._player._position)) {
+
+ event.handled = true;
+ } else if (R2_GLOBALS._events.getCursor() == CURSOR_WALK) {
+ if (_walkRect1.contains(event.mousePos)) {
+ if (!_walkRect1.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 1;
+ _moveMode = 1;
}
- } else if (_rect2.contains(event.mousePos)) {
- if (!_rect2.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect2.contains(event.mousePos)) {
+ if (!_walkRect2.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 2;
+ _moveMode = 2;
}
- } else if (_rect3.contains(event.mousePos)) {
- if (!_rect3.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect3.contains(event.mousePos)) {
+ if (!_walkRect3.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 3;
+ _moveMode = 3;
}
- } else if (_rect4.contains(event.mousePos)) {
- if (!_rect4.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect4.contains(event.mousePos)) {
+ if (!_walkRect4.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 4;
+ _moveMode = 4;
}
- } else if (_rect5.contains(event.mousePos)) {
- if (!_rect5.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect5.contains(event.mousePos)) {
+ if (!_walkRect5.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 5;
+ _moveMode = 5;
}
- } else if (_rect6.contains(event.mousePos)) {
- if (!_rect6.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect6.contains(event.mousePos)) {
+ if (!_walkRect6.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 6;
+ _moveMode = 6;
}
} else {
event.handled = true;
@@ -3613,9 +3626,9 @@ void Scene2700::process(Event &event) {
}
if (_sceneMode == 10) {
R2_GLOBALS._player.disableControl();
- switch (_field412) {
+ switch (_areaMode) {
case 0:
- if (_field414 >= 6) {
+ if (_moveMode >= 6) {
Common::Point pt(205, 162);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3638,11 +3651,11 @@ void Scene2700::process(Event &event) {
break;
}
case 3:
- if (_field414 == 1) {
+ if (_moveMode == 1) {
Common::Point pt(80, 137);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
- } else if (_field414 == 6) {
+ } else if (_moveMode == 6) {
Common::Point pt(140, 162);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3653,7 +3666,7 @@ void Scene2700::process(Event &event) {
}
break;
case 4:
- if (_field414 == 5) {
+ if (_moveMode == 5) {
Common::Point pt(235, 132);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3685,19 +3698,20 @@ void Scene2700::process(Event &event) {
}
/*--------------------------------------------------------------------------
- * Scene 2750 - Forest Maze
+ * Scene 2750 - Inner Forest
*
*--------------------------------------------------------------------------*/
+
Scene2750::Scene2750(): SceneExt() {
- _field412 = _field414 = _field416 = 0;
+ _areaMode = _moveMode = _stripNumber = 0;
}
void Scene2750::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
+ s.syncAsSint16LE(_areaMode);
+ s.syncAsSint16LE(_moveMode);
+ s.syncAsSint16LE(_stripNumber);
}
void Scene2750::Action1::signal() {
@@ -3707,20 +3721,20 @@ void Scene2750::Action1::signal() {
case 1:
setDelay(60 + R2_GLOBALS._randomSource.getRandomNumber(240));
_actionIndex = 2;
- scene->_actor5.show();
- scene->_actor5.animate(ANIM_MODE_8, 1, NULL);
+ scene->_bird2.show();
+ scene->_bird2.animate(ANIM_MODE_8, 1, NULL);
break;
case 2:
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(600));
_actionIndex = 0;
- scene->_actor5.show();
- scene->_actor3.animate(ANIM_MODE_2, NULL);
+ scene->_bird2.show();
+ scene->_bird1.animate(ANIM_MODE_2, NULL);
break;
default:
setDelay(30);
_actionIndex = 1;
- scene->_actor3.animate(ANIM_MODE_6, NULL);
- scene->_actor4.animate(ANIM_MODE_8, 1, NULL);
+ scene->_bird1.animate(ANIM_MODE_6, NULL);
+ scene->_folliage1.animate(ANIM_MODE_8, 1, NULL);
break;
}
}
@@ -3729,20 +3743,20 @@ void Scene2750::Action2::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor6.animate(ANIM_MODE_8, 1, NULL);
+ scene->_folliage2.animate(ANIM_MODE_8, 1, NULL);
}
void Scene2750::Action3::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
- if (scene->_actor7._position.x <= 320) {
+ if (scene->_folliage3._position.x <= 320) {
setDelay(1800 + R2_GLOBALS._randomSource.getRandomNumber(600));
} else {
setDelay(60);
- scene->_actor7.setPosition(Common::Point(-10, 25));
+ scene->_folliage3.setPosition(Common::Point(-10, 25));
Common::Point pt(330, 45);
NpcMover *mover = new NpcMover();
- scene->_actor7.addMover(mover, &pt, NULL);
+ scene->_folliage3.addMover(mover, &pt, NULL);
}
}
@@ -3750,38 +3764,38 @@ void Scene2750::Action4::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor8.animate(ANIM_MODE_8, 1, NULL);
+ scene->_folliage4.animate(ANIM_MODE_8, 1, NULL);
}
void Scene2750::Action5::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor9.animate(ANIM_MODE_8, 1, NULL);
+ scene->_folliage5.animate(ANIM_MODE_8, 1, NULL);
}
void Scene2750::Action6::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor10.animate(ANIM_MODE_8, 1, NULL);
+ scene->_folliage6.animate(ANIM_MODE_8, 1, NULL);
}
void Scene2750::Action7::signal() {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
setDelay(600 + R2_GLOBALS._randomSource.getRandomNumber(300));
- scene->_actor11.animate(ANIM_MODE_8, 1, NULL);
+ scene->_folliage7.animate(ANIM_MODE_8, 1, NULL);
}
-void Scene2750::Area1::process(Event &event) {
+void Scene2750::WestExit::process(Event &event) {
SceneArea::process(event);
if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 10;
- scene->_field414 = 2752;
- switch (scene->_field412) {
+ scene->_moveMode = 2752;
+ switch (scene->_areaMode) {
case 1: {
scene->_sceneMode = 2752;
scene->setAction(&scene->_sequenceManager, scene, 2752, &R2_GLOBALS._player, NULL);
@@ -3805,14 +3819,14 @@ void Scene2750::Area1::process(Event &event) {
}
}
-void Scene2750::Area2::process(Event &event) {
+void Scene2750::EastExit::process(Event &event) {
SceneArea::process(event);
if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._player._canWalk) && (_bounds.contains(event.mousePos))) {
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 10;
- scene->_field414 = 2753;
- switch (scene->_field412) {
+ scene->_moveMode = 2753;
+ switch (scene->_areaMode) {
case 1: {
Common::Point pt(140, 142);
NpcMover *mover = new NpcMover();
@@ -3840,93 +3854,93 @@ void Scene2750::postInit(SceneObjectList *OwnerList) {
loadScene(2750);
R2_GLOBALS._sound2.stop();
SceneExt::postInit();
- _area1.setDetails(Rect(0, 90, 20, 135), EXITCURSOR_W);
- _area2.setDetails(Rect(300, 90, 320, 135), EXITCURSOR_E);
+ _westExit.setDetails(Rect(0, 90, 20, 135), EXITCURSOR_W);
+ _eastExit.setDetails(Rect(300, 90, 320, 135), EXITCURSOR_E);
- _rect1.set(30, 127, 155, 147);
- _rect2.set(130, 142, 210, 167);
- _rect3.set(-1, 137, 290, 147);
+ _walkRect1.set(30, 127, 155, 147);
+ _walkRect2.set(130, 142, 210, 167);
+ _walkRect3.set(-1, 137, 290, 147);
- if (R2_INVENTORY.getObjectScene(36) == 0) {
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) == 0) {
R2_GLOBALS._sound1.changeSound(235);
- _actor2.postInit();
- _actor2.setup(2751, 1, 1);
- _actor2.setPosition(Common::Point(104, 158));
- _actor2.animate(ANIM_MODE_2, NULL);
- }
-
- _actor3.postInit();
- _actor3.setup(2750, 1, 1);
- _actor3.setPosition(Common::Point(188, 34));
- _actor3.animate(ANIM_MODE_2, NULL);
- _actor3._numFrames = 16;
-
- _actor4.postInit();
- _actor4.setup(2700, 4, 1);
- _actor4.setPosition(Common::Point(188, 37));
- _actor4.fixPriority(26);
-
- _actor5.postInit();
- _actor5.setup(2750, 2, 1);
- _actor5.setPosition(Common::Point(188, 34));
- _actor5.hide();
-
- _actor3.setAction(&_action1);
-
- _actor6.postInit();
- _actor6.setup(2750, 3, 1);
- _actor6.setPosition(Common::Point(9, 167));
- _actor6.fixPriority(252);
- _actor6.setAction(&_action2);
-
- _actor7.postInit();
- _actor7.setup(2750, 4, 1);
- _actor7.setPosition(Common::Point(-10, 25));
- _actor7.animate(ANIM_MODE_1, NULL);
- _actor7.setStrip2(4);
- _actor7._moveRate = 20;
- _actor7.setAction(&_action3);
-
- _actor8.postInit();
- _actor8.fixPriority(26);
- _actor8.setup(2750, 5, 1);
- _actor8.setPosition(Common::Point(258, 33));
- _actor8.setAction(&_action4);
-
- _actor9.postInit();
- _actor9.fixPriority(26);
- _actor9.setup(2750, 6, 1);
- _actor9.setPosition(Common::Point(61, 38));
- _actor9.setAction(&_action5);
-
- _actor10.postInit();
- _actor10.fixPriority(26);
- _actor10.setup(2750, 7, 1);
- _actor10.setPosition(Common::Point(69, 37));
- _actor10.setAction(&_action6);
-
- _actor11.postInit();
- _actor11.fixPriority(26);
- _actor11.setup(2750, 8, 1);
- _actor11.setPosition(Common::Point(80, 35));
- _actor11.setAction(&_action7);
-
- _item2.setDetails(Rect(29, 50, 35, 56), 2750, 3, -1, 5, 1, NULL);
- _item3.setDetails(Rect(47, 36, 54, 42), 2750, 3, -1, 5, 1, NULL);
- _item4.setDetails(Rect(193, 21, 206, 34), 2750, 3, -1, 5, 1, NULL);
- _item5.setDetails(Rect(301, 18, 315, 32), 2750, 3, -1, 5, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 2700, 0, -1, 2, 1, NULL);
+ _fire.postInit();
+ _fire.setup(2751, 1, 1);
+ _fire.setPosition(Common::Point(104, 158));
+ _fire.animate(ANIM_MODE_2, NULL);
+ }
+
+ _bird1.postInit();
+ _bird1.setup(2750, 1, 1);
+ _bird1.setPosition(Common::Point(188, 34));
+ _bird1.animate(ANIM_MODE_2, NULL);
+ _bird1._numFrames = 16;
+
+ _folliage1.postInit();
+ _folliage1.setup(2700, 4, 1);
+ _folliage1.setPosition(Common::Point(188, 37));
+ _folliage1.fixPriority(26);
+
+ _bird2.postInit();
+ _bird2.setup(2750, 2, 1);
+ _bird2.setPosition(Common::Point(188, 34));
+ _bird2.hide();
+
+ _bird1.setAction(&_action1);
+
+ _folliage2.postInit();
+ _folliage2.setup(2750, 3, 1);
+ _folliage2.setPosition(Common::Point(9, 167));
+ _folliage2.fixPriority(252);
+ _folliage2.setAction(&_action2);
+
+ _folliage3.postInit();
+ _folliage3.setup(2750, 4, 1);
+ _folliage3.setPosition(Common::Point(-10, 25));
+ _folliage3.animate(ANIM_MODE_1, NULL);
+ _folliage3.setStrip2(4);
+ _folliage3._moveRate = 20;
+ _folliage3.setAction(&_action3);
+
+ _folliage4.postInit();
+ _folliage4.fixPriority(26);
+ _folliage4.setup(2750, 5, 1);
+ _folliage4.setPosition(Common::Point(258, 33));
+ _folliage4.setAction(&_action4);
+
+ _folliage5.postInit();
+ _folliage5.fixPriority(26);
+ _folliage5.setup(2750, 6, 1);
+ _folliage5.setPosition(Common::Point(61, 38));
+ _folliage5.setAction(&_action5);
+
+ _folliage6.postInit();
+ _folliage6.fixPriority(26);
+ _folliage6.setup(2750, 7, 1);
+ _folliage6.setPosition(Common::Point(69, 37));
+ _folliage6.setAction(&_action6);
+
+ _folliage7.postInit();
+ _folliage7.fixPriority(26);
+ _folliage7.setup(2750, 8, 1);
+ _folliage7.setPosition(Common::Point(80, 35));
+ _folliage7.setAction(&_action7);
+
+ _ghoulHome1.setDetails(Rect(29, 50, 35, 56), 2750, 3, -1, 5, 1, NULL);
+ _ghoulHome2.setDetails(Rect(47, 36, 54, 42), 2750, 3, -1, 5, 1, NULL);
+ _ghoulHome3.setDetails(Rect(193, 21, 206, 34), 2750, 3, -1, 5, 1, NULL);
+ _ghoulHome4.setDetails(Rect(301, 18, 315, 32), 2750, 3, -1, 5, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2700, 0, -1, 2, 1, NULL);
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
_stripManager.addSpeaker(&_quinnSpeaker);
_stripManager.addSpeaker(&_nejSpeaker);
- if (R2_INVENTORY.getObjectScene(36) == 0) {
- _actor1.postInit();
- _actor1.setup(2752, 5, 1);
- _actor1.animate(ANIM_MODE_NONE, NULL);
- _actor1.setPosition(Common::Point(101, 148));
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) == 0) {
+ _nej.postInit();
+ _nej.setup(2752, 5, 1);
+ _nej.animate(ANIM_MODE_NONE, NULL);
+ _nej.setPosition(Common::Point(101, 148));
}
R2_GLOBALS._player.postInit();
@@ -3936,47 +3950,49 @@ void Scene2750::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._sceneManager._previousScene == 2700) {
- if (R2_INVENTORY.getObjectScene(36) == 0) {
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) == 0) {
R2_GLOBALS._player.setVisage(2752);
R2_GLOBALS._player.setStrip(6);
R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL);
R2_GLOBALS._player.setPosition(Common::Point(81, 165));
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- _field416 = 1204;
+
+ R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ _stripNumber = 1204;
_sceneMode = 11;
- _stripManager.start(_field416, this);
+ _stripManager.start(_stripNumber, this);
} else {
_sceneMode = 2750;
- _field412 = 1;
+ _areaMode = 1;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2750, &R2_GLOBALS._player, NULL);
}
} else if (R2_GLOBALS._sceneManager._previousScene == 2800) {
_sceneMode = 2751;
- _field412 = 3;
+ _areaMode = 3;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2751, &R2_GLOBALS._player, NULL);
} else {
- _field412 = 1;
+ _areaMode = 1;
R2_GLOBALS._player.setPosition(Common::Point(90, 137));
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS._player.enableControl();
}
}
+
void Scene2750::signal() {
switch (_sceneMode) {
case 10:
- switch (_field414) {
+ switch (_moveMode) {
case 1:
- switch (_field412) {
+ switch (_areaMode) {
case 2: {
- _sceneMode = _field414;
- _field412 = 1;
+ _sceneMode = _moveMode;
+ _areaMode = 1;
Common::Point pt(90, 137);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 3: {
- _field412 = 2;
+ _areaMode = 2;
Common::Point pt(140, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -3987,25 +4003,25 @@ void Scene2750::signal() {
}
break;
case 2: {
- _sceneMode = _field414;
- _field412 = 2;
+ _sceneMode = _moveMode;
+ _areaMode = 2;
Common::Point pt(170, 162);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 3:
- switch (_field412) {
+ switch (_areaMode) {
case 1: {
- _field412 = 2;
+ _areaMode = 2;
Common::Point pt(210, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 2: {
- _sceneMode = _field414;
- _field412 = 3;
+ _sceneMode = _moveMode;
+ _areaMode = 3;
Common::Point pt(270, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -4016,20 +4032,20 @@ void Scene2750::signal() {
}
break;
case 2752:
- switch (_field412) {
+ switch (_areaMode) {
case 1:
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
setAction(&_sequenceManager, this, 2752, &R2_GLOBALS._player, NULL);
break;
case 2: {
- _field412 = 1;
+ _areaMode = 1;
Common::Point pt(20, 132);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 3: {
- _field412 = 2;
+ _areaMode = 2;
Common::Point pt(140, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -4040,23 +4056,23 @@ void Scene2750::signal() {
}
break;
case 2753:
- switch (_field412) {
+ switch (_areaMode) {
case 1: {
- _field412 = 2;
+ _areaMode = 2;
Common::Point pt(210, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 2: {
- _field412 = 3;
+ _areaMode = 3;
Common::Point pt(300, 132);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
case 3:
- _sceneMode = _field414;
+ _sceneMode = _moveMode;
setAction(&_sequenceManager, this, 2753, &R2_GLOBALS._player, NULL);
break;
default:
@@ -4076,30 +4092,31 @@ void Scene2750::signal() {
g_globals->_sceneManager.changeScene(2700);
break;
default:
- R2_GLOBALS._player.enableControl(R2_NEGATOR_GUN);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
void Scene2750::process(Event &event) {
- if ((R2_GLOBALS._player._canWalk) && (event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN)) {
- if (_rect1.contains(event.mousePos)) {
- if (!_rect1.contains(R2_GLOBALS._player._position)) {
+ if ((R2_GLOBALS._player._canWalk) && (event.eventType == EVENT_BUTTON_DOWN)
+ && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN)) {
+ if (_walkRect1.contains(event.mousePos)) {
+ if (!_walkRect1.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 1;
+ _moveMode = 1;
}
- } else if (_rect2.contains(event.mousePos)) {
- if (!_rect2.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect2.contains(event.mousePos)) {
+ if (!_walkRect2.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 2;
+ _moveMode = 2;
}
- } else if (_rect3.contains(event.mousePos)) {
- if (!_rect3.contains(R2_GLOBALS._player._position)) {
+ } else if (_walkRect3.contains(event.mousePos)) {
+ if (!_walkRect3.contains(R2_GLOBALS._player._position)) {
event.handled = true;
_sceneMode = 10;
- _field414 = 3;
+ _moveMode = 3;
}
} else {
event.handled = true;
@@ -4108,7 +4125,7 @@ void Scene2750::process(Event &event) {
if (_sceneMode == 10) {
R2_GLOBALS._player.disableControl();
- switch (_field412) {
+ switch (_areaMode) {
case 1: {
Common::Point pt(140, 142);
NpcMover *mover = new NpcMover();
@@ -4116,7 +4133,7 @@ void Scene2750::process(Event &event) {
}
break;
case 2:
- if (_field414 == 1) {
+ if (_moveMode == 1) {
Common::Point pt(140, 142);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
@@ -4141,23 +4158,24 @@ void Scene2750::process(Event &event) {
}
/*--------------------------------------------------------------------------
- * Scene 2800 - Exiting forest
+ * Scene 2800 - Guard post
*
*--------------------------------------------------------------------------*/
+
Scene2800::Scene2800(): SceneExt() {
- _field412 = 0;
+ _stripNumber = 0;
}
void Scene2800::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_stripNumber);
}
-bool Scene2800::Item2::startAction(CursorType action, Event &event) {
- Scene2800 *scene = (Scene2800 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene2800::Outpost::startAction(CursorType action, Event &event) {
if ((action == CURSOR_USE) && (R2_GLOBALS.getFlag(47))) {
+ Scene2800 *scene = (Scene2800 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 2805;
scene->setAction(&scene->_sequenceManager, scene, 2805, &R2_GLOBALS._player, NULL);
@@ -4166,23 +4184,23 @@ bool Scene2800::Item2::startAction(CursorType action, Event &event) {
return SceneHotspot::startAction(action, event);
}
-bool Scene2800::Actor1::startAction(CursorType action, Event &event) {
+bool Scene2800::Guard::startAction(CursorType action, Event &event) {
Scene2800 *scene = (Scene2800 *)R2_GLOBALS._sceneManager._scene;
if (action == CURSOR_TALK) {
R2_GLOBALS._player.disableControl();
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
R2_GLOBALS.setFlag(47);
- scene->_field412 = 1205;
+ scene->_stripNumber = 1205;
scene->_sceneMode = 2803;
- scene->_stripManager.start(scene->_field412, scene);
+ scene->_stripManager.start(scene->_stripNumber, scene);
return true;
} else if (action == R2_SONIC_STUNNER) {
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
R2_GLOBALS._player.disableControl();
R2_GLOBALS.setFlag(47);
scene->_sceneMode = 10;
- scene->setAction(&scene->_sequenceManager, scene, 2802, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 2802, &R2_GLOBALS._player, &scene->_nej, &scene->_guard, NULL);
return true;
} else
return SceneActor::startAction(action, event);
@@ -4195,10 +4213,10 @@ void Scene2800::Action1::signal() {
setDelay(120);
Common::Point pt(330, 25);
NpcMover *mover = new NpcMover();
- scene->_object1.addMover(mover, &pt, NULL);
+ scene->_bird.addMover(mover, &pt, NULL);
} else {
setDelay(1800 + R2_GLOBALS._randomSource.getRandomNumber(600));
- scene->_object1.setPosition(Common::Point(-10, 45));
+ scene->_bird.setPosition(Common::Point(-10, 45));
}
}
@@ -4253,37 +4271,37 @@ void Scene2800::Action2::signal() {
case 4:
setDelay(18);
_object4.setStrip(4);
- scene->_actor1.setVisage(2800);
- scene->_actor1.setStrip(5);
- scene->_actor1.setFrame(1);
- scene->_actor1._numFrames = 5;
- scene->_actor1._moveRate = 5;
- scene->_actor1.setPosition(Common::Point(300, 104));
- scene->_actor1.fixPriority(110);
- scene->_actor1.changeZoom(100);
- scene->_actor1.show();
+ scene->_guard.setVisage(2800);
+ scene->_guard.setStrip(5);
+ scene->_guard.setFrame(1);
+ scene->_guard._numFrames = 5;
+ scene->_guard._moveRate = 5;
+ scene->_guard.setPosition(Common::Point(300, 104));
+ scene->_guard.fixPriority(110);
+ scene->_guard.changeZoom(100);
+ scene->_guard.show();
break;
case 5:
- scene->_actor1.animate(ANIM_MODE_5, this);
+ scene->_guard.animate(ANIM_MODE_5, this);
break;
case 6: {
- scene->_actor1.changeZoom(-1);
- scene->_actor1.setVisage(3107);
- scene->_actor1.animate(ANIM_MODE_1, NULL);
- scene->_actor1.setStrip(3);
- scene->_actor1.setPosition(Common::Point(297, 140));
- scene->_actor1._numFrames = 10;
- scene->_actor1._moveRate = 10;
- scene->_actor1._moveDiff = Common::Point(3, 2);
+ scene->_guard.changeZoom(-1);
+ scene->_guard.setVisage(3107);
+ scene->_guard.animate(ANIM_MODE_1, NULL);
+ scene->_guard.setStrip(3);
+ scene->_guard.setPosition(Common::Point(297, 140));
+ scene->_guard._numFrames = 10;
+ scene->_guard._moveRate = 10;
+ scene->_guard._moveDiff = Common::Point(3, 2);
Common::Point pt(297, 160);
NpcMover *mover = new NpcMover();
- scene->_actor1.addMover(mover, &pt, this);
+ scene->_guard.addMover(mover, &pt, this);
break;
}
case 7: {
- scene->_actor1.changeZoom(75);
- scene->_actor1.updateAngle(R2_GLOBALS._player._position);
+ scene->_guard.changeZoom(75);
+ scene->_guard.updateAngle(R2_GLOBALS._player._position);
Common::Point pt(105, 82);
NpcMover *mover = new NpcMover();
@@ -4309,7 +4327,7 @@ void Scene2800::Action2::signal() {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.setObjectWrapper(new SceneObjectWrapper());
- Common::Point pt(100, 64);
+ Common::Point pt(64, 100);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
break;
@@ -4338,9 +4356,9 @@ void Scene2800::Action2::signal() {
break;
}
case 13:
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- scene->_field412 = 1207;
- scene->_stripManager.start(scene->_field412, this);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
+ scene->_stripNumber = 1207;
+ scene->_stripManager.start(scene->_stripNumber, this);
break;
case 14: {
R2_GLOBALS._player.disableControl();
@@ -4353,7 +4371,7 @@ void Scene2800::Action2::signal() {
}
case 15:
setDelay(18);
- scene->_actor1.updateAngle(R2_GLOBALS._player._position);
+ scene->_guard.updateAngle(R2_GLOBALS._player._position);
R2_GLOBALS._player.setVisage(2800);
R2_GLOBALS._player.setStrip(6);
R2_GLOBALS._player.setFrame(1);
@@ -4406,34 +4424,34 @@ void Scene2800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound2.stop();
SceneExt::postInit();
- _object1.postInit();
- _object1.setup(2750, 4, 1);
- _object1.setPosition(Common::Point(-10, 25));
- _object1.animate(ANIM_MODE_1, NULL);
- _object1.setStrip2(4);
- _object1._moveRate = 20;
- _object1.setAction(&_action1);
-
- _actor3.postInit();
- _actor3.setup(2802, 1, 1);
- _actor3.setPosition(Common::Point(116, 80));
- _actor3.fixPriority(111);
- _actor3.animate(ANIM_MODE_2, NULL);
- _actor3._numFrames = 6;
+ _bird.postInit();
+ _bird.setup(2750, 4, 1);
+ _bird.setPosition(Common::Point(-10, 25));
+ _bird.animate(ANIM_MODE_1, NULL);
+ _bird.setStrip2(4);
+ _bird._moveRate = 20;
+ _bird.setAction(&_action1);
+
+ _lightBar.postInit();
+ _lightBar.setup(2802, 1, 1);
+ _lightBar.setPosition(Common::Point(116, 80));
+ _lightBar.fixPriority(111);
+ _lightBar.animate(ANIM_MODE_2, NULL);
+ _lightBar._numFrames = 6;
if (!R2_GLOBALS.getFlag(47)) {
- _actor1.postInit();
- _actor1.setVisage(3105);
- _actor1.setStrip(3);
- _actor1.setFrame(1);
- _actor1.setZoom(50);
- _actor1._moveDiff = Common::Point(2, 1);
- _actor1.setPosition(Common::Point(122, 82));
- _actor1.animate(ANIM_MODE_NONE, NULL);
- _actor1.setDetails(2800, -1, -1, -1, 1, (SceneItem *)NULL);
+ _guard.postInit();
+ _guard.setVisage(3105);
+ _guard.setStrip(3);
+ _guard.setFrame(1);
+ _guard.setZoom(50);
+ _guard._moveDiff = Common::Point(2, 1);
+ _guard.setPosition(Common::Point(122, 82));
+ _guard.animate(ANIM_MODE_NONE, NULL);
+ _guard.setDetails(2800, -1, -1, -1, 1, (SceneItem *)NULL);
}
- _item1.setDetails(Rect(0, 0, 320, 200), 2800, -1, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 2800, -1, -1, -1, 1, NULL);
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
@@ -4441,17 +4459,17 @@ void Scene2800::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_nejSpeaker);
_stripManager.addSpeaker(&_guardSpeaker);
- if (R2_INVENTORY.getObjectScene(36) == 0) {
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) == 0) {
R2_GLOBALS._sound1.fadeSound(237);
if (R2_GLOBALS.getFlag(47)) {
- _item2.setDetails(Rect(76, 45, 155, 90), 2800, 3, -1, -1, 2, NULL);
+ _outpost.setDetails(Rect(76, 45, 155, 90), 2800, 3, -1, -1, 2, NULL);
} else {
- _actor2.postInit();
- _actor2.setup(2752, 5, 1);
- _actor2.animate(ANIM_MODE_NONE, NULL);
- _actor2.changeZoom(100);
- _actor2._moveDiff = Common::Point(2, 1);
- _actor2.setPosition(Common::Point(101, 148));
+ _nej.postInit();
+ _nej.setup(2752, 5, 1);
+ _nej.animate(ANIM_MODE_NONE, NULL);
+ _nej.changeZoom(100);
+ _nej._moveDiff = Common::Point(2, 1);
+ _nej.setPosition(Common::Point(101, 148));
}
}
@@ -4462,7 +4480,8 @@ void Scene2800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(2, 2);
R2_GLOBALS._player.disableControl();
- if (R2_INVENTORY.getObjectScene(36) == 0) {
+ if (R2_INVENTORY.getObjectScene(R2_FLUTE) != 0) {
+ _sceneMode = 2800;
R2_GLOBALS._player.setAction(&_sequenceManager, this, 2800, &R2_GLOBALS._player, NULL);
} else if (R2_GLOBALS.getFlag(47)) {
R2_GLOBALS._player.setVisage(3110);
@@ -4472,7 +4491,8 @@ void Scene2800::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.enableControl();
} else {
_sceneMode = 2801;
- R2_GLOBALS._player.setAction(&_sequenceManager, this, 2801, &R2_GLOBALS._player, &_actor2, &_actor1, NULL);
+ R2_GLOBALS._player.setAction(&_sequenceManager, this, 2801, &R2_GLOBALS._player,
+ &_nej, &_guard, NULL);
}
}
@@ -4480,17 +4500,17 @@ void Scene2800::signal() {
switch (_sceneMode) {
case 10:
R2_GLOBALS._sound1.play(238);
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- _field412 = 1206;
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
+ _stripNumber = 1206;
_sceneMode = 2804;
- _stripManager.start(_field412, this);
+ _stripManager.start(_stripNumber, this);
break;
case 11:
- _actor2.remove();
- _object1.setAction(NULL);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ _nej.remove();
+ _bird.setAction(NULL);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- _item2.setDetails(Rect(76, 45, 155, 90), 2800, 3, -1, -1, 2, NULL);
+ _outpost.setDetails(Rect(76, 45, 155, 90), 2800, 3, -1, -1, 2, NULL);
break;
case 12:
R2_GLOBALS._sound1.fadeOut2(NULL);
@@ -4501,21 +4521,21 @@ void Scene2800::signal() {
g_globals->_sceneManager.changeScene(2750);
break;
case 2801:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
R2_GLOBALS._player._canWalk = false;
break;
case 2803:
R2_GLOBALS._player.disableControl();
_sceneMode = 10;
- setAction(&_sequenceManager, this, 2803, &R2_GLOBALS._player, &_actor2, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 2803, &R2_GLOBALS._player, &_nej, &_guard, NULL);
break;
case 2804:
R2_GLOBALS._player.disableControl();
_sceneMode = 11;
- setAction(&_sequenceManager, this, 2804, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 2804, &R2_GLOBALS._player, &_nej, NULL);
break;
case 2805:
- _object1.remove();
+ _bird.remove();
setAction(&_action2);
break;
default:
@@ -4523,5 +4543,668 @@ void Scene2800::signal() {
}
}
+/*--------------------------------------------------------------------------
+ * Scene 2900 - Balloon Cutscene
+ *
+ *--------------------------------------------------------------------------*/
+
+bool Scene2900::Scenery::startAction(CursorType action, Event &event) {
+ switch (action) {
+ case CURSOR_USE:
+ SceneItem::display2(1, 5 + R2_GLOBALS._randomSource.getRandomNumber(5));
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(2900, 0);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(1, 10 + R2_GLOBALS._randomSource.getRandomNumber(5));
+ break;
+ default:
+ break;
+ }
+
+ event.handled = true;
+ return true;
+}
+
+bool Scene2900::ControlPanel::startAction(CursorType action, Event &event) {
+ switch (action) {
+ case CURSOR_USE:
+ SceneItem::display2(2900, 5);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(2900, 3);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(2900, 4);
+ break;
+ default:
+ break;
+ }
+
+ event.handled = true;
+ return true;
+}
+
+bool Scene2900::Altimeter::startAction(CursorType action, Event &event) {
+ switch (action) {
+ case CURSOR_USE:
+ SceneItem::display2(2900, 8);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(2900, 6);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(2900, 4);
+ break;
+ default:
+ break;
+ }
+
+ event.handled = true;
+ return true;
+}
+
+bool Scene2900::KnobLeft::startAction(CursorType action, Event &event) {
+ Scene2900 *scene = (Scene2900 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_USE:
+ if (scene->_majorMinorFlag || scene->_altitudeChanging ||
+ scene->_xAmount != scene->_xComparison) {
+ // Let your altitude stablize first
+ SceneItem::display2(2900, 17);
+ } else if (R2_GLOBALS._balloonAltitude / 48 == 0) {
+ // Maximum altitude
+ SceneItem::display2(2900, 15);
+ } else {
+ // Increase altitude
+ R2_GLOBALS._sound2.fadeSound(282);
+ scene->_altitudeChanging = true;
+ scene->_altitudeMajorChange = -1;
+ scene->_xComparison = 100 - ((R2_GLOBALS._balloonAltitude / 48) - 1) * 25;
+ }
+ break;
+
+ case CURSOR_LOOK:
+ SceneItem::display2(2900, 9);
+ break;
+
+ case CURSOR_TALK:
+ SceneItem::display2(2900, 4);
+ break;
+
+ default:
+ break;
+ }
+
+ event.handled = true;
+ return true;
+}
+
+bool Scene2900::KnobRight::startAction(CursorType action, Event &event) {
+ switch (action) {
+ case CURSOR_USE: {
+ Scene2900 *scene = (Scene2900 *)R2_GLOBALS._sceneManager._scene;
+
+ if (scene->_majorMinorFlag || scene->_altitudeChanging ||
+ scene->_xAmount != scene->_xComparison) {
+ // Let your altitude stablize first
+ SceneItem::display2(2900, 17);
+ } else if (R2_GLOBALS._balloonAltitude / 48 >= 3) {
+ // Altitude is too low - cannot land here
+ SceneItem::display2(2900, 16);
+ } else {
+ // Decrease altitude
+ R2_GLOBALS._sound2.fadeSound(212);
+ scene->_altitudeChanging = true;
+ scene->_altitudeMajorChange = 1;
+ scene->_xComparison = 100 - ((R2_GLOBALS._balloonAltitude / 48) + 1) * 25;
+ }
+ break;
+ }
+
+ case CURSOR_LOOK:
+ SceneItem::display2(2900, 12);
+ break;
+
+ case CURSOR_TALK:
+ SceneItem::display2(2900, 4);
+ break;
+
+ default:
+ break;
+ }
+
+ event.handled = true;
+ return true;
+}
+
+bool Scene2900::Skip::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE) {
+ Scene2900 *scene = (Scene2900 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 12;
+ scene->signal();
+ }
+
+ return true;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene2900::Action1::signal() {
+ Scene2900 *scene = (Scene2900 *)R2_GLOBALS._sceneManager._scene;
+ setDelay(3);
+
+ if (!scene->_majorMinorFlag && !scene->_altitudeChanging) {
+ scene->_fadeCounter = 2;
+ scene->_controlsActiveChanging = false;
+ } else if (scene->_majorMinorFlag) {
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ } else if (scene->_fadeCounter == 0) {
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ } else if (!scene->_controlsActiveChanging) {
+ scene->_knobLeftContent.hide();
+ scene->_knobRightContent.hide();
+ scene->_controlsActiveChanging = true;
+ } else {
+ --scene->_fadeCounter;
+ scene->_knobLeftContent.show();
+ scene->_knobRightContent.show();
+ scene->_controlsActiveChanging = false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene2900::Map::Map() {
+ _mapWidth = _mapHeight = 0;
+ _resNum = 0;
+ _xV = _yV = 0;
+ _bounds = Rect(40, 0, 280, 150);
+}
+
+void Scene2900::Map::load(int resNum) {
+ byte *data = g_resourceManager->getResource(RES_BITMAP, resNum, 9999);
+
+ _resNum = resNum;
+ _xV = _yV = 0;
+ _mapWidth = READ_LE_UINT16(data);
+ _mapHeight = READ_LE_UINT16(data + 2);
+
+ DEALLOCATE(data);
+}
+
+Common::Point Scene2900::Map::setPosition(const Common::Point &pos, bool initialFlag) {
+ Common::Point p = pos;
+ Rect updateRect;
+
+ if (p.x >= 0) {
+ int xRight = p.x + _bounds.width();
+ if (xRight > _mapWidth) {
+ p.x = _mapWidth - _bounds.width();
+ }
+ } else {
+ p.x = 0;
+ }
+
+ if (p.y >= 0) {
+ int yBottom = p.y + _bounds.height();
+ if (yBottom > _mapHeight) {
+ p.y = _mapHeight - _bounds.height();
+ }
+ } else {
+ p.y = 0;
+ }
+
+ if ((p.x != 0 || p.y != 0) && !initialFlag) {
+ moveArea(updateRect, _xV - p.x, _yV - p.y);
+ redraw(&updateRect);
+ } else {
+ redraw();
+ }
+
+ _xV = p.x;
+ _yV = p.y;
+ return Common::Point(_xV, _yV);
+}
+
+void Scene2900::Map::redraw(Rect *updateRect) {
+ int xHalfCount = _mapWidth / 160;
+ int yHalfCount = _mapHeight / 100;
+ int rlbNum = 0;
+
+ Rect blockRect(0, 0, 160, 100);
+ Rect screenRect = _bounds;
+ screenRect.translate(_xV - _bounds.left, _yV - _bounds.top);
+
+ Rect modifyRect;
+ if (updateRect)
+ modifyRect = *updateRect;
+
+ for (int xCtr = 0; xCtr < xHalfCount; ++xCtr) {
+ for (int yCtr = 0; yCtr < yHalfCount; ++yCtr, ++rlbNum) {
+ blockRect.moveTo(160 * xCtr, 100 * yCtr);
+ if (blockRect.intersects(screenRect)) {
+ // The block of the map is at least partially on-screen, so needs drawing
+ blockRect.translate(_bounds.left - _xV, _bounds.top - _yV);
+ byte *data = g_resourceManager->getResource(RES_BITMAP, _resNum, rlbNum);
+
+ drawBlock(data, blockRect.left, blockRect.top, _bounds, modifyRect);
+
+ DEALLOCATE(data);
+ }
+ }
+ }
+}
+
+void Scene2900::Map::synchronize(Serializer &s) {
+ s.syncAsUint16LE(_resNum);
+ if (s.isLoading())
+ load(_resNum);
+
+ s.syncAsSint16LE(_xV);
+ s.syncAsSint16LE(_yV);
+ _bounds.synchronize(s);
+}
+
+int Scene2900::Map::adjustRect(Common::Rect &r1, const Common::Rect &r2) {
+ if (r2.contains(r1))
+ return 0;
+ if (!r2.intersects(r1))
+ return 1;
+
+ if (r1.top >= r2.top && r1.bottom <= r2.bottom) {
+ if (r1.left >= r2.left && r1.left < r2.right) {
+ r1.left = r2.right - 1;
+ return 1;
+ }
+ if (r1.right > r2.left && r1.right <= r2.right) {
+ r1.right = r2.left + 1;
+ return 1;
+ }
+ }
+
+ if (r1.left < r2.left || r1.right > r2.right)
+ return -1;
+
+ if (r1.top >= r2.top && r1.top < r2.bottom) {
+ r1.top = r2.bottom - 1;
+ return 1;
+ }
+ if (r1.bottom > r2.top && r1.bottom <= r2.bottom) {
+ r1.bottom = r2.top + 1;
+ return 1;
+ }
+
+ return -1;
+}
+
+void Scene2900::Map::drawBlock(const byte *data, int xp, int yp,
+ const Rect &bounds, const Rect &updateRect) {
+ Rect blockRect(xp, yp, xp + 160, yp + 100);
+ const byte *src = data;
+
+ if (blockRect.intersects(bounds)) {
+ blockRect.clip(bounds);
+
+ if (adjustRect(blockRect, updateRect) != 0) {
+ int width = blockRect.width();
+ int height = blockRect.height();
+ src += (blockRect.top - yp) * 160 + blockRect.left - xp;
+
+ GfxSurface &surface = R2_GLOBALS._sceneManager._scene->_backSurface;
+ Graphics::Surface s = surface.lockSurface();
+
+ for (int yCtr = 0; yCtr < height; ++yCtr, src += 160) {
+ byte *destP = (byte *)s.getBasePtr(blockRect.left, blockRect.top + yCtr);
+ Common::copy(src, src + width, destP);
+ }
+
+ surface.unlockSurface();
+ R2_GLOBALS.gfxManager().copyFrom(surface, blockRect, blockRect);
+ }
+ }
+}
+
+void Scene2900::Map::moveArea(Rect &r, int xAmt, int yAmt) {
+ Rect tempRect = r;
+ tempRect.translate(xAmt, yAmt);
+ int xpSrc, xpDest, width;
+ int ypSrc, ypDest, height;
+
+ if (tempRect.intersects(r)) {
+ if (xAmt >= 0) {
+ xpSrc = tempRect.left;
+ width = tempRect.width() - xAmt;
+ xpDest = tempRect.left + xAmt;
+ } else {
+ xpSrc = tempRect.left - xAmt;
+ width = tempRect.width() + xAmt;
+ xpDest = tempRect.left;
+ }
+
+ if (yAmt > 0) {
+ height = tempRect.height() - yAmt;
+ ypDest = tempRect.top + yAmt + (height - 1);
+ ypSrc = tempRect.top + (height - 1);
+
+ for (int yCtr = 0; yCtr < height; ++yCtr, --ypSrc, --ypDest) {
+ moveLine(xpSrc, ypSrc, xpDest, ypDest, width);
+ }
+ } else {
+ ypSrc = tempRect.top - yAmt;
+ height = tempRect.height() + yAmt;
+ ypDest = tempRect.top;
+
+ for (int yCtr = 0; yCtr < height; ++yCtr, ++ypSrc, ++ypDest) {
+ moveLine(xpSrc, ypSrc, xpDest, ypDest, width);
+ }
+ }
+ } else {
+ r = Rect(0, 0, 0, 0);
+ }
+}
+
+void Scene2900::Map::moveLine(int xpSrc, int ypSrc, int xpDest, int ypDest, int width) {
+ byte buffer[SCREEN_WIDTH];
+ assert(width <= SCREEN_WIDTH);
+
+ GfxSurface &surface = R2_GLOBALS.gfxManager().getSurface();
+ Graphics::Surface s = surface.lockSurface();
+
+ byte *srcP = (byte *)s.getBasePtr(xpSrc, ypSrc);
+ byte *destP = (byte *)s.getBasePtr(xpDest, ypDest);
+ Common::copy(srcP, srcP + width, &buffer[0]);
+ Common::copy(&buffer[0], &buffer[width], destP);
+
+ surface.unlockSurface();
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene2900::Scene2900(): SceneExt() {
+ _controlsActiveChanging = false;
+ _altitudeChanging = false;
+ _majorMinorFlag = false;
+ _balloonLocation = Common::Point(550, 550);
+ _altitudeMinorChange = 0;
+ _altitudeMajorChange = 0;
+ _balloonScreenPos = Common::Point(160, 100);
+ _newAltitude = 0;
+ _xAmount = 100;
+ _xComparison = 100;
+ _fadeCounter = 0;
+ _paletteReloadNeeded = false;
+}
+
+void Scene2900::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_controlsActiveChanging);
+ s.syncAsSint16LE(_altitudeChanging);
+ s.syncAsSint16LE(_majorMinorFlag);
+ s.syncAsSint16LE(_altitudeMinorChange);
+ s.syncAsSint16LE(_altitudeMajorChange);
+ s.syncAsSint16LE(_balloonLocation.x);
+ s.syncAsSint16LE(_balloonLocation.y);
+ s.syncAsSint16LE(_balloonScreenPos.x);
+ s.syncAsSint16LE(_balloonScreenPos.y);
+ s.syncAsSint16LE(_newAltitude);
+ s.syncAsSint16LE(_xAmount);
+ s.syncAsSint16LE(_xComparison);
+ s.syncAsSint16LE(_fadeCounter);
+ s.syncAsSint16LE(_paletteReloadNeeded);
+
+ _map.synchronize(s);
+}
+
+void Scene2900::postInit(SceneObjectList *OwnerList) {
+ R2_GLOBALS._uiElements._active = false;
+ // TODO: Determine correct colors
+ R2_GLOBALS._gfxColors.foreground = 228;
+ R2_GLOBALS._fontColors.background = 12;
+ R2_GLOBALS._fontColors.foreground = 22;
+
+ _map.load(2950);
+
+ loadScene(2900);
+ SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
+ _leftEdge.setup(2900, 6, 1, 22, 0, 25);
+ _rightEdge.setup(2900, 6, 1, 280, 0, 25);
+ _knob.setup(2900, 1, 3, 228, 199, 25);
+
+ _altimeterContent.postInit();
+ _altimeterContent.setVisage(2900);
+ _altimeterContent.setStrip(2);
+ _altimeterContent.setFrame(1);
+ _altimeterContent.fixPriority(10);
+
+ _knobLeftContent.postInit();
+ _knobLeftContent.setVisage(2900);
+ _knobLeftContent.setStrip(1);
+ _knobLeftContent.setFrame(1);
+ _knobLeftContent.setPosition(Common::Point(209, 199));
+ _knobLeftContent.fixPriority(200);
+
+ _knobRightContent.postInit();
+ _knobRightContent.setVisage(2900);
+ _knobRightContent.setStrip(1);
+ _knobRightContent.setFrame(2);
+ _knobRightContent.setPosition(Common::Point(247, 199));
+ _knobRightContent.fixPriority(200);
+
+ // Set up hotspots
+ _scenery.setDetails(Rect(0, 0, 320, 150), 2900, -1, -1, -1, 1, (SceneItem *)NULL);
+ _controlPanel.setDetails(Rect(0, 150, 320, 200), 2900, -1, -1, -1, 1, (SceneItem *)NULL);
+ _altimeter.setDetails(Rect(42, 164, 129, 190), 2900, -1, -1, -1, 2, (SceneItem *)NULL);
+ _knobLeft.setDetails(Rect(165, 160, 228, 200), 2900, -1, -1, -1, 2, (SceneItem *)NULL);
+ _knobRight.setDetails(Rect(228, 160, 285, 200), 2900, -1, -1, -1, 2, (SceneItem *)NULL);
+ _skip.postInit();
+ _skip.setBounds(185, 50, 200, 0);
+ R2_GLOBALS._sceneItems.push_front(&_skip);
+
+ // For ScummVM, we're introducing a Skip button, since the scene is a pain
+ _skipText._color1 = R2_GLOBALS._scenePalette._colors.foreground;
+ _skipText._color2 = R2_GLOBALS._scenePalette._colors.background;
+ _skipText.setPosition(Common::Point(0, 185));
+ _skipText.setup("Skip");
+
+ setAction(&_action1);
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.setVisage(2900);
+ R2_GLOBALS._player.setStrip2(3);
+ R2_GLOBALS._player.setFrame2(1);
+ R2_GLOBALS._player.fixPriority(15);
+ R2_GLOBALS._player._moveDiff = Common::Point(2, 2);
+ R2_GLOBALS._player.disableControl();
+
+ if (R2_GLOBALS._sceneManager._previousScene == 2350 &&
+ R2_GLOBALS._balloonPosition.x == 0 && R2_GLOBALS._balloonPosition.y == 0) {
+ R2_GLOBALS._balloonAltitude = 5;
+ _map.setPosition(Common::Point(_balloonLocation.x - 120, _balloonLocation.y - 100));
+ _sceneMode = 10;
+
+ R2_GLOBALS._player.changeZoom(100);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 180));
+ ADD_PLAYER_MOVER(160, 100);
+
+ _altimeterContent.setPosition(Common::Point(9, 189));
+ } else {
+ _balloonLocation.x = R2_GLOBALS._balloonPosition.x + 120;
+ _balloonLocation.y = R2_GLOBALS._balloonPosition.y + 100;
+
+ if ((R2_GLOBALS._balloonAltitude % 8) == 0)
+ _balloonLocation.x -= 70;
+ else if ((R2_GLOBALS._balloonAltitude % 8) == 7)
+ _balloonLocation.x += 70;
+
+ if (_balloonLocation.x <= 120)
+ _balloonScreenPos.x = _balloonLocation.x + 40;
+ else if (_balloonLocation.x >= 680)
+ _balloonScreenPos.x = _balloonLocation.x - 520;
+
+ if ((R2_GLOBALS._balloonAltitude / 6) == 5)
+ _balloonLocation.y -= 50;
+ if (_balloonLocation.y <= 100)
+ _balloonScreenPos.y = _balloonLocation.y;
+
+ _xAmount = _xComparison = 100 - (R2_GLOBALS._balloonAltitude / 48) * 25;
+ _map.setPosition(Common::Point(_balloonLocation.x - 120, _balloonLocation.y - 100));
+ _sceneMode = 11;
+
+ R2_GLOBALS._player.changeZoom(_xAmount);
+ R2_GLOBALS._player.setPosition(_balloonScreenPos);
+ R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player._canWalk = false;
+
+ _altimeterContent.setPosition(Common::Point(109 - _xAmount, 189));
+ }
+
+ R2_GLOBALS._sound1.play(211);
+}
+
+void Scene2900::remove() {
+ // TODO: Figure out correct colors
+ R2_GLOBALS._gfxColors.foreground = 59;
+ R2_GLOBALS._fontColors.background = 4;
+ R2_GLOBALS._fontColors.foreground = 15;
+
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._scenePalette.setEntry(255, 255, 255, 255);
+
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sound2.stop();
+
+ R2_GLOBALS._interfaceY = UI_INTERFACE_Y;
+ SceneExt::remove();
+}
+
+void Scene2900::signal() {
+ switch (_sceneMode) {
+ case 10:
+ _sceneMode = 11;
+ R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player._canWalk = false;
+ break;
+ case 12:
+ R2_GLOBALS._sceneManager.changeScene(2600);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene2900::dispatch() {
+ if (_sceneMode == 11) {
+ _balloonLocation.x += balloonData[R2_GLOBALS._balloonAltitude].x;
+ _balloonLocation.y += balloonData[R2_GLOBALS._balloonAltitude].y;
+ _altitudeMinorChange = balloonData[R2_GLOBALS._balloonAltitude].v3;
+
+ if (_altitudeMinorChange == 0) {
+ _majorMinorFlag = false;
+ } else {
+ _majorMinorFlag = true;
+ _altitudeChanging = false;
+ _xComparison = 100 - ((R2_GLOBALS._balloonAltitude / 48) + _altitudeMinorChange) * 25;
+ }
+
+ // Zooming/altitude balloon change
+ if (_xAmount == _xComparison) {
+ _majorMinorFlag = false;
+ } else {
+ if (!_majorMinorFlag) {
+ _xAmount = _xAmount - _altitudeMajorChange;
+ } else {
+ _xAmount = _xAmount - _altitudeMinorChange;
+ }
+
+ if (_altitudeMinorChange == -1 || _altitudeMajorChange == -1) {
+ if (_altimeterContent._frame == 1) {
+ _altimeterContent.setFrame2(10);
+ } else {
+ _altimeterContent.setFrame2(_altimeterContent._frame - 1);
+ }
+ } else if (_altitudeMinorChange == -1 || _altitudeMajorChange == 1) {
+ if (_altimeterContent._frame == 10)
+ _altimeterContent.setFrame2(1);
+ else
+ _altimeterContent.setFrame2(_altimeterContent._frame + 1);
+ }
+
+ _altimeterContent.setPosition(Common::Point(109 - _xAmount, 189));
+ R2_GLOBALS._player.changeZoom(_xAmount);
+ }
+
+ if (!_paletteReloadNeeded) {
+ R2_GLOBALS._scenePalette.loadPalette(2950);
+ R2_GLOBALS._scenePalette.refresh();
+ }
+
+ R2_GLOBALS._balloonPosition = _map.setPosition(
+ Common::Point(_balloonLocation.x - 120, _balloonLocation.y - 100), !_paletteReloadNeeded);
+ _paletteReloadNeeded = true;
+
+ if (_balloonLocation.x <= 120)
+ _balloonScreenPos.x = _balloonLocation.x + 40;
+ else if (_balloonLocation.x >= 680)
+ _balloonScreenPos.x = _balloonLocation.x - 520;
+
+ if (_balloonLocation.y <= 100)
+ _balloonScreenPos.y = _balloonLocation.y;
+
+ R2_GLOBALS._player.setPosition(_balloonScreenPos);
+
+ if ((_balloonLocation.x % 100) == 50 && (_balloonLocation.y % 100) == 50 && !_majorMinorFlag) {
+ // At an altitude change point, so calculate new altitude
+ _newAltitude = R2_GLOBALS._balloonAltitude;
+ if (_altitudeChanging) {
+ _newAltitude += _altitudeMajorChange * 48;
+ _altitudeChanging = false;
+ }
+
+ if (balloonData[R2_GLOBALS._balloonAltitude].x > 0) {
+ ++_newAltitude;
+ } else if (balloonData[R2_GLOBALS._balloonAltitude].x < 0) {
+ --_newAltitude;
+ }
+
+ if (balloonData[R2_GLOBALS._balloonAltitude].y > 0) {
+ _newAltitude -= 8;
+ } else if (balloonData[R2_GLOBALS._balloonAltitude].y < 0) {
+ _newAltitude += 8;
+ }
+
+ if (balloonData[R2_GLOBALS._balloonAltitude].v3 > 0) {
+ _newAltitude += 48;
+ } else if (balloonData[R2_GLOBALS._balloonAltitude].v3 < 0) {
+ _newAltitude -= 48;
+ }
+
+ assert(_newAltitude < 193);
+ R2_GLOBALS._balloonAltitude = _newAltitude;
+ if (R2_GLOBALS._balloonAltitude == 189) {
+ // Finally reached landing point
+ _sceneMode = 12;
+ R2_GLOBALS._player.disableControl();
+
+ ADD_MOVER(R2_GLOBALS._player, 160, -10);
+ }
+ }
+ }
+
+ Scene::dispatch();
+}
+
+void Scene2900::refreshBackground(int xAmount, int yAmount) {
+ SceneExt::refreshBackground(xAmount, yAmount);
+
+ _map.redraw();
+}
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.h b/engines/tsage/ringworld2/ringworld2_scenes2.h
index 281d1da366..3960d93f94 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.h
@@ -45,23 +45,23 @@ class Scene2000 : public SceneExt {
virtual void signal();
};
- class Exit1 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit4 : public SceneExit {
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit5 : public SceneExit {
+ class DoorExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -69,17 +69,18 @@ public:
bool _exitingFlag;
int _mazePlayerMode;
- NamedHotspot _item1;
- SceneActor _object1;
- SceneActor _objList1[11];
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
- Exit4 _exit4;
- Exit5 _exit5;
+ NamedHotspot _background;
+ SceneActor _companion;
+ SceneActor _persons[11];
+ WestExit _westExit;
+ EastExit _eastExit;
+ SouthExit _southExit;
+ NorthExit _northExit;
+ DoorExit _doorExit;
Action1 _action1, _action2, _action3, _action4, _action5;
SequenceManager _sequenceManager;
+ Scene2000();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void signal();
@@ -91,10 +92,10 @@ public:
};
class Scene2350 : public SceneExt {
- class Actor2 : public SceneActor {
+ class Companion : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Balloon : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
@@ -105,14 +106,13 @@ class Scene2350 : public SceneExt {
virtual void changeScene();
};
public:
-
SpeakerQuinn _quinnSpeaker;
SpeakerPharisha _pharishaSpeaker;
- NamedHotspot _item1;
- SceneActor _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Actor3 _actor4;
+ NamedHotspot _background;
+ SceneActor _person;
+ Companion _companion;
+ Balloon _balloon;
+ Balloon _harness;
ExitUp _exitUp;
ExitWest _exitWest;
SequenceManager _sequenceManager;
@@ -120,19 +120,18 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void signal();
- virtual void process(Event &event);
};
class Scene2400 : public SceneExt {
- class Exit1 : public SceneExit {
+ class WestExit : public SceneExit {
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class EastExit : public SceneExit {
virtual void changeScene();
};
public:
- Exit1 _exit1;
- Exit2 _exit2;
+ WestExit _westExit;
+ EastExit _eastExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -140,45 +139,45 @@ public:
};
class Scene2425 : public SceneExt {
- class Item1 : public NamedHotspot {
+ class RopeDest1 : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item2 : public NamedHotspot {
+ class RopeDest2 : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item3 : public NamedHotspot {
+ class Crevasse : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item4 : public NamedHotspot {
+ class Background : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor1 : public SceneActor {
+ class Rope : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Pictographs : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthEastExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- Item1 _item1;
- Item2 _item2;
- Item3 _item3;
- Item4 _item4;
- Actor1 _actor1;
- Actor2 _actor2;
- Actor2 _actor3;
- Exit1 _exit1;
+ RopeDest1 _ropeDest1;
+ RopeDest2 _ropeDest2;
+ Crevasse _crevasse;
+ Background _background;
+ Rope _rope;
+ Pictographs _pictographs1;
+ Pictographs _pictographs2;
+ SouthEastExit _southEastExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -187,41 +186,41 @@ public:
};
class Scene2430 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class GunPowder : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class OilLamp : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- NamedHotspot _item7;
- NamedHotspot _item8;
- NamedHotspot _item9;
- NamedHotspot _item10;
- NamedHotspot _item11;
- NamedHotspot _item12;
- NamedHotspot _item13;
- Actor1 _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _bottles2;
+ NamedHotspot _furnishings;
+ NamedHotspot _rug1;
+ NamedHotspot _mirror;
+ NamedHotspot _garments;
+ NamedHotspot _bed;
+ NamedHotspot _towel;
+ NamedHotspot _bottles1;
+ NamedHotspot _post;
+ NamedHotspot _clothesPile1;
+ NamedHotspot _clothesPile2;
+ NamedHotspot _rug2;
+ Companion _companion;
+ GunPowder _gunPowder;
+ OilLamp _oilLamp;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -229,16 +228,16 @@ public:
};
class Scene2435 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Astor : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -246,12 +245,12 @@ public:
SpeakerQuinn2435 _quinnSpeaker;
SpeakerSeeker2435 _seekerSpeaker;
SpeakerPharisha2435 _pharishaSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- Actor1 _actor1;
- Actor2 _actor2;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _leftWindow;
+ NamedHotspot _rightWindow;
+ Companion _companion;
+ Astor _astor;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -260,30 +259,30 @@ public:
};
class Scene2440 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class OilLamp : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthEastExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- NamedHotspot _item7;
- Actor1 _actor1;
- Actor2 _actor2;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _garments;
+ NamedHotspot _bedspread;
+ NamedHotspot _post;
+ NamedHotspot _rug;
+ NamedHotspot _furnishings;
+ NamedHotspot _bottles;
+ Companion _companion;
+ OilLamp _oilLamp;
+ SouthEastExit _southEastExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -300,16 +299,16 @@ public:
};
class Scene2450 : public SceneExt {
- class Actor2 : public SceneActor {
+ class Parker : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class CareTaker : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthWestExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -317,13 +316,13 @@ public:
SpeakerQuinn2450 _quinnSpeaker;
SpeakerSeeker2450 _seekerSpeaker;
SpeakerCaretaker2450 _caretakerSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- SceneActor _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _post;
+ NamedHotspot _bedspread;
+ SceneActor _companion;
+ Parker _parker;
+ CareTaker _careTaker;
+ SouthWestExit _southWestExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -332,29 +331,29 @@ public:
};
class Scene2455 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Lamp : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Pool : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class ScrithKey : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- Actor1 _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Exit1 _exit1;
+ NamedHotspot _background;
+ Lamp _lamp;
+ Pool _pool;
+ ScrithKey _scrithKey;
+ NorthExit _northExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -363,7 +362,7 @@ public:
};
class Scene2500 : public SceneExt {
- class Exit1 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -372,11 +371,11 @@ public:
SpeakerSeeker _seekerSpeaker;
SpeakerMiranda _mirandaSpeaker;
SpeakerWebbster2500 _webbsterSpeaker;
- NamedHotspot _item1;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Exit1 _exit1;
+ NamedHotspot _background;
+ SceneActor _companion;
+ SceneActor _quinn;
+ SceneActor _ship;
+ WestExit _westExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -384,30 +383,30 @@ public:
};
class Scene2525 : public SceneExt {
- class Item5 : public NamedHotspot {
+ class StopCock : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class GlassDome : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- Item5 _item5;
- SceneActor _actor1;
- SceneActor _actor2;
- Actor3 _actor3;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _machine;
+ NamedHotspot _pipes1;
+ NamedHotspot _pipes2;
+ StopCock _stopcock;
+ SceneActor _companion;
+ SceneActor _compressor;
+ GlassDome _glassDome;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -416,29 +415,29 @@ public:
};
class Scene2530 : public SceneExt {
- class Actor2 : public SceneActor {
+ class Flask : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Crank : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
+ NamedHotspot _background;
+ NamedHotspot _crank2;
+ NamedHotspot _shelf;
NamedHotspot _item4;
- NamedHotspot _item5;
- SceneActor _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Exit1 _exit1;
+ NamedHotspot _rope;
+ SceneActor _companion;
+ Flask _flask;
+ Crank _crank;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -446,32 +445,32 @@ public:
};
class Scene2535 : public SceneExt {
- class Actor3 : public SceneActor {
+ class RebreatherTank : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class TannerMask : public SceneActor {
public:
bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- NamedHotspot _item7;
- SceneActor _actor1;
- SceneActor _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _roof;
+ NamedHotspot _skin1;
+ NamedHotspot _skin2;
+ NamedHotspot _skin3;
+ NamedHotspot _skin4;
+ NamedHotspot _depression;
+ SceneActor _companion;
+ SceneActor _rope;
+ RebreatherTank _rebreatherTank;
+ TannerMask _tannerMask;
+ SouthExit _southExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -508,37 +507,38 @@ class Scene2700 : public SceneExt {
void signal();
};
- class Area1: public SceneArea {
+ class SouthExit: public SceneArea {
public:
void process(Event &event);
};
- class Area2: public SceneArea {
+ class EastExit: public SceneArea {
public:
void process(Event &event);
};
public:
SpeakerQuinn2700 _quinnSpeaker;
SpeakerNej2700 _nejSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- NamedHotspot _item6;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
+ NamedHotspot _background;
+ NamedHotspot _ghoulHome1;
+ NamedHotspot _ghoulHome2;
+ NamedHotspot _ghoulHome3;
+ NamedHotspot _ghoulHome4;
+ NamedHotspot _ghoulHome5;
+ SceneActor _nej;
+ SceneActor _ghoulHome6;
+ SceneActor _ghoulHome7;
+ SceneActor _ghoulHome8;
+ SceneActor _ghoulHome9;
Action1 _action1;
Action2 _action2;
Action3 _action3;
Action4 _action4;
- Area1 _area1;
- Area2 _area2;
- Rect _rect1, _rect2, _rect3, _rect4, _rect5, _rect6;
+ SouthExit _southExit;
+ EastExit _eastExit;
+ Rect _walkRect1, _walkRect2, _walkRect3;
+ Rect _walkRect4, _walkRect5, _walkRect6;
SequenceManager _sequenceManager;
- int _field412, _field414, _field416;
+ int _areaMode, _moveMode, _stripNumber;
Scene2700();
virtual void synchronize(Serializer &s);
@@ -577,33 +577,33 @@ class Scene2750 : public SceneExt {
void signal();
};
- class Area1: public SceneArea {
+ class WestExit: public SceneArea {
public:
void process(Event &event);
};
- class Area2: public SceneArea {
+ class EastExit: public SceneArea {
public:
void process(Event &event);
};
public:
SpeakerQuinn2750 _quinnSpeaker;
SpeakerNej2750 _nejSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
- SceneActor _actor10;
- SceneActor _actor11;
+ NamedHotspot _background;
+ NamedHotspot _ghoulHome1;
+ NamedHotspot _ghoulHome2;
+ NamedHotspot _ghoulHome3;
+ NamedHotspot _ghoulHome4;
+ SceneActor _nej;
+ SceneActor _fire;
+ SceneActor _bird1;
+ SceneActor _folliage1;
+ SceneActor _bird2;
+ SceneActor _folliage2;
+ SceneActor _folliage3;
+ SceneActor _folliage4;
+ SceneActor _folliage5;
+ SceneActor _folliage6;
+ SceneActor _folliage7;
Action1 _action1;
Action2 _action2;
Action3 _action3;
@@ -611,11 +611,11 @@ public:
Action5 _action5;
Action6 _action6;
Action7 _action7;
- Area1 _area1;
- Area2 _area2;
- Rect _rect1, _rect2, _rect3;
+ WestExit _westExit;
+ EastExit _eastExit;
+ Rect _walkRect1, _walkRect2, _walkRect3;
SequenceManager _sequenceManager;
- int _field412, _field414, _field416;
+ int _areaMode, _moveMode, _stripNumber;
Scene2750();
virtual void synchronize(Serializer &s);
@@ -625,12 +625,12 @@ public:
};
class Scene2800 : public SceneExt {
- class Item2 : public NamedHotspot {
+ class Outpost : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor1 : public SceneActor {
+ class Guard : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
@@ -649,16 +649,16 @@ public:
SpeakerQuinn2800 _quinnSpeaker;
SpeakerNej2800 _nejSpeaker;
SpeakerGuard2800 _guardSpeaker;
- NamedHotspot _item1;
- Item2 _item2;
- Actor1 _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneObject _object1;
+ NamedHotspot _background;
+ Outpost _outpost;
+ Guard _guard;
+ SceneActor _nej;
+ SceneActor _lightBar;
+ SceneObject _bird;
Action1 _action1;
Action2 _action2;
SequenceManager _sequenceManager;
- int _field412;
+ int _stripNumber;
Scene2800();
virtual void synchronize(Serializer &s);
@@ -666,6 +666,97 @@ public:
virtual void signal();
};
+class Scene2900 : public SceneExt {
+ /* Items */
+ class Scenery : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class ControlPanel : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Altimeter : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class KnobLeft : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class KnobRight : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Skip : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ /* Actions */
+ class Action1: public Action {
+ public:
+ void signal();
+ };
+
+ /* Miscellaneous */
+ class Map {
+ private:
+ void moveArea(Rect &r, int xAmt, int yAmt);
+ void moveLine(int xpSrc, int ypSrc, int xpDest, int ypDest, int width);
+ int adjustRect(Common::Rect &r1, const Common::Rect &r2);
+ void drawBlock(const byte *data, int xp, int yp, const Rect &r1, const Rect &r2);
+ public:
+ int _mapWidth, _mapHeight;
+ int _resNum;
+ int _xV, _yV;
+ Rect _bounds;
+
+ Map();
+ void load(int resNum);
+ Common::Point setPosition(const Common::Point &pos, bool initialFlag = false);
+ void synchronize(Serializer &s);
+ void redraw(Rect *updateRect = NULL);
+ };
+public:
+ SceneObject _leftEdge;
+ SceneObject _rightEdge;
+ SceneObject _knob;
+ SceneObject _altimeterContent;
+ SceneObject _knobRightContent;
+ SceneObject _knobLeftContent;
+ Scenery _scenery;
+ ControlPanel _controlPanel;
+ Altimeter _altimeter;
+ KnobLeft _knobLeft;
+ KnobRight _knobRight;
+ Skip _skip;
+ Action1 _action1;
+ Map _map;
+ SceneText _skipText;
+
+ bool _controlsActiveChanging;
+ bool _altitudeChanging;
+ bool _majorMinorFlag;
+ int _altitudeMinorChange;
+ int _altitudeMajorChange;
+ Common::Point _balloonLocation;
+ Common::Point _balloonScreenPos;
+ int _newAltitude;
+ int _xAmount;
+ int _xComparison;
+ int _fadeCounter;
+ bool _paletteReloadNeeded;
+
+ Scene2900();
+ virtual void synchronize(Serializer &s);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
+ virtual void refreshBackground(int xAmount, int yAmount);
+};
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index 61711d0a4f..732add03ec 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -30,17 +30,18 @@ namespace TsAGE {
namespace Ringworld2 {
/*--------------------------------------------------------------------------
- * Scene 3100 -
+ * Scene 3100 - ARM Base Hanager
*
*--------------------------------------------------------------------------*/
+
Scene3100::Scene3100() {
- _field412 = 0;
+ _fadeSound = false;
}
void Scene3100::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_fadeSound);
}
bool Scene3100::Guard::startAction(CursorType action, Event &event) {
@@ -58,12 +59,12 @@ bool Scene3100::Guard::startAction(CursorType action, Event &event) {
void Scene3100::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene == 1000) {
- if (R2_GLOBALS._player._oldCharacterScene[1] == 3100) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_QUINN] == 3100) {
loadScene(3101);
R2_GLOBALS._uiElements._active = false;
} else {
loadScene(3100);
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
+ _sceneBounds = Rect(160, 0, 480, SCREEN_HEIGHT);
}
} else {
loadScene(3100);
@@ -83,20 +84,21 @@ void Scene3100::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._characterIndex = R2_QUINN;
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _item2.setDetails(Rect(212, 97, 320, 114), 3100, 3, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 480, 200), 3100, 0, -1, -1, 1, NULL);
- _field412 = 0;
+ _hammerHead.postInit();
+ _hammerHead2.setDetails(Rect(212, 97, 320, 114), 3100, 3, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 480, 200), 3100, 0, -1, -1, 1, NULL);
+ _fadeSound = false;
if (R2_GLOBALS._sceneManager._previousScene == 1000) {
- if (R2_GLOBALS._player._oldCharacterScene[1] == 3100) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_QUINN] == 3100) {
_sceneMode = 3102;
- _actor3.postInit();
- _actor4.postInit();
- _actor5.postInit();
+ _ghoul.postInit();
+ _technicians.postInit();
+ _deadBodies.postInit();
R2_GLOBALS._sound1.play(274);
_sound1.fadeSound(130);
- setAction(&_sequenceManager, this, 3102, &_actor1, &R2_GLOBALS._player, &_actor3, &_actor4, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 3102, &_hammerHead, &R2_GLOBALS._player,
+ &_ghoul, &_technicians, &_deadBodies, NULL);
} else {
_guard.postInit();
_guard.setup(3110, 5, 1);
@@ -104,27 +106,28 @@ void Scene3100::postInit(SceneObjectList *OwnerList) {
_guard.setPosition(Common::Point(10, 149));
_guard.setDetails(3100, 6, -1, -1, 2, (SceneItem *)NULL);
- _actor4.postInit();
- _actor4.setup(3103, 1, 1);
- _actor4.setPosition(Common::Point(278, 113));
- _actor4.setDetails(3100, 9, -1, -1, 2, (SceneItem *)NULL);
- _actor4.animate(ANIM_MODE_2, NULL);
+ _technicians.postInit();
+ _technicians.setup(3103, 1, 1);
+ _technicians.setPosition(Common::Point(278, 113));
+ _technicians.setDetails(3100, 9, -1, -1, 2, (SceneItem *)NULL);
+ _technicians.animate(ANIM_MODE_2, NULL);
- _field412 = 1;
- _actor1.setDetails(3100, 3, -1, -1, 2, (SceneItem *)NULL);
+ _fadeSound = true;
+ _hammerHead.setDetails(3100, 3, -1, -1, 2, (SceneItem *)NULL);
R2_GLOBALS._sound1.play(243);
R2_GLOBALS._sound2.play(130);
_sceneMode = 3100;
- setAction(&_sequenceManager, this, 3100, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 3100, &R2_GLOBALS._player, &_hammerHead, NULL);
}
} else if (R2_GLOBALS._sceneManager._previousScene == 3255) {
_sceneMode = 3101;
- _actor2.postInit();
- _actor3.postInit();
- _field412 = 1;
+ _miranda.postInit();
+ _ghoul.postInit();
+ _fadeSound = true;
- setAction(&_sequenceManager, this, 3101, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3101, &R2_GLOBALS._player, &_hammerHead,
+ &_miranda, &_ghoul, NULL);
} else {
_guard.postInit();
_guard.setup(3110, 5, 1);
@@ -132,28 +135,28 @@ void Scene3100::postInit(SceneObjectList *OwnerList) {
_guard.setPosition(Common::Point(10, 149));
_guard.setDetails(3100, 6, -1, -1, 2, (SceneItem *)NULL);
- _actor4.postInit();
- _actor4.setup(3103, 1, 1);
- _actor4.setPosition(Common::Point(278, 113));
- _actor4.setDetails(3100, 9, -1, -1, 2, (SceneItem *)NULL);
- _actor4.animate(ANIM_MODE_2, NULL);
+ _technicians.postInit();
+ _technicians.setup(3103, 1, 1);
+ _technicians.setPosition(Common::Point(278, 113));
+ _technicians.setDetails(3100, 9, -1, -1, 2, (SceneItem *)NULL);
+ _technicians.animate(ANIM_MODE_2, NULL);
- _actor1.postInit();
- _actor1.setup(3104, 4, 1);
- _actor1.setPosition(Common::Point(143, 104));
- _actor1.setDetails(3100, 3, -1, -1, 2, (SceneItem *)NULL);
+ _hammerHead.postInit();
+ _hammerHead.setup(3104, 4, 1);
+ _hammerHead.setPosition(Common::Point(143, 104));
+ _hammerHead.setDetails(3100, 3, -1, -1, 2, (SceneItem *)NULL);
R2_GLOBALS._player.setup(3110, 3, 1);
R2_GLOBALS._player.changeZoom(50);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.setPosition(Common::Point(160, 150));
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
R2_GLOBALS._sound1.play(243);
}
- R2_GLOBALS._player._oldCharacterScene[1] = 3100;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 3100;
}
void Scene3100::remove() {
@@ -172,29 +175,29 @@ void Scene3100::signal() {
case 3100:
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 3101:
R2_GLOBALS._sceneManager.changeScene(1000);
break;
case 3102:
- R2_GLOBALS._player._oldCharacterScene[1] = 1000;
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 1000;
R2_GLOBALS._sceneManager.changeScene(1000);
break;
default:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
void Scene3100::dispatch() {
- if ((_sceneMode == 3100) && (_field412 != 0) && (R2_GLOBALS._player._position.y == 104)) {
- _field412 = 0;
+ if ((_sceneMode == 3100) && _fadeSound && (R2_GLOBALS._player._position.y == 104)) {
+ _fadeSound = false;
R2_GLOBALS._sound2.fadeOut2(NULL);
}
- if ((_sceneMode == 3101) && (_field412 != 0) && (R2_GLOBALS._player._position.y < 104)) {
- _field412 = 0;
+ if ((_sceneMode == 3101) && _fadeSound && (R2_GLOBALS._player._position.y < 104)) {
+ _fadeSound = false;
_sound1.fadeSound(130);
}
@@ -205,54 +208,56 @@ void Scene3100::dispatch() {
* Scene 3125 - Ghouls dormitory
*
*--------------------------------------------------------------------------*/
+
Scene3125::Scene3125() {
- _field412 = 0;
+ _soundPlayed = false;
}
void Scene3125::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_soundPlayed);
}
-bool Scene3125::Item1::startAction(CursorType action, Event &event) {
- Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3125::Background::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_USE:
if (_useLineNum != -1)
- SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
case CURSOR_LOOK:
if (_lookLineNum != -1)
- SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
case CURSOR_TALK:
if (_talkLineNum != -1)
- SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
- default:
+ default: {
+ Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
return scene->display(action, event);
+ }
break;
}
return true;
}
-bool Scene3125::Item2::startAction(CursorType action, Event &event) {
- Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3125::Table::startAction(CursorType action, Event &event) {
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3125;
- scene->setAction(&scene->_sequenceManager1, scene, 3125, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3125, &R2_GLOBALS._player, NULL);
+ }
break;
case CURSOR_LOOK:
- SceneItem::display(3125, 15, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3125, 15, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
case CURSOR_TALK:
- SceneItem::display(3125, 13, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3125, 13, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
default:
return SceneHotspot::startAction(action, event);
@@ -262,21 +267,24 @@ bool Scene3125::Item2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3125::Item3::startAction(CursorType action, Event &event) {
- Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3125::Computer::startAction(CursorType action, Event &event) {
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
- scene->_actor5.postInit();
+ scene->_ghoul4.postInit();
scene->_sceneMode = 3126;
- scene->setAction(&scene->_sequenceManager1, scene, 3126, &R2_GLOBALS._player, &scene->_actor2, &scene->_actor3, &scene->_actor4, &scene->_actor1, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3126, &R2_GLOBALS._player,
+ &scene->_ghoul1, &scene->_ghoul2, &scene->_ghoul3, &scene->_door,
+ &scene->_ghoul4, NULL);
+ }
break;
case CURSOR_LOOK:
- SceneItem::display(3125, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3125, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
case CURSOR_TALK:
- SceneItem::display(3125, 13, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3125, 13, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
break;
default:
return SceneHotspot::startAction(action, event);
@@ -286,68 +294,68 @@ bool Scene3125::Item3::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3125::Actor1::startAction(CursorType action, Event &event) {
- Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3125::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
+ Scene3125 *scene = (Scene3125 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3176;
- scene->setAction(&scene->_sequenceManager1, scene, 3176, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3176, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
}
void Scene3125::postInit(SceneObjectList *OwnerList) {
loadScene(3125);
SceneExt::postInit();
- _field412 = 0;
+ _soundPlayed = false;
- _actor1.postInit();
- _actor1.setup(3175, 1, 1);
- _actor1.setPosition(Common::Point(35, 72));
- _actor1.setDetails(3125, 12, 13, -1, 1, (SceneItem *)NULL);
+ _door.postInit();
+ _door.setup(3175, 1, 1);
+ _door.setPosition(Common::Point(35, 72));
+ _door.setDetails(3125, 12, 13, -1, 1, (SceneItem *)NULL);
- _actor2.postInit();
- _actor2.setup(3126, 4, 1);
- _actor2.setPosition(Common::Point(71, 110));
- _actor2._numFrames = 20;
+ _ghoul1.postInit();
+ _ghoul1.setup(3126, 4, 1);
+ _ghoul1.setPosition(Common::Point(71, 110));
+ _ghoul1._numFrames = 20;
- _actor3.postInit();
- _actor3.setup(3126, 1, 1);
- _actor3.setPosition(Common::Point(215, 62));
- _actor3.fixPriority(71);
+ _ghoul2.postInit();
+ _ghoul2.setup(3126, 1, 1);
+ _ghoul2.setPosition(Common::Point(215, 62));
+ _ghoul2.fixPriority(71);
- _actor4.postInit();
- _actor4.setup(3126, 1, 1);
- _actor4.setPosition(Common::Point(171, 160));
- _actor4.fixPriority(201);
+ _ghoul3.postInit();
+ _ghoul3.setup(3126, 1, 1);
+ _ghoul3.setPosition(Common::Point(171, 160));
+ _ghoul3.fixPriority(201);
- _item3.setDetails(12, 3125, 9, 13, -1);
- _item2.setDetails(11, 3125, 15, 13, -1);
- _item1.setDetails(Rect(0, 0, 320, 200), 3125, 0, 1, 2, 1, NULL);
+ _computer.setDetails(12, 3125, 9, 13, -1);
+ _table.setDetails(11, 3125, 15, 13, -1);
+ _background.setDetails(Rect(0, 0, 320, 200), 3125, 0, 1, 2, 1, NULL);
R2_GLOBALS._sound1.play(262);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._oldCharacterScene[3] == 3250) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 3250) {
_sceneMode = 3175;
- setAction(&_sequenceManager1, this, 3175, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 3175, &R2_GLOBALS._player, &_door, NULL);
} else {
R2_GLOBALS._player.setup(30, 5, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.setPosition(Common::Point(89, 76));
R2_GLOBALS._player.enableControl();
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3125;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3125;
}
void Scene3125::signal() {
switch (_sceneMode) {
case 3125:
- SceneItem::display(3125, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3125, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
_sceneMode = 3127;
- setAction(&_sequenceManager1, this, 3127, &R2_GLOBALS._player, NULL);
+ setAction(&_sequenceManager, this, 3127, &R2_GLOBALS._player, NULL);
break;
case 3126:
R2_GLOBALS.setFlag(79);
@@ -362,9 +370,9 @@ void Scene3125::signal() {
}
void Scene3125::dispatch() {
- if ((_sceneMode == 3126) && (_actor2._frame == 2) && (_field412 == 0)) {
- _field412 = 1;
+ if ((_sceneMode == 3126) && (_ghoul1._frame == 2) && !_soundPlayed) {
R2_GLOBALS._sound1.play(265);
+ _soundPlayed = true;
}
Scene::dispatch();
}
@@ -373,28 +381,29 @@ void Scene3125::dispatch() {
* Scene 3150 - Jail
*
*--------------------------------------------------------------------------*/
-bool Scene3150::Item5::startAction(CursorType action, Event &event) {
+
+bool Scene3150::LightFixture::startAction(CursorType action, Event &event) {
Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
- if (R2_INVENTORY.getObjectScene(47) != 3150)
+ if (R2_INVENTORY.getObjectScene(R2_LIGHT_BULB) != 3150)
return SceneHotspot::startAction(action, event);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3154;
- scene->setAction(&scene->_sequenceManager, scene, 3154, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3154, &R2_GLOBALS._player, &scene->_bulbOrWire, NULL);
return true;
case R2_SUPERCONDUCTOR_WIRE:
- if ((R2_INVENTORY.getObjectScene(47) != 3150) && (R2_GLOBALS.getFlag(75))) {
+ if ((R2_INVENTORY.getObjectScene(R2_LIGHT_BULB) != 3150) && (R2_GLOBALS.getFlag(75))) {
R2_GLOBALS._player.disableControl();
- scene->_actor3.postInit();
- scene->_actor3._effect = 3;
- scene->_actor3._shade = 5;
+ scene->_bulbOrWire.postInit();
+ scene->_bulbOrWire._effect = EFFECT_SHADED2;
+ scene->_bulbOrWire._shade = 5;
scene->_sceneMode = 3155;
- scene->setAction(&scene->_sequenceManager, scene, 3155, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3155, &R2_GLOBALS._player, &scene->_bulbOrWire, NULL);
} else {
- SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
return true;
default:
@@ -403,50 +412,54 @@ bool Scene3150::Item5::startAction(CursorType action, Event &event) {
}
}
-bool Scene3150::Item6::startAction(CursorType action, Event &event) {
+bool Scene3150::Toilet::startAction(CursorType action, Event &event) {
Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case R2_PILLOW:
R2_GLOBALS._player.disableControl();
- scene->_actor4.postInit();
- scene->_actor4._effect = 6;
- scene->_actor4._shade = 3;
+ scene->_water.postInit();
+ scene->_water._effect = EFFECT_SHADED2;
+ scene->_water._shade = 3;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3158;
- scene->setAction(&scene->_sequenceManager, scene, 3158, &R2_GLOBALS._player, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3158, &R2_GLOBALS._player, &scene->_water, NULL);
return true;
case R2_FOOD_TRAY:
- if ((R2_INVENTORY.getObjectScene(47) != 3150) && (R2_INVENTORY.getObjectScene(40) == 3150) && (R2_GLOBALS.getFlag(75))) {
- scene->_actor5.postInit();
- scene->_actor5._effect = 6;
- scene->_actor5._shade = 3;
- scene->_actor5.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
+ if ((R2_INVENTORY.getObjectScene(R2_LIGHT_BULB) != 3150) &&
+ (R2_INVENTORY.getObjectScene(R2_SUPERCONDUCTOR_WIRE) == 3150)
+ && (R2_GLOBALS.getFlag(75))) {
+ scene->_foodTray.postInit();
+ scene->_foodTray._effect = EFFECT_SHADED2;
+ scene->_foodTray._shade = 3;
+ scene->_foodTray.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3159;
- scene->setAction(&scene->_sequenceManager, scene, 3159, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3159, &R2_GLOBALS._player, &scene->_foodTray, NULL);
} else {
- SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
+ return true;
default:
return SceneHotspot::startAction(action, event);
break;
}
}
-bool Scene3150::Actor4::startAction(CursorType action, Event &event) {
- Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3150::Water::startAction(CursorType action, Event &event) {
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
if (R2_GLOBALS.getFlag(75))
return SceneActor::startAction(action, event);
+ Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3151;
- scene->setAction(&scene->_sequenceManager, scene, 3151, &R2_GLOBALS._player, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3151, &R2_GLOBALS._player, &scene->_water, NULL);
return true;
+ }
case R2_FOOD_TRAY:
return false;
default:
@@ -455,22 +468,22 @@ bool Scene3150::Actor4::startAction(CursorType action, Event &event) {
}
}
-bool Scene3150::Actor5::startAction(CursorType action, Event &event) {
- Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3150::FoodTray::startAction(CursorType action, Event &event) {
if ((action != CURSOR_USE) || (R2_GLOBALS.getFlag(77)))
- return SceneActor::startAction(action ,event);
+ return SceneActor::startAction(action, event);
+
+ Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3157;
- scene->setAction(&scene->_sequenceManager, scene, 3157, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3157, &R2_GLOBALS._player, &scene->_foodTray, NULL);
return true;
}
-bool Scene3150::Actor6::startAction(CursorType action, Event &event) {
- Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3150::ToiletFlush::startAction(CursorType action, Event &event) {
if (action == CURSOR_USE) {
+ Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
+
if (R2_GLOBALS.getFlag(75)) {
if (R2_GLOBALS.getFlag(77)) {
R2_GLOBALS._player.disableControl();
@@ -479,10 +492,10 @@ bool Scene3150::Actor6::startAction(CursorType action, Event &event) {
scene->setAction(&scene->_sequenceManager, scene, 3152, &R2_GLOBALS._player, NULL);
} else {
scene->_sceneMode = 3153;
- scene->setAction(&scene->_sequenceManager, scene, 3152, &R2_GLOBALS._player, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3153, &R2_GLOBALS._player, &scene->_water, NULL);
}
} else {
- SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(3150, 42, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
}
} else {
R2_GLOBALS._player.disableControl();
@@ -495,20 +508,20 @@ bool Scene3150::Actor6::startAction(CursorType action, Event &event) {
}
}
-bool Scene3150::Actor7::startAction(CursorType action, Event &event) {
- Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3150::AirVent::startAction(CursorType action, Event &event) {
if ((action == R2_LASER_HACKSAW) && (!R2_GLOBALS.getFlag(80))) {
+ Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3160;
- scene->setAction(&scene->_sequenceManager, scene, 3160, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3160, &R2_GLOBALS._player, &scene->_airVent, NULL);
return true;
}
return SceneActor::startAction(action, event);
}
-void Scene3150::Exit1::changeScene() {
+void Scene3150::DoorExit::changeScene() {
Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -521,7 +534,7 @@ void Scene3150::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3150::Exit2::changeScene() {
+void Scene3150::VentExit::changeScene() {
Scene3150 *scene = (Scene3150 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
@@ -535,128 +548,128 @@ void Scene3150::Exit2::changeScene() {
void Scene3150::postInit(SceneObjectList *OwnerList) {
loadScene(3150);
if (R2_GLOBALS._sceneManager._previousScene == -1) {
- R2_INVENTORY.setObjectScene(35, 2000);
- R2_GLOBALS._player._oldCharacterScene[1] = 3100;
- R2_GLOBALS._player._oldCharacterScene[3] = 0;
+ R2_INVENTORY.setObjectScene(R2_ANCIENT_SCROLLS, 2000);
+ R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = 3100;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 0;
R2_GLOBALS._player._characterIndex = R2_MIRANDA;
}
SceneExt::postInit();
if (R2_GLOBALS.getFlag(78)) {
- _exit1.setDetails(Rect(0, 135, 60, 168), EXITCURSOR_SW, 3275);
- _exit1.setDest(Common::Point(70, 125));
+ _doorExit.setDetails(Rect(0, 135, 60, 168), EXITCURSOR_SW, 3275);
+ _doorExit.setDest(Common::Point(70, 125));
}
if (R2_GLOBALS.getFlag(80)) {
- _exit2.setDetails(Rect(249, 36, 279, 60), EXITCURSOR_NE, 3150);
- _exit2.setDest(Common::Point(241, 106));
+ _ventExit.setDetails(Rect(249, 36, 279, 60), EXITCURSOR_NE, 3150);
+ _ventExit.setDest(Common::Point(241, 106));
}
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
- _actor2.postInit();
- _actor2.setPosition(Common::Point(64, 139));
+ _doorBars.postInit();
+ _doorBars.setPosition(Common::Point(64, 139));
if (R2_GLOBALS.getFlag(78)) {
- _actor2.setup(3151, 1, 5);
- _actor2.fixPriority(125);
+ _doorBars.setup(3151, 1, 5);
+ _doorBars.fixPriority(125);
} else {
- _actor2.setup(3151, 1, 1);
- _actor2.setDetails(3150, 8, -1, 9, 1, (SceneItem *)NULL);
+ _doorBars.setup(3151, 1, 1);
+ _doorBars.setDetails(3150, 8, -1, 9, 1, (SceneItem *)NULL);
}
if (R2_GLOBALS.getFlag(78)) {
- _actor1.postInit();
- _actor1.setup(3154, 1, 16);
- _actor1.setPosition(Common::Point(104, 129));
- _actor1._effect = 6;
- _actor1._shade = 3;
- _actor1.setDetails(3150, 24, -1, -1, -1, (SceneItem *)NULL);
+ _guard.postInit();
+ _guard.setup(3154, 1, 16);
+ _guard.setPosition(Common::Point(104, 129));
+ _guard._effect = EFFECT_SHADED2;
+ _guard._shade = 3;
+ _guard.setDetails(3150, 24, -1, -1, -1, (SceneItem *)NULL);
}
- _actor7.postInit();
- _actor7.setup(3154, 5, 1);
+ _airVent.postInit();
+ _airVent.setup(3154, 5, 1);
if (R2_GLOBALS.getFlag(80))
- _actor7.setPosition(Common::Point(264, 108));
+ _airVent.setPosition(Common::Point(264, 108));
else
- _actor7.setPosition(Common::Point(264, 58));
- _actor7.fixPriority(50);
- _actor7.setDetails(3150, 17, -1, 19, 1, (SceneItem *)NULL);
+ _airVent.setPosition(Common::Point(264, 58));
+ _airVent.fixPriority(50);
+ _airVent.setDetails(3150, 17, -1, 19, 1, (SceneItem *)NULL);
- if (R2_INVENTORY.getObjectScene(41) == 3150) {
- _actor4.postInit();
+ if (R2_INVENTORY.getObjectScene(R2_PILLOW) == 3150) {
+ _water.postInit();
if (R2_GLOBALS.getFlag(75)) {
if (R2_GLOBALS.getFlag(76)) {
- R2_GLOBALS._walkRegions.enableRegion(1);
- R2_GLOBALS._walkRegions.enableRegion(4);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
- _actor4.setup(3152, 4, 10);
- _actor4.setDetails(3150, 14, -1, -1, 1, (SceneItem *)NULL);
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ _water.setup(3152, 4, 10);
+ _water.setDetails(3150, 14, -1, -1, 1, (SceneItem *)NULL);
} else {
- _actor4.setup(3152, 7, 4);
- _actor4.setDetails(3150, 13, -1, -1, 1, (SceneItem *)NULL);
+ _water.setup(3152, 7, 4);
+ _water.setDetails(3150, 13, -1, -1, 1, (SceneItem *)NULL);
}
- _actor4.fixPriority(110);
- _actor4.setPosition(Common::Point(83, 88));
- _actor4._effect = 6;
- _actor4._shade = 3;
+ _water.fixPriority(110);
+ _water.setPosition(Common::Point(83, 88));
+ _water._effect = EFFECT_SHADED2;
+ _water._shade = 3;
} else {
- _actor4.setup(3152, 7, 3);
- _actor4.setPosition(Common::Point(143, 70));
- _actor4.setDetails(3150, 15, -1, -1, 1, (SceneItem *)NULL);
+ _water.setup(3152, 7, 3);
+ _water.setPosition(Common::Point(143, 70));
+ _water.setDetails(3150, 15, -1, -1, 1, (SceneItem *)NULL);
}
}
- if (R2_INVENTORY.getObjectScene(47) == 3150) {
- _actor3.postInit();
- _actor3.setup(3152, 7, 1);
- _actor3.setPosition(Common::Point(73, 83));
+ if (R2_INVENTORY.getObjectScene(R2_LIGHT_BULB) == 3150) {
+ _bulbOrWire.postInit();
+ _bulbOrWire.setup(3152, 7, 1);
+ _bulbOrWire.setPosition(Common::Point(73, 83));
}
- if (R2_INVENTORY.getObjectScene(40) == 3150) {
- _actor3.postInit();
- _actor3.setup(3152, 7, 3);
- _actor3.setPosition(Common::Point(70, 55));
- _actor3.fixPriority(111);
- _actor3._effect = 6;
- _actor3._shade = 5;
+ if (R2_INVENTORY.getObjectScene(R2_SUPERCONDUCTOR_WIRE) == 3150) {
+ _bulbOrWire.postInit();
+ _bulbOrWire.setup(3152, 7, 2);
+ _bulbOrWire.setPosition(Common::Point(70, 55));
+ _bulbOrWire.fixPriority(111);
+ _bulbOrWire._effect = EFFECT_SHADED2;
+ _bulbOrWire._shade = 5;
}
- if (R2_INVENTORY.getObjectScene(42) == 3150) {
- _actor5.postInit();
+ if (R2_INVENTORY.getObjectScene(R2_FOOD_TRAY) == 3150) {
+ _foodTray.postInit();
if (R2_GLOBALS.getFlag(77)) {
- _actor5.setup(3152, 7, 8);
- _actor5.setPosition(Common::Point(82, 92));
- _actor5.fixPriority(111);
- _actor5._effect = 6;
- _actor5._shade = 3;
+ _foodTray.setup(3152, 7, 8);
+ _foodTray.setPosition(Common::Point(82, 92));
+ _foodTray.fixPriority(111);
+ _foodTray._effect = EFFECT_SHADED2;
+ _foodTray._shade = 3;
} else {
- _actor5.setup(3152, 7, 7);
- _actor5.setPosition(Common::Point(155, 79));
+ _foodTray.setup(3152, 7, 7);
+ _foodTray.setPosition(Common::Point(155, 79));
}
- _actor5.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
+ _foodTray.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
}
- _actor6.postInit();
- _actor6.setup(3152, 7, 6);
- _actor6.setPosition(Common::Point(98, 73));
- _actor6.setDetails(3150, 43, -1, -1, 1, (SceneItem *)NULL);
+ _toiletFlush.postInit();
+ _toiletFlush.setup(3152, 7, 6);
+ _toiletFlush.setPosition(Common::Point(98, 73));
+ _toiletFlush.setDetails(3150, 43, -1, -1, 1, (SceneItem *)NULL);
- _item2.setDetails(12, 3150, 10, -1, 12);
- _item3.setDetails(Rect(186, 17, 210, 36), 3150, 6, -1, -1, 1, NULL);
- _item4.setDetails(Rect(61, 21, 92, 41), 3150, 7, -1, -1, 1, NULL);
- _item5.setDetails(Rect(63, 48, 78, 58), 3150, 6, -1, -1, 1, NULL);
- _item6.setDetails(Rect(63, 81, 100, 95), 3150, 3, 4, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 200, 320), 3150, 0, 1, 2, 1, NULL);
+ _bed.setDetails(12, 3150, 10, -1, 12);
+ _lightFixture2.setDetails(Rect(186, 17, 210, 36), 3150, 6, -1, -1, 1, NULL);
+ _bars.setDetails(Rect(61, 21, 92, 41), 3150, 7, -1, -1, 1, NULL);
+ _lightFixture.setDetails(Rect(63, 48, 78, 58), 3150, 6, -1, -1, 1, NULL);
+ _toilet.setDetails(Rect(63, 81, 100, 95), 3150, 3, 4, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 200, 320), 3150, 0, 1, 2, 1, NULL);
- switch (R2_GLOBALS._player._oldCharacterScene[3]) {
+ switch (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA]) {
case 0:
_sceneMode = 3150;
- _actor1.postInit();
- _actor1._effect = 6;
- _actor1._shade = 5;
- setAction(&_sequenceManager, this, 3150, &R2_GLOBALS._player, &_actor1, &_actor2, NULL);
+ _guard.postInit();
+ _guard._effect = EFFECT_SHADED2;
+ _guard._shade = 5;
+ setAction(&_sequenceManager, this, 3150, &R2_GLOBALS._player, &_guard, &_doorBars, NULL);
break;
case 1200:
_sceneMode = 3162;
@@ -675,22 +688,24 @@ void Scene3150::postInit(SceneObjectList *OwnerList) {
break;
}
default:
- if ((R2_GLOBALS._v56AA0 == 1) && (R2_INVENTORY.getObjectScene(35) == 2000) && (R2_GLOBALS._player._oldCharacterScene[1] == 3100)) {
- ++R2_GLOBALS._v56AA0;
+ if ((R2_GLOBALS._mirandaJailState == 1) && (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2000)
+ && (R2_GLOBALS._player._oldCharacterScene[R2_QUINN] == 3100)) {
+ // Moving story on to Miranda getting food delivered
+ ++R2_GLOBALS._mirandaJailState;
_sceneMode = 3156;
- _actor1.postInit();
- _actor1._effect = 6;
- _actor1._shade = 3;
+ _guard.postInit();
+ _guard._effect = EFFECT_SHADED2;
+ _guard._shade = 3;
- _actor2.postInit();
- _actor5.postInit();
- _actor5._effect = 6;
- _actor5._shade = 3;
+ _doorBars.postInit();
+ _foodTray.postInit();
+ _foodTray._effect = EFFECT_SHADED2;
+ _foodTray._shade = 3;
- setAction(&_sequenceManager, this, 3156, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 3156, &R2_GLOBALS._player, &_guard, &_doorBars, &_foodTray, NULL);
} else {
- if (R2_GLOBALS._v56AA0 != 2)
- ++R2_GLOBALS._v56AA0;
+ if ((R2_GLOBALS._mirandaJailState != 1) && (R2_GLOBALS._mirandaJailState != 2))
+ ++R2_GLOBALS._mirandaJailState;
R2_GLOBALS._player.setup(30, 3, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
@@ -700,7 +715,7 @@ void Scene3150::postInit(SceneObjectList *OwnerList) {
}
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3150;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3150;
}
void Scene3150::signal() {
@@ -712,62 +727,62 @@ void Scene3150::signal() {
R2_GLOBALS._sceneManager.changeScene(1200);
break;
case 3151:
- _actor1.remove();
- R2_INVENTORY.setObjectScene(41, 3);
+ _guard.remove();
+ R2_INVENTORY.setObjectScene(R2_PILLOW, 3);
R2_GLOBALS._player.enableControl();
break;
case 3153:
R2_GLOBALS.setFlag(76);
- _actor4.setDetails(3150, 14, -1, -1, 3, (SceneItem *)NULL);
- _actor1.postInit();
- _actor1.setDetails(3150, 24, -1, -1, 2, (SceneItem *)NULL);
+ _water.setDetails(3150, 14, -1, -1, 3, (SceneItem *)NULL);
+ _guard.postInit();
+ _guard.setDetails(3150, 24, -1, -1, 2, (SceneItem *)NULL);
_sceneMode = 3161;
- setAction(&_sequenceManager, this, 3161, &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3161, &_guard, &_doorBars, NULL);
break;
case 3154:
- _actor3.remove();
- R2_INVENTORY.setObjectScene(47, 3);
+ _bulbOrWire.remove();
+ R2_INVENTORY.setObjectScene(R2_LIGHT_BULB, 3);
R2_GLOBALS._player.enableControl();
break;
case 3155:
- R2_INVENTORY.setObjectScene(40, 3150);
+ R2_INVENTORY.setObjectScene(R2_SUPERCONDUCTOR_WIRE, 3150);
R2_GLOBALS._player.enableControl();
break;
case 3156:
- _actor5.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
- R2_INVENTORY.setObjectScene(42, 3150);
+ _foodTray.setDetails(3150, 30, -1, -1, 2, (SceneItem *)NULL);
+ R2_INVENTORY.setObjectScene(R2_FOOD_TRAY, 3150);
R2_GLOBALS._player.enableControl();
break;
case 3157:
- _actor5.remove();
- R2_INVENTORY.setObjectScene(42, 3);
+ _foodTray.remove();
+ R2_INVENTORY.setObjectScene(R2_FOOD_TRAY, 3);
R2_GLOBALS._player.enableControl();
break;
case 3158:
R2_GLOBALS.setFlag(75);
- R2_INVENTORY.setObjectScene(41, 3150);
- _actor4.fixPriority(110);
- _actor4.setDetails(3150, 13, -1, -1, 2, (SceneItem *)NULL);
+ R2_INVENTORY.setObjectScene(R2_PILLOW, 3150);
+ _water.fixPriority(110);
+ _water.setDetails(3150, 13, -1, -1, 2, (SceneItem *)NULL);
R2_GLOBALS._player.enableControl();
break;
case 3159:
R2_GLOBALS.setFlag(77);
- R2_INVENTORY.setObjectScene(42, 3150);
+ R2_INVENTORY.setObjectScene(R2_FOOD_TRAY, 3150);
R2_GLOBALS._player.enableControl();
break;
case 3160:
- R2_INVENTORY.setObjectScene(52, 3150);
+ R2_INVENTORY.setObjectScene(R2_TOOLBOX, 3150);
R2_GLOBALS.setFlag(80);
R2_GLOBALS._sceneManager.changeScene(1200);
break;
case 3161:
- R2_GLOBALS._sceneItems.remove(&_actor2);
- _exit1.setDetails(Rect(0, 135, 60, 168), EXITCURSOR_SW, 3275);
- _exit1.setDest(Common::Point(70, 125));
- R2_GLOBALS._walkRegions.enableRegion(1);
- R2_GLOBALS._walkRegions.enableRegion(4);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
+ R2_GLOBALS._sceneItems.remove(&_doorBars);
+ _doorExit.setDetails(Rect(0, 135, 60, 168), EXITCURSOR_SW, 3275);
+ _doorExit.setDest(Common::Point(70, 125));
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
R2_GLOBALS.setFlag(78);
R2_GLOBALS._player.enableControl();
break;
@@ -778,14 +793,14 @@ void Scene3150::signal() {
}
void Scene3150::dispatch() {
- if (_actor5._position.x == 155) {
- _actor5._effect = 0;
- _actor5._shade = 0;
+ if (_foodTray._position.x == 155) {
+ _foodTray._effect = EFFECT_NONE;
+ _foodTray._shade = 0;
}
- if (_actor1._visage == 3154) {
- _actor1._effect = 0;
- _actor1._shade = 0;
+ if (_guard._visage == 3154) {
+ _guard._effect = EFFECT_NONE;
+ _guard._shade = 0;
}
Scene::dispatch();
@@ -795,25 +810,24 @@ void Scene3150::dispatch() {
* Scene 3175 - Autopsy room
*
*--------------------------------------------------------------------------*/
-bool Scene3175::Item1::startAction(CursorType action, Event &event) {
- Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
+bool Scene3175::RoomItem::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_USE:
if (_useLineNum != -1) {
- SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_LOOK:
if (_lookLineNum != -1) {
- SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_TALK:
if (_talkLineNum != -1) {
- SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
@@ -821,28 +835,27 @@ bool Scene3175::Item1::startAction(CursorType action, Event &event) {
break;
}
+ Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
return scene->display(action, event);
}
-bool Scene3175::Actor3::startAction(CursorType action, Event &event) {
- Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3175::Corpse::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_USE:
if (_useLineNum != -1) {
- SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_LOOK:
if (_lookLineNum != -1) {
- SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_TALK:
if (_talkLineNum != -1) {
- SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
@@ -850,25 +863,27 @@ bool Scene3175::Actor3::startAction(CursorType action, Event &event) {
break;
}
+ Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
return scene->display(action, event);
}
-bool Scene3175::Actor1::startAction(CursorType action, Event &event) {
- Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3175::Door::startAction(CursorType action, Event &event) {
switch (action) {
- case CURSOR_USE:
+ case CURSOR_USE: {
+ Scene3175 *scene = (Scene3175 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3176;
- scene->setAction(&scene->_sequenceManager, scene, 3176, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3176, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
+ }
break;
case CURSOR_LOOK:
- SceneItem::display(3175, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3175, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
break;
case CURSOR_TALK:
- SceneItem::display(3175, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(3175, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
break;
default:
@@ -881,37 +896,37 @@ void Scene3175::postInit(SceneObjectList *OwnerList) {
loadScene(3175);
SceneExt::postInit();
- _actor1.postInit();
- _actor1.setup(3175, 1, 1);
- _actor1.setPosition(Common::Point(35, 72));
- _actor1.setDetails(3175, 9, 10, -1, 1, (SceneItem *)NULL);
+ _door.postInit();
+ _door.setup(3175, 1, 1);
+ _door.setPosition(Common::Point(35, 72));
+ _door.setDetails(3175, 9, 10, -1, 1, (SceneItem *)NULL);
- _actor2.postInit();
- _actor2.setup(3175, 2, 1);
- _actor2.setPosition(Common::Point(87, 148));
+ _computer.postInit();
+ _computer.setup(3175, 2, 1);
+ _computer.setPosition(Common::Point(87, 148));
- _actor3.postInit();
- _actor3.setup(3175, 3, 1);
- _actor3.setPosition(Common::Point(199, 117));
- _actor3.setDetails(3175, 15, 16, 17, 1, (SceneItem *)NULL);
+ _corpse.postInit();
+ _corpse.setup(3175, 3, 1);
+ _corpse.setPosition(Common::Point(199, 117));
+ _corpse.setDetails(3175, 15, 16, 17, 1, (SceneItem *)NULL);
- _item2.setDetails(12, 3175, 3, 1, 5);
- _item3.setDetails(11, 3175, 6, 7, 8);
- _item1.setDetails(Rect(0, 0, 320, 200), 3175, 0, 1, 2, 1, NULL);
+ _table.setDetails(12, 3175, 3, 1, 5);
+ _autopsies.setDetails(11, 3175, 6, 7, 8);
+ _background.setDetails(Rect(0, 0, 320, 200), 3175, 0, 1, 2, 1, NULL);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._oldCharacterScene[3] == 3250) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 3250) {
R2_GLOBALS._player.setup(30, 5, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.setPosition(Common::Point(126, 77));
R2_GLOBALS._player.enableControl();
} else {
_sceneMode = 3175;
- setAction(&_sequenceManager, this, 3175, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 3175, &R2_GLOBALS._player, &_door, NULL);
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3175;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3175;
}
void Scene3175::signal() {
@@ -925,6 +940,7 @@ void Scene3175::signal() {
* Scene 3200 - Cutscene : Guards - Discussion
*
*--------------------------------------------------------------------------*/
+
void Scene3200::postInit(SceneObjectList *OwnerList) {
loadScene(3200);
R2_GLOBALS._uiElements._active = false;
@@ -938,11 +954,12 @@ void Scene3200::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor3.postInit();
- _actor2.postInit();
+ _rocko.postInit();
+ _jocko.postInit();
+ _socko.postInit();
- setAction(&_sequenceManager, this, 3200 + R2_GLOBALS._randomSource.getRandomNumber(1), &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3200 + R2_GLOBALS._randomSource.getRandomNumber(1),
+ &_rocko, &_jocko, &_socko, NULL);
}
void Scene3200::signal() {
@@ -953,6 +970,7 @@ void Scene3200::signal() {
* Scene 3210 - Cutscene : Captain and Private - Discussion
*
*--------------------------------------------------------------------------*/
+
void Scene3210::postInit(SceneObjectList *OwnerList) {
loadScene(3210);
R2_GLOBALS._uiElements._active = false;
@@ -965,10 +983,11 @@ void Scene3210::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor2.postInit();
+ _captain.postInit();
+ _private.postInit();
- setAction(&_sequenceManager, this, 3210 + R2_GLOBALS._randomSource.getRandomNumber(1), &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3210 + R2_GLOBALS._randomSource.getRandomNumber(1),
+ &_captain, &_private, NULL);
}
void Scene3210::signal() {
@@ -979,6 +998,7 @@ void Scene3210::signal() {
* Scene 3220 - Cutscene : Guards in cargo zone
*
*--------------------------------------------------------------------------*/
+
void Scene3220::postInit(SceneObjectList *OwnerList) {
loadScene(3220);
R2_GLOBALS._uiElements._active = false;
@@ -991,10 +1011,11 @@ void Scene3220::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor2.postInit();
+ _rocko.postInit();
+ _jocko.postInit();
- setAction(&_sequenceManager, this, 3220 + R2_GLOBALS._randomSource.getRandomNumber(1), &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3220 + R2_GLOBALS._randomSource.getRandomNumber(1),
+ &_rocko, &_jocko, NULL);
}
void Scene3220::signal() {
@@ -1005,6 +1026,7 @@ void Scene3220::signal() {
* Scene 3230 - Cutscene : Guards on duty
*
*--------------------------------------------------------------------------*/
+
void Scene3230::postInit(SceneObjectList *OwnerList) {
loadScene(3230);
R2_GLOBALS._uiElements._active = false;
@@ -1017,11 +1039,12 @@ void Scene3230::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor2.postInit();
- _actor3.postInit();
+ _rocko.postInit();
+ _jocko.postInit();
+ _ghoul.postInit();
- setAction(&_sequenceManager, this, 3230 + R2_GLOBALS._randomSource.getRandomNumber(1), &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3230 + R2_GLOBALS._randomSource.getRandomNumber(1),
+ &_rocko, &_jocko, &_ghoul, NULL);
}
void Scene3230::signal() {
@@ -1032,6 +1055,7 @@ void Scene3230::signal() {
* Scene 3240 - Cutscene : Teal monolog
*
*--------------------------------------------------------------------------*/
+
void Scene3240::postInit(SceneObjectList *OwnerList) {
loadScene(3240);
R2_GLOBALS._uiElements._active = false;
@@ -1045,10 +1069,11 @@ void Scene3240::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor2.postInit();
+ _teal.postInit();
+ _webbster.postInit();
- setAction(&_sequenceManager, this, 3240 + R2_GLOBALS._randomSource.getRandomNumber(1), &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3240 + R2_GLOBALS._randomSource.getRandomNumber(1),
+ &_teal, &_webbster, NULL);
}
void Scene3240::signal() {
@@ -1059,6 +1084,7 @@ void Scene3240::signal() {
* Scene 3245 - Cutscene : Discussions with Dr. Tomko
*
*--------------------------------------------------------------------------*/
+
void Scene3245::postInit(SceneObjectList *OwnerList) {
loadScene(3245);
R2_GLOBALS._uiElements._active = false;
@@ -1071,17 +1097,18 @@ void Scene3245::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor2.postInit();
+ _ralf.postInit();
+ _tomko.postInit();
- if (R2_GLOBALS._v56AA1 < 4)
- ++R2_GLOBALS._v56AA1;
+ if (R2_GLOBALS._scientistConvIndex < 4)
+ ++R2_GLOBALS._scientistConvIndex;
- if (R2_GLOBALS._v56AA1 >= 4) {
- SceneItem::display(1200, 7, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ if (R2_GLOBALS._scientistConvIndex >= 4) {
+ SceneItem::display(1200, 7, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
signal();
} else {
- setAction(&_sequenceManager, this, 3244 + R2_GLOBALS._v56AA1, &_actor1, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3244 + R2_GLOBALS._scientistConvIndex,
+ &_ralf, &_tomko, NULL);
}
}
@@ -1093,25 +1120,24 @@ void Scene3245::signal() {
* Scene 3250 - Room with large stasis field negator
*
*--------------------------------------------------------------------------*/
-bool Scene3250::Item::startAction(CursorType action, Event &event) {
- Scene3250 *scene = (Scene3250 *)R2_GLOBALS._sceneManager._scene;
+bool Scene3250::Item::startAction(CursorType action, Event &event) {
switch (action) {
case CURSOR_USE:
if (_useLineNum != -1) {
- SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _useLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_LOOK:
if (_lookLineNum != -1) {
- SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _lookLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
case CURSOR_TALK:
if (_talkLineNum != -1) {
- SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ SceneItem::display(_resNum, _talkLineNum, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
return true;
}
break;
@@ -1119,29 +1145,29 @@ bool Scene3250::Item::startAction(CursorType action, Event &event) {
break;
}
+ Scene3250 *scene = (Scene3250 *)R2_GLOBALS._sceneManager._scene;
return scene->display(action, event);
}
-bool Scene3250::Actor::startAction(CursorType action, Event &event) {
- Scene3250 *scene = (Scene3250 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3250::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
+ Scene3250 *scene = (Scene3250 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl();
switch(_position.x) {
case 25:
scene->_sceneMode = 3262;
- scene->setAction(&scene->_sequenceManager, scene, 3262, &R2_GLOBALS._player, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3262, &R2_GLOBALS._player, &scene->_leftDoor, NULL);
break;
case 259:
scene->_sceneMode = 3260;
- scene->setAction(&scene->_sequenceManager, scene, 3260, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3260, &R2_GLOBALS._player, &scene->_topDoor, NULL);
break;
case 302:
scene->_sceneMode = 3261;
- scene->setAction(&scene->_sequenceManager, scene, 3261, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3261, &R2_GLOBALS._player, &scene->_rightDoor, NULL);
break;
default:
break;
@@ -1153,65 +1179,66 @@ void Scene3250::postInit(SceneObjectList *OwnerList) {
loadScene(3250);
if (R2_GLOBALS._sceneManager._previousScene == -1) {
- R2_GLOBALS._player._oldCharacterScene[3] = 1200;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 1200;
R2_GLOBALS._player._characterIndex = R2_MIRANDA;
}
SceneExt::postInit();
- _actor1.postInit();
- _actor1.setup(3250, 6, 1);
- _actor1.setPosition(Common::Point(25, 148));
- _actor1.fixPriority(10);
- _actor1.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
-
- _actor2.postInit();
- _actor2.setup(3250, 4, 1);
- _actor2.setPosition(Common::Point(259, 126));
- _actor2.fixPriority(10);
- _actor2.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
-
- _actor3.postInit();
- _actor3.setup(3250, 5, 1);
- _actor3.setPosition(Common::Point(302, 138));
- _actor3.fixPriority(10);
- _actor3.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
-
- _item3.setDetails(Rect(119, 111, 149, 168), 3250, 6, 7, 2, 1, NULL);
- _item2.setDetails(Rect(58, 85, 231, 138), 3250, 12, 7, 2, 1, NULL);
- _item4.setDetails(12, 3250, 3, 1, 2);
- _item1.setDetails(Rect(0, 0, 320, 200), 3250, 0, 1, 2, 1, NULL);
+ _leftDoor.postInit();
+ _leftDoor.setup(3250, 6, 1);
+ _leftDoor.setPosition(Common::Point(25, 148));
+ _leftDoor.fixPriority(10);
+ _leftDoor.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
+
+ _topDoor.postInit();
+ _topDoor.setup(3250, 4, 1);
+ _topDoor.setPosition(Common::Point(259, 126));
+ _topDoor.fixPriority(10);
+ _topDoor.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
+
+ _rightDoor.postInit();
+ _rightDoor.setup(3250, 5, 1);
+ _rightDoor.setPosition(Common::Point(302, 138));
+ _rightDoor.fixPriority(10);
+ _rightDoor.setDetails(3250, 9, 10, -1, 1, (SceneItem *)NULL);
+
+ _floodLights.setDetails(Rect(119, 111, 149, 168), 3250, 6, 7, 2, 1, NULL);
+ _tnuctipunShip.setDetails(Rect(58, 85, 231, 138), 3250, 12, 7, 2, 1, NULL);
+ _negator.setDetails(12, 3250, 3, 1, 2);
+ _background.setDetails(Rect(0, 0, 320, 200), 3250, 0, 1, 2, 1, NULL);
R2_GLOBALS._player.postInit();
- switch (R2_GLOBALS._player._oldCharacterScene[3]) {
+ switch (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA]) {
case 1200:
_sceneMode = 3250;
- _actor4.postInit();
- R2_GLOBALS._player._effect = 0;
- setAction(&_sequenceManager, this, 3250, &R2_GLOBALS._player, &_actor4, NULL);
+ _grate.postInit();
+ R2_GLOBALS._player._effect = EFFECT_NONE;
+ setAction(&_sequenceManager, this, 3250, &R2_GLOBALS._player, &_grate, NULL);
break;
case 3125:
if (R2_GLOBALS.getFlag(79)) {
_sceneMode = 3254;
- _actor5.postInit();
- _actor5._effect = 1;
- _actor6.postInit();
- _actor6._effect = 1;
- _actor7.postInit();
- _actor7._effect = 1;
- setAction(&_sequenceManager, this, 3254, &R2_GLOBALS._player, &_actor3, &_actor5, &_actor6, &_actor7, &_actor1, NULL);
+ _ghoul1.postInit();
+ _ghoul1._effect = EFFECT_SHADED;
+ _ghoul2.postInit();
+ _ghoul2._effect = EFFECT_SHADED;
+ _ghoul3.postInit();
+ _ghoul3._effect = EFFECT_SHADED;
+ setAction(&_sequenceManager, this, 3254, &R2_GLOBALS._player, &_rightDoor,
+ &_ghoul1, &_ghoul2, &_ghoul3, &_leftDoor, NULL);
} else {
_sceneMode = 3252;
- setAction(&_sequenceManager, this, 3252, &R2_GLOBALS._player, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3252, &R2_GLOBALS._player, &_rightDoor, NULL);
}
break;
case 3175:
_sceneMode = 3251;
- setAction(&_sequenceManager, this, 3251, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3251, &R2_GLOBALS._player, &_topDoor, NULL);
break;
case 3255:
_sceneMode = 3253;
- setAction(&_sequenceManager, this, 3253, &R2_GLOBALS._player, &_actor1, NULL);
+ setAction(&_sequenceManager, this, 3253, &R2_GLOBALS._player, &_leftDoor, NULL);
break;
default:
R2_GLOBALS._player.setup(31, 3, 1);
@@ -1221,13 +1248,13 @@ void Scene3250::postInit(SceneObjectList *OwnerList) {
break;
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3250;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3250;
}
void Scene3250::signal() {
switch(_sceneMode) {
case 3250:
- R2_GLOBALS._player._effect = 1;
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
R2_GLOBALS._player.enableControl();
break;
case 3254:
@@ -1249,7 +1276,7 @@ void Scene3250::signal() {
void Scene3250::dispatch() {
if ((R2_GLOBALS._player._visage == 3250) && (R2_GLOBALS._player._strip == 3) && (R2_GLOBALS._player._effect == 0)) {
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
R2_GLOBALS._player._shade = 6;
}
@@ -1257,9 +1284,10 @@ void Scene3250::dispatch() {
}
/*--------------------------------------------------------------------------
- * Scene 3255 -
+ * Scene 3255 - Guard Post
*
*--------------------------------------------------------------------------*/
+
void Scene3255::postInit(SceneObjectList *OwnerList) {
loadScene(3255);
SceneExt::postInit();
@@ -1277,31 +1305,32 @@ void Scene3255::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sound1.play(267);
R2_GLOBALS._sound2.play(268);
_sceneMode = 3257;
- _actor3.postInit();
- _actor4.postInit();
- _actor4._effect = 1;
- setAction(&_sequenceManager, this, 3257, &R2_GLOBALS._player, &_actor4, &_actor3, NULL);
+ _door.postInit();
+ _quinn.postInit();
+ _quinn._effect = EFFECT_SHADED;
+ setAction(&_sequenceManager, this, 3257, &R2_GLOBALS._player, &_quinn, &_door, NULL);
} else {
- _actor1.postInit();
- _actor1.setup(303, 1, 1);
- _actor1.setPosition(Common::Point(208, 128));
- _actor2.postInit();
- _actor2.setup(3107, 3, 1);
- _actor2.setPosition(Common::Point(230, 127));
+ _teal.postInit();
+ _teal.setup(303, 1, 1);
+ _teal.setPosition(Common::Point(208, 128));
+ _guard.postInit();
+ _guard.setup(3107, 3, 1);
+ _guard.setPosition(Common::Point(230, 127));
_sceneMode = 3255;
setAction(&_sequenceManager, this, 3255, &R2_GLOBALS._player, NULL);
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3255;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3255;
}
void Scene3255::signal() {
switch (_sceneMode) {
case 10:
_sceneMode = 3258;
- _actor5.postInit();
- _actor6.postInit();
- _actor7.postInit();
- setAction(&_sequenceManager, this, 3258, &R2_GLOBALS._player, &_actor4, &_actor3, &_actor5, &_actor6, &_actor7, NULL);
+ _ghoul1.postInit();
+ _ghoul2.postInit();
+ _ghoul3.postInit();
+ setAction(&_sequenceManager, this, 3258, &R2_GLOBALS._player, &_quinn,
+ &_door, &_ghoul1, &_ghoul2, &_ghoul3, NULL);
break;
case 3256:
R2_GLOBALS._sceneManager.changeScene(3250);
@@ -1315,7 +1344,7 @@ void Scene3255::signal() {
R2_GLOBALS._sceneManager.changeScene(3100);
break;
default:
- SceneItem::display(3255, 0, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(3255, 0, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
_sceneMode = 3256;
setAction(&_sequenceManager, this, 3256, &R2_GLOBALS._player, NULL);
}
@@ -1323,40 +1352,40 @@ void Scene3255::signal() {
void Scene3255::dispatch() {
if (R2_GLOBALS.getFlag(79)) {
- if (_actor5._position.y >= 95) {
- if (_actor5._position.y <= 110)
- _actor5._shade = 6 - (_actor5._position.y - 95) / 3;
+ if (_ghoul1._position.y >= 95) {
+ if (_ghoul1._position.y <= 110)
+ _ghoul1._shade = 6 - (_ghoul1._position.y - 95) / 3;
else
- _actor5._effect = 1;
+ _ghoul1._effect = EFFECT_SHADED;
} else {
- _actor5._effect = 6;
- _actor5._shade = 6;
+ _ghoul1._effect = EFFECT_SHADED2;
+ _ghoul1._shade = 6;
}
- if (_actor6._position.y >= 95) {
- if (_actor6._position.y <= 110)
- _actor6._shade = 6 - (_actor6._position.y - 95) / 3;
+ if (_ghoul2._position.y >= 95) {
+ if (_ghoul2._position.y <= 110)
+ _ghoul2._shade = 6 - (_ghoul2._position.y - 95) / 3;
else
- _actor6._effect = 1;
+ _ghoul2._effect = EFFECT_SHADED;
} else {
- _actor6._effect = 6;
- _actor6._shade = 6;
+ _ghoul2._effect = EFFECT_SHADED2;
+ _ghoul2._shade = 6;
}
- if (_actor7._position.y >= 95) {
- if (_actor7._position.y <= 110)
- _actor7._shade = 6 - (_actor7._position.y - 95) / 3;
+ if (_ghoul3._position.y >= 95) {
+ if (_ghoul3._position.y <= 110)
+ _ghoul3._shade = 6 - (_ghoul3._position.y - 95) / 3;
else
- _actor7._effect = 1;
+ _ghoul3._effect = EFFECT_SHADED;
} else {
- _actor7._effect = 6;
- _actor7._shade = 6;
+ _ghoul3._effect = EFFECT_SHADED2;
+ _ghoul3._shade = 6;
}
}
if ((R2_GLOBALS._player._position.x > 250) && (R2_GLOBALS._player._shade == 1)) {
- R2_GLOBALS._player._effect = 6;
- _actor4._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
+ _quinn._effect = EFFECT_SHADED2;
}
Scene::dispatch();
}
@@ -1365,27 +1394,28 @@ void Scene3255::dispatch() {
* Scene 3260 - Computer room
*
*--------------------------------------------------------------------------*/
-bool Scene3260::Actor13::startAction(CursorType action, Event &event) {
- Scene3260 *scene = (Scene3260 *)R2_GLOBALS._sceneManager._scene;
+bool Scene3260::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
+ Scene3260 *scene = (Scene3260 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3271;
- scene->setAction(&scene->_sequenceManager, scene, 3271, &R2_GLOBALS._player, &scene->_actor13, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3271, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
}
-bool Scene3260::Actor14::startAction(CursorType action, Event &event) {
- Scene3260 *scene = (Scene3260 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3260::Toolbox::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
+ Scene3260 *scene = (Scene3260 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3272;
- scene->setAction(&scene->_sequenceManager, scene, 3272, &R2_GLOBALS._player, &scene->_actor14, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3272, &R2_GLOBALS._player, &scene->_toolbox, NULL);
return true;
}
@@ -1402,103 +1432,103 @@ void Scene3260::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
R2_GLOBALS._sound1.play(285);
- _actor13.postInit();
- _actor13.setup(3260, 6, 1);
- _actor13.setPosition(Common::Point(40, 106));
- _actor13.setDetails(3260, 18, 1, -1, 1, (SceneItem *)NULL);
+ _door.postInit();
+ _door.setup(3260, 6, 1);
+ _door.setPosition(Common::Point(40, 106));
+ _door.setDetails(3260, 18, 1, -1, 1, (SceneItem *)NULL);
- if (R2_INVENTORY.getObjectScene(52) == 3260) {
- _actor14.postInit();
- _actor14.setup(3260, 7, 1);
- _actor14.setPosition(Common::Point(202, 66));
- _actor14.setDetails(3260, 12, 1, -1, 1, (SceneItem *)NULL);
+ if (R2_INVENTORY.getObjectScene(R2_TOOLBOX) == 3260) {
+ _toolbox.postInit();
+ _toolbox.setup(3260, 7, 1);
+ _toolbox.setPosition(Common::Point(202, 66));
+ _toolbox.setDetails(3260, 12, 1, -1, 1, (SceneItem *)NULL);
}
- _actor1.postInit();
- _actor1.setup(3260, 1, 1);
- _actor1.setPosition(Common::Point(93, 73));
- _actor1.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor1.setAction(&_action1, &_actor1);
-
- _actor2.postInit();
- _actor2.setup(3260, 2, 1);
- _actor2.setPosition(Common::Point(142, 63));
- _actor2.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor2.setAction(&_action2, &_actor2);
-
- _actor3.postInit();
- _actor3.setup(3260, 2, 1);
- _actor3.setPosition(Common::Point(166, 54));
- _actor3.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor3.setAction(&_action3, &_actor3);
-
- _actor4.postInit();
- _actor4.setup(3260, 2, 1);
- _actor4.setPosition(Common::Point(190, 46));
- _actor4.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor4.setAction(&_action4, &_actor4);
-
- _actor5.postInit();
- _actor5.setup(3260, 2, 1);
- _actor5.setPosition(Common::Point(142, 39));
- _actor5.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor5.setAction(&_action5, &_actor5);
-
- _actor6.postInit();
- _actor6.setup(3260, 2, 1);
- _actor6.setPosition(Common::Point(166, 30));
- _actor6.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor6.setAction(&_action6, &_actor6);
-
- _actor7.postInit();
- _actor7.setup(3260, 2, 1);
- _actor7.setPosition(Common::Point(190, 22));
- _actor7.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor7.setAction(&_action7, &_actor7);
-
- _actor8.postInit();
- _actor8.setup(3260, 2, 1);
- _actor8.setPosition(Common::Point(142, 14));
- _actor8.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor8.setAction(&_action8, &_actor8);
-
- _actor9.postInit();
- _actor9.setup(3260, 2, 1);
- _actor9.setPosition(Common::Point(166, 6));
- _actor9.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
- _actor9.setAction(&_action9, &_actor9);
-
- _actor10.postInit();
- _actor10.setup(3260, 3, 1);
- _actor10.setPosition(Common::Point(265, 163));
- _actor10.fixPriority(180);
- _actor10._numFrames = 10;
- _actor10.setDetails(3260, 6, 1, 8, 1, (SceneItem *)NULL);
- _actor10.animate(ANIM_MODE_2, NULL);
-
- _actor11.postInit();
- _actor11.setup(3260, 4, 1);
- _actor11.setPosition(Common::Point(127, 108));
- _actor11.fixPriority(120);
- _actor11.setAction(&_action11, &_actor11);
- _actor11._numFrames = 15;
- _actor11.setDetails(3260, 6, 1, 8, 1, (SceneItem *)NULL);
- _actor11.animate(ANIM_MODE_2, NULL);
-
- _actor12.postInit();
- _actor12.setup(3260, 5, 1);
- _actor12.setPosition(Common::Point(274, 65));
- _actor12.setAction(&_action12, &_actor12);
- _actor12._numFrames = 5;
- _actor12.setDetails(3260, 9, 1, 11, 1, (SceneItem *)NULL);
- _actor12.animate(ANIM_MODE_2, NULL);
-
- _item1.setDetails(Rect(0, 0, 320, 200), 3260, 0, 1, 2, 1, NULL);
+ _sceeen1.postInit();
+ _sceeen1.setup(3260, 1, 1);
+ _sceeen1.setPosition(Common::Point(93, 73));
+ _sceeen1.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _sceeen1.setAction(&_action1, &_sceeen1);
+
+ _screen2.postInit();
+ _screen2.setup(3260, 2, 1);
+ _screen2.setPosition(Common::Point(142, 63));
+ _screen2.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen2.setAction(&_action2, &_screen2);
+
+ _screen3.postInit();
+ _screen3.setup(3260, 2, 1);
+ _screen3.setPosition(Common::Point(166, 54));
+ _screen3.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen3.setAction(&_action3, &_screen3);
+
+ _screen4.postInit();
+ _screen4.setup(3260, 2, 1);
+ _screen4.setPosition(Common::Point(190, 46));
+ _screen4.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen4.setAction(&_action4, &_screen4);
+
+ _screen5.postInit();
+ _screen5.setup(3260, 2, 1);
+ _screen5.setPosition(Common::Point(142, 39));
+ _screen5.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen5.setAction(&_action5, &_screen5);
+
+ _screen6.postInit();
+ _screen6.setup(3260, 2, 1);
+ _screen6.setPosition(Common::Point(166, 30));
+ _screen6.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen6.setAction(&_action6, &_screen6);
+
+ _screen7.postInit();
+ _screen7.setup(3260, 2, 1);
+ _screen7.setPosition(Common::Point(190, 22));
+ _screen7.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen7.setAction(&_action7, &_screen7);
+
+ _screen8.postInit();
+ _screen8.setup(3260, 2, 1);
+ _screen8.setPosition(Common::Point(142, 14));
+ _screen8.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen8.setAction(&_action8, &_screen8);
+
+ _screen9.postInit();
+ _screen9.setup(3260, 2, 1);
+ _screen9.setPosition(Common::Point(166, 6));
+ _screen9.setDetails(3260, 3, 1, 5, 1, (SceneItem *)NULL);
+ _screen9.setAction(&_action9, &_screen9);
+
+ _securityConsole.postInit();
+ _securityConsole.setup(3260, 3, 1);
+ _securityConsole.setPosition(Common::Point(265, 163));
+ _securityConsole.fixPriority(180);
+ _securityConsole._numFrames = 10;
+ _securityConsole.setDetails(3260, 6, 1, 8, 1, (SceneItem *)NULL);
+ _securityConsole.animate(ANIM_MODE_2, NULL);
+
+ _computerConsole.postInit();
+ _computerConsole.setup(3260, 4, 1);
+ _computerConsole.setPosition(Common::Point(127, 108));
+ _computerConsole.fixPriority(120);
+ _computerConsole.setAction(&_action11, &_computerConsole);
+ _computerConsole._numFrames = 15;
+ _computerConsole.setDetails(3260, 6, 1, 8, 1, (SceneItem *)NULL);
+ _computerConsole.animate(ANIM_MODE_2, NULL);
+
+ _lightingConsole.postInit();
+ _lightingConsole.setup(3260, 5, 1);
+ _lightingConsole.setPosition(Common::Point(274, 65));
+ _lightingConsole.setAction(&_action12, &_lightingConsole);
+ _lightingConsole._numFrames = 5;
+ _lightingConsole.setDetails(3260, 9, 1, 11, 1, (SceneItem *)NULL);
+ _lightingConsole.animate(ANIM_MODE_2, NULL);
+
+ _background.setDetails(Rect(0, 0, 320, 200), 3260, 0, 1, 2, 1, NULL);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._oldCharacterScene[3] == 3275) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 3275) {
_sceneMode = 3270;
- setAction(&_sequenceManager, this, 3270, &R2_GLOBALS._player, &_actor13, NULL);
+ setAction(&_sequenceManager, this, 3270, &R2_GLOBALS._player, &_door, NULL);
} else {
R2_GLOBALS._player.setup(30, 5, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
@@ -1506,7 +1536,7 @@ void Scene3260::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._player.enableControl();
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3260;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3260;
}
void Scene3260::remove() {
@@ -1521,15 +1551,15 @@ void Scene3260::signal() {
break;
case 3272:
_sceneMode = 3273;
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- SceneItem::display(3260, 15, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999);
+ R2_GLOBALS._events.setCursor(CURSOR_WALK);
+ SceneItem::display(3260, 15, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
R2_GLOBALS._player.disableControl();
- R2_INVENTORY.setObjectScene(52, 3);
- R2_INVENTORY.setObjectScene(43, 3);
- setAction(&_sequenceManager, this, 3273, &R2_GLOBALS._player, &_actor14, NULL);
+ R2_INVENTORY.setObjectScene(R2_TOOLBOX, 3);
+ R2_INVENTORY.setObjectScene(R2_LASER_HACKSAW, 3);
+ setAction(&_sequenceManager, this, 3273, &R2_GLOBALS._player, &_toolbox, NULL);
break;
case 3273:
- _actor4.remove();
+ _screen4.remove();
R2_GLOBALS._player.enableControl();
break;
default:
@@ -1542,19 +1572,20 @@ void Scene3260::signal() {
* Scene 3275 - Hall
*
*--------------------------------------------------------------------------*/
-bool Scene3275::Actor2::startAction(CursorType action, Event &event) {
- Scene3275 *scene = (Scene3275 *)R2_GLOBALS._sceneManager._scene;
+bool Scene3275::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
+ Scene3275 *scene = (Scene3275 *)R2_GLOBALS._sceneManager._scene;
+
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3275;
- scene->setAction(&scene->_sequenceManager, scene, 3275, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3275, &R2_GLOBALS._player, &scene->_door, NULL);
return true;
}
-void Scene3275::Exit1::changeScene() {
+void Scene3275::CellExit::changeScene() {
Scene3275 *scene = (Scene3275 *)R2_GLOBALS._sceneManager._scene;
scene->_sceneMode = 0;
@@ -1573,33 +1604,31 @@ void Scene3275::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._sceneManager._previousScene = 3260;
if (R2_GLOBALS._sceneManager._previousScene == 3150)
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
- else
- g_globals->gfxManager()._bounds.moveTo(Common::Point(0, 0));
+ _sceneBounds = Rect(160, 0, 480, 200);
SceneExt::postInit();
- _exit1.setDetails(Rect(398, 60, 439, 118), SHADECURSOR_UP, 3150);
- _exit1.setDest(Common::Point(418, 128));
+ _cellExit.setDetails(Rect(398, 60, 439, 118), SHADECURSOR_UP, 3150);
+ _cellExit.setDest(Common::Point(418, 128));
- _actor1.postInit();
- _actor1.setup(3275, 1, 7);
- _actor1.setPosition(Common::Point(419, 119));
+ _doorFrame.postInit();
+ _doorFrame.setup(3275, 1, 7);
+ _doorFrame.setPosition(Common::Point(419, 119));
- _actor2.postInit();
- _actor2.setup(3275, 2, 1);
- _actor2.setPosition(Common::Point(56, 118));
- _actor2.setDetails(3275, 3, 4, -1, 1, (SceneItem *)NULL);
+ _door.postInit();
+ _door.setup(3275, 2, 1);
+ _door.setPosition(Common::Point(56, 118));
+ _door.setDetails(3275, 3, 4, -1, 1, (SceneItem *)NULL);
- _item2.setDetails(Rect(153, 58, 200, 120), 3275, 6, 7, 8, 1, NULL);
- _item3.setDetails(Rect(275, 58, 331, 120), 3275, 6, 7, 8, 1, NULL);
- _item4.setDetails(Rect(0, 66, 22, 127), 3275, 9, 10, 11, 1, NULL);
- _item5.setDetails(Rect(457, 66, 480, 127), 3275, 9, 10, 11, 1, NULL);
- _item1.setDetails(Rect(0, 0, 480, 200), 3275, 0, 1, 2, 1, NULL);
+ _emptyCell1.setDetails(Rect(153, 58, 200, 120), 3275, 6, 7, 8, 1, NULL);
+ _emptyCell2.setDetails(Rect(275, 58, 331, 120), 3275, 6, 7, 8, 1, NULL);
+ _securityBeams1.setDetails(Rect(0, 66, 22, 127), 3275, 9, 10, 11, 1, NULL);
+ _securityBeams2.setDetails(Rect(457, 66, 480, 127), 3275, 9, 10, 11, 1, NULL);
+ _background.setDetails(Rect(0, 0, 480, 200), 3275, 0, 1, 2, 1, NULL);
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._oldCharacterScene[3] == 3150) {
+ if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 3150) {
_sceneMode = 11;
R2_GLOBALS._player.setup(30, 3, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
@@ -1608,9 +1637,9 @@ void Scene3275::postInit(SceneObjectList *OwnerList) {
Common::Point pt(418, 128);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
- } else if (R2_GLOBALS._player._oldCharacterScene[3] == 3260) {
+ } else if (R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] == 3260) {
_sceneMode = 3276;
- setAction(&_sequenceManager, this, 3276, &R2_GLOBALS._player, &_actor2, NULL);
+ setAction(&_sequenceManager, this, 3276, &R2_GLOBALS._player, &_door, NULL);
} else {
R2_GLOBALS._player.setup(30, 3, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
@@ -1618,7 +1647,7 @@ void Scene3275::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._player.enableControl();
}
- R2_GLOBALS._player._oldCharacterScene[3] = 3275;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 3275;
}
void Scene3275::signal() {
@@ -1639,10 +1668,12 @@ void Scene3275::signal() {
* Scene 3350 - Cutscene - Ship landing
*
*--------------------------------------------------------------------------*/
+
void Scene3350::postInit(SceneObjectList *OwnerList) {
loadScene(3350);
R2_GLOBALS._uiElements._active = false;
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
R2_GLOBALS._sound2.play(310);
_rotation = R2_GLOBALS._scenePalette.addRotation(176, 203, 1);
@@ -1652,27 +1683,27 @@ void Scene3350::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.hide();
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- _actor1.hide();
- _actor2.postInit();
- _actor2.hide();
- _actor3.postInit();
- _actor3.hide();
- _actor4.postInit();
- _actor4.hide();
- _actor9.postInit();
- _actor9.hide();
- _actor8.postInit();
- _actor8.hide();
- _actor5.postInit();
- _actor5.hide();
- _actor6.postInit();
- _actor6.hide();
- _actor7.postInit();
- _actor7.hide();
+ _miranda.postInit();
+ _miranda.hide();
+ _seeker.postInit();
+ _seeker.hide();
+ _webbster.postInit();
+ _webbster.hide();
+ _seatedPeople.postInit();
+ _seatedPeople.hide();
+ _shipFront.postInit();
+ _shipFront.hide();
+ _canopy.postInit();
+ _canopy.hide();
+ _ship.postInit();
+ _ship.hide();
+ _landedShip.postInit();
+ _landedShip.hide();
+ _shipShadow.postInit();
+ _shipShadow.hide();
_sceneMode = 3350;
- setAction(&_sequenceManager, this, _sceneMode, &_actor5, &_actor6, &_actor7, NULL);
+ setAction(&_sequenceManager, this, _sceneMode, &_ship, &_landedShip, &_shipShadow, NULL);
}
void Scene3350::remove() {
@@ -1684,11 +1715,13 @@ void Scene3350::signal() {
switch (_sceneMode) {
case 3350:
_sceneMode = 3351;
- setAction(&_sequenceManager, this, 3351, &_actor4, &_actor9, &_actor8, NULL);
+ setAction(&_sequenceManager, this, 3351, &_seatedPeople, &_shipFront, &_canopy, NULL);
break;
case 3351:
_sceneMode = 3352;
- setAction(&_sequenceManager, this, 3352, &_actor4, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3352, &_seatedPeople, &R2_GLOBALS._player,
+ &_miranda, &_seeker, &_webbster, NULL);
+ break;
case 3352:
R2_GLOBALS._sceneManager.changeScene(3395);
break;
@@ -1699,109 +1732,103 @@ void Scene3350::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 3375 -
+ * Scene 3375 - Circular Walkway
*
*--------------------------------------------------------------------------*/
-Scene3375::Scene3375() {
- _field1488 = _field1492 = 0;
- for (int i = 0; i < 4; ++i)
- _field148A[i] = 0;
-}
void Scene3375::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field1488);
- s.syncAsSint16LE(_field1492);
+ s.syncAsSint16LE(_newSceneMode);
for (int i = 0; i < 4; ++i)
- s.syncAsSint16LE(_field148A[i]);
+ s.syncAsSint16LE(_sceneAreas[i]);
}
-void Scene3375::subFC696(int sceneMode) {
+void Scene3375::enterArea(int sceneMode) {
switch (sceneMode) {
case 3379:
R2_GLOBALS._player.setPosition(Common::Point(0, 155));
- _actor1.setPosition(Common::Point(-20, 163));
- _actor2.setPosition(Common::Point(-5, 150));
- _actor3.setPosition(Common::Point(-20, 152));
+ _companion1.setPosition(Common::Point(-20, 163));
+ _companion2.setPosition(Common::Point(-5, 150));
+ _webbster.setPosition(Common::Point(-20, 152));
break;
case 3380:
- ++R2_GLOBALS._v56A9E;
- if (R2_GLOBALS._v56A9E >= 4)
- R2_GLOBALS._v56A9E = 0;
+ ++R2_GLOBALS._walkwaySceneNumber;
+ if (R2_GLOBALS._walkwaySceneNumber >= 4)
+ R2_GLOBALS._walkwaySceneNumber = 0;
- loadScene(_field148A[R2_GLOBALS._v56A9E]);
+ loadScene(_sceneAreas[R2_GLOBALS._walkwaySceneNumber]);
R2_GLOBALS._uiElements.show();
R2_GLOBALS._player.setStrip(4);
R2_GLOBALS._player.setPosition(Common::Point(148, 230));
- _actor1.setPosition(Common::Point(191, 274));
- _actor1._effect = 1;
- _actor2.setPosition(Common::Point(124, 255));
- _actor2._effect = 1;
- _actor3.setPosition(Common::Point(155, 245));
- _actor3._effect = 1;
+ _companion1.setPosition(Common::Point(191, 274));
+ _companion1._effect = EFFECT_SHADED;
+ _companion2.setPosition(Common::Point(124, 255));
+ _companion2._effect = EFFECT_SHADED;
+ _webbster.setPosition(Common::Point(155, 245));
+ _webbster._effect = EFFECT_SHADED;
break;
case 3381:
- --R2_GLOBALS._v56A9E;
- if (R2_GLOBALS._v56A9E < 0)
- R2_GLOBALS._v56A9E = 3;
+ --R2_GLOBALS._walkwaySceneNumber;
+ if (R2_GLOBALS._walkwaySceneNumber < 0)
+ R2_GLOBALS._walkwaySceneNumber = 3;
- loadScene(_field148A[R2_GLOBALS._v56A9E]);
+ loadScene(_sceneAreas[R2_GLOBALS._walkwaySceneNumber]);
R2_GLOBALS._uiElements.show();
R2_GLOBALS._player.setStrip(6);
R2_GLOBALS._player.setPosition(Common::Point(201, 131));
- _actor1.setPosition(Common::Point(231, 127));
- _actor1._effect = 1;
- _actor2.setPosition(Common::Point(231, 127));
- _actor2._effect = 1;
- _actor3.setPosition(Common::Point(231, 127));
- _actor3._effect = 1;
+ _companion1.setPosition(Common::Point(231, 127));
+ _companion1._effect = EFFECT_SHADED;
+ _companion2.setPosition(Common::Point(231, 127));
+ _companion2._effect = EFFECT_SHADED;
+ _webbster.setPosition(Common::Point(231, 127));
+ _webbster._effect = EFFECT_SHADED;
break;
default:
R2_GLOBALS._player.setPosition(Common::Point(192, 155));
- _actor1.setPosition(Common::Point(138, 134));
- _actor2.setPosition(Common::Point(110, 139));
- _actor3.setPosition(Common::Point(125, 142));
+ _companion1.setPosition(Common::Point(138, 134));
+ _companion2.setPosition(Common::Point(110, 139));
+ _webbster.setPosition(Common::Point(125, 142));
break;
}
- if (R2_GLOBALS._v56A9E == 2) {
- R2_GLOBALS._sceneItems.remove(&_actor4);
+ if (R2_GLOBALS._walkwaySceneNumber == 2) {
+ R2_GLOBALS._sceneItems.remove(&_door);
for (int i = 0; i <= 12; i++)
R2_GLOBALS._sceneItems.remove(&_itemArray[i]);
- R2_GLOBALS._sceneItems.remove(&_item1);
+ R2_GLOBALS._sceneItems.remove(&_background);
- _actor4.show();
- _actor4.setDetails(3375, 9, 10, -1, 1, (SceneItem *)NULL);
+ _door.show();
+ _door.setDetails(3375, 9, 10, -1, 1, (SceneItem *)NULL);
for (int i = 0; i <= 12; i++)
_itemArray[i].setDetails(3375, 3, -1, -1);
- _item1.setDetails(Rect(0, 0, 320, 200), 3375, 0, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 3375, 0, -1, -1, 1, NULL);
} else {
- _actor4.hide();
- R2_GLOBALS._sceneItems.remove(&_actor4);
+ _door.hide();
+ R2_GLOBALS._sceneItems.remove(&_door);
}
if (_sceneMode == 0)
signal();
else
- setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_companion1, &_companion2, &_webbster, NULL);
}
-bool Scene3375::Actor1::startAction(CursorType action, Event &event) {
- Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3375::Companion2::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3304, scene);
@@ -1809,14 +1836,14 @@ bool Scene3375::Actor1::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3375::Actor2::startAction(CursorType action, Event &event) {
- Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3375::Companion1::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3301, scene);
@@ -1824,69 +1851,70 @@ bool Scene3375::Actor2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3375::Actor3::startAction(CursorType action, Event &event) {
- Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3375::Webbster::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
scene->_stripManager.start(3303, scene);
return true;
}
-bool Scene3375::Actor4::startAction(CursorType action, Event &event) {
- Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3375::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
- if (R2_GLOBALS._v56A9E != 0) {
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
+ if (R2_GLOBALS._walkwaySceneNumber != 0) {
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(3);
} else {
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.enableRegion(3);
+ R2_GLOBALS._walkRegions.enableRegion(4);
}
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(7);
- R2_GLOBALS._walkRegions.disableRegion(8);
+ R2_GLOBALS._walkRegions.enableRegion(6);
+ R2_GLOBALS._walkRegions.enableRegion(7);
+ R2_GLOBALS._walkRegions.enableRegion(8);
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 3375;
- scene->setAction(&scene->_sequenceManager, scene, 3375, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3375, &R2_GLOBALS._player,
+ &scene->_companion1, &scene->_companion2, &scene->_webbster, &scene->_door, NULL);
return true;
}
-void Scene3375::Exit1::changeScene() {
+void Scene3375::LeftExit::changeScene() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 3376;
- if (R2_GLOBALS._v56A9E != 0) {
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
+ if (R2_GLOBALS._walkwaySceneNumber != 0) {
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(3);
} else {
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.enableRegion(3);
+ R2_GLOBALS._walkRegions.enableRegion(4);
}
- if (scene->_actor1._position.y != 163) {
- R2_GLOBALS._player.setStrip(-1);
- scene->_actor1.setStrip2(-1);
- scene->_actor2.setStrip2(-1);
- scene->_actor3.setStrip2(-1);
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, NULL);
+ if (scene->_companion1._position.y != 163) {
+ R2_GLOBALS._player.setStrip2(-1);
+ scene->_companion1.setStrip2(-1);
+ scene->_companion2.setStrip2(-1);
+ scene->_webbster.setStrip2(-1);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_companion1, &scene->_companion2, &scene->_webbster, NULL);
} else {
R2_GLOBALS._player.setStrip2(2);
- scene->_actor1.setStrip2(2);
- scene->_actor2.setStrip2(2);
- scene->_actor3.setStrip2(2);
+ scene->_companion1.setStrip2(2);
+ scene->_companion2.setStrip2(2);
+ scene->_webbster.setStrip2(2);
R2_GLOBALS._sound2.play(314);
Common::Point pt(50, 150);
@@ -1895,57 +1923,61 @@ void Scene3375::Exit1::changeScene() {
}
}
-void Scene3375::Exit2::changeScene() {
+void Scene3375::DownExit::changeScene() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
R2_GLOBALS._player._shade = 4;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 3377;
- scene->_field1488 = 3381;
+ scene->_newSceneMode = 3381;
- if (R2_GLOBALS._v56A9E != 0) {
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
+ if (R2_GLOBALS._walkwaySceneNumber != 0) {
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(3);
} else {
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.enableRegion(3);
+ R2_GLOBALS._walkRegions.enableRegion(4);
}
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_companion1, &scene->_companion2, &scene->_webbster, NULL);
}
-void Scene3375::Exit3::changeScene() {
+void Scene3375::RightExit::changeScene() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
_moving = false;
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
R2_GLOBALS._player._shade = 4;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 3378;
- scene->_field1488 = 3380;
+ scene->_newSceneMode = 3380;
- if (R2_GLOBALS._v56A9E != 0) {
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
+ if (R2_GLOBALS._walkwaySceneNumber != 0) {
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(3);
} else {
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.enableRegion(3);
+ R2_GLOBALS._walkRegions.enableRegion(4);
}
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_companion1, &scene->_companion2, &scene->_webbster, NULL);
}
-void Scene3375::postInit(SceneObjectList *OwnerList) {
- _field148A[0] = 3376;
- _field148A[1] = 3377;
- _field148A[2] = 3375;
- _field148A[3] = 3378;
+Scene3375::Scene3375() {
+ _newSceneMode = 0;
+
+ _sceneAreas[0] = 3376;
+ _sceneAreas[1] = 3377;
+ _sceneAreas[2] = 3375;
+ _sceneAreas[3] = 3378;
+}
- loadScene(_field148A[R2_GLOBALS._v56A9E]);
+void Scene3375::postInit(SceneObjectList *OwnerList) {
+ loadScene(_sceneAreas[R2_GLOBALS._walkwaySceneNumber]);
SceneExt::postInit();
R2_GLOBALS._sound1.play(313);
@@ -1957,28 +1989,28 @@ void Scene3375::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_mirandaSpeaker);
_stripManager.addSpeaker(&_webbsterSpeaker);
- R2_GLOBALS._player._characterScene[1] = 3375;
- R2_GLOBALS._player._characterScene[2] = 3375;
- R2_GLOBALS._player._characterScene[3] = 3375;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3375;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3375;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3375;
setZoomPercents(126, 55, 200, 167);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- } else {
+ else
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- }
+
R2_GLOBALS._player.changeZoom(-1);
switch (R2_GLOBALS._player._characterIndex) {
- case 2:
+ case R2_SEEKER:
if (R2_GLOBALS._sceneManager._previousScene == 3385)
R2_GLOBALS._player.setup(20, 1, 1);
else
R2_GLOBALS._player.setup(20, 3, 1);
break;
- case 3:
+ case R2_MIRANDA:
if (R2_GLOBALS._sceneManager._previousScene == 3385)
R2_GLOBALS._player.setup(30, 1, 1);
else
@@ -1995,16 +2027,16 @@ void Scene3375::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor1._moveRate = 10;
- _actor1._moveDiff = Common::Point(3, 2);
+ _companion1.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _companion1._moveRate = 10;
+ _companion1._moveDiff = Common::Point(3, 2);
} else {
- _actor1._moveRate = 7;
- _actor1._moveDiff = Common::Point(5, 3);
+ _companion1._moveRate = 7;
+ _companion1._moveDiff = Common::Point(5, 3);
}
- _actor1.changeZoom(-1);
- _actor1._effect = 1;
+ _companion1.changeZoom(-1);
+ _companion1._effect = EFFECT_SHADED;
int tmpStrip, tmpVisage;
if (R2_GLOBALS._sceneManager._previousScene == 3385)
@@ -2012,72 +2044,72 @@ void Scene3375::postInit(SceneObjectList *OwnerList) {
else
tmpStrip = 4;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
tmpVisage = 10;
else
tmpVisage = 20;
- _actor1.setup(tmpVisage, tmpStrip, 1);
- _actor1.animate(ANIM_MODE_1, NULL);
+ _companion1.setup(tmpVisage, tmpStrip, 1);
+ _companion1.animate(ANIM_MODE_1, NULL);
- _actor2.postInit();
- _actor2._moveDiff = Common::Point(3, 2);
- _actor2.changeZoom(-1);
- _actor2._effect = 1;
+ _companion2.postInit();
+ _companion2._moveDiff = Common::Point(3, 2);
+ _companion2.changeZoom(-1);
+ _companion2._effect = EFFECT_SHADED;
if (R2_GLOBALS._sceneManager._previousScene == 3385)
tmpStrip = 1;
else
tmpStrip = 8;
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
tmpVisage = 10;
else
tmpVisage = 30;
- _actor2.setup(tmpVisage, tmpStrip, 1);
- _actor2.animate(ANIM_MODE_1, NULL);
+ _companion2.setup(tmpVisage, tmpStrip, 1);
+ _companion2.animate(ANIM_MODE_1, NULL);
- _actor3.postInit();
- _actor3._moveRate = 7;
- _actor3._moveDiff = Common::Point(5, 3);
- _actor3.changeZoom(-1);
- _actor3._effect = 1;
+ _webbster.postInit();
+ _webbster._moveRate = 7;
+ _webbster._moveDiff = Common::Point(5, 3);
+ _webbster.changeZoom(-1);
+ _webbster._effect = EFFECT_SHADED;
if (R2_GLOBALS._sceneManager._previousScene == 3385)
tmpStrip = 1;
else
tmpStrip = 4;
- _actor3.setup(40, tmpStrip, 1);
- _actor3.animate(ANIM_MODE_1, NULL);
+ _webbster.setup(40, tmpStrip, 1);
+ _webbster.animate(ANIM_MODE_1, NULL);
- _actor2.setDetails(3375, -1, -1, -1, 1, (SceneItem *)NULL);
- _actor3.setDetails(3375, 21, -1, -1, 1, (SceneItem *)NULL);
- _actor1.setDetails(3375, -1, -1, -1, 1, (SceneItem *)NULL);
+ _companion2.setDetails(3375, -1, -1, -1, 1, (SceneItem *)NULL);
+ _webbster.setDetails(3375, 21, -1, -1, 1, (SceneItem *)NULL);
+ _companion1.setDetails(3375, -1, -1, -1, 1, (SceneItem *)NULL);
- _actor4.postInit();
- _actor4.setup(3375, 1, 1);
- _actor4.setPosition(Common::Point(254, 166));
- _actor4.fixPriority(140);
- _actor4.hide();
+ _door.postInit();
+ _door.setup(3375, 1, 1);
+ _door.setPosition(Common::Point(254, 166));
+ _door.fixPriority(140);
+ _door.hide();
- _exit1.setDetails(Rect(0, 84, 24, 167), EXITCURSOR_W, 3375);
- _exit1.setDest(Common::Point(65, 155));
- _exit2.setDetails(Rect(103, 152, 183, 170), SHADECURSOR_DOWN, 3375);
- _exit2.setDest(Common::Point(158, 151));
- _exit3.setDetails(Rect(180, 75, 213, 132), EXITCURSOR_E, 3375);
- _exit3.setDest(Common::Point(201, 131));
+ _leftExit.setDetails(Rect(0, 84, 24, 167), EXITCURSOR_W, 3375);
+ _leftExit.setDest(Common::Point(65, 155));
+ _downExit.setDetails(Rect(103, 152, 183, 170), SHADECURSOR_DOWN, 3375);
+ _downExit.setDest(Common::Point(158, 151));
+ _rightExit.setDetails(Rect(180, 75, 213, 132), EXITCURSOR_E, 3375);
+ _rightExit.setDest(Common::Point(201, 131));
for (int i = 0; i <= 12; ++i)
_itemArray[i].setDetails(i, 3375, 3, -1, -1);
- _item1.setDetails(Rect(0, 0, 320, 200), 3375, 0, -1, 1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 3375, 0, -1, 1, 1, NULL);
if (R2_GLOBALS._sceneManager._previousScene == 3385)
_sceneMode = 3379;
else
_sceneMode = 0;
- subFC696(_sceneMode);
+ enterArea(_sceneMode);
}
void Scene3375::remove() {
@@ -2086,44 +2118,61 @@ void Scene3375::remove() {
}
void Scene3375::signalCase3379() {
- switch (R2_GLOBALS._v56A9E) {
+ switch (R2_GLOBALS._walkwaySceneNumber) {
case 0:
- _exit1._enabled = true;
- if (R2_GLOBALS._sceneManager._previousScene == 3385)
- R2_GLOBALS._walkRegions.enableRegion(1);
- else {
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(4);
+ _leftExit._enabled = true;
+ if (R2_GLOBALS._sceneManager._previousScene == 3385) {
+ // WORKAROUND: The original disables the left entry region here for
+ // some reason. But there's also some walk issue even I leave it enabled.
+ // Instead, for now, add an extra walk into the properly enabled regions
+ _sceneMode = 1;
+ ADD_MOVER(R2_GLOBALS._player, 70, R2_GLOBALS._player._position.y);
+ R2_GLOBALS._sceneManager._previousScene = 3375;
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
+ _companion1._effect = EFFECT_SHADED;
+ _companion2._effect = EFFECT_SHADED;
+ _webbster._effect = EFFECT_SHADED;
+
+ return;
+ //R2_GLOBALS._walkRegions.disableRegion(1);
+ } else {
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
}
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ break;
case 2:
- _exit1._enabled = false;
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(8);
- R2_GLOBALS._walkRegions.enableRegion(9);
+ _leftExit._enabled = false;
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(8);
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ break;
default:
- _exit1._enabled = false;
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(3);
- R2_GLOBALS._walkRegions.enableRegion(5);
- R2_GLOBALS._walkRegions.enableRegion(6);
+ _leftExit._enabled = false;
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
break;
}
R2_GLOBALS._sceneManager._previousScene = 3375;
- R2_GLOBALS._player._effect = 1;
- _actor1._effect = 1;
- _actor2._effect = 1;
- _actor3._effect = 1;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
+ _companion1._effect = EFFECT_SHADED;
+ _companion2._effect = EFFECT_SHADED;
+ _webbster._effect = EFFECT_SHADED;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
}
void Scene3375::signal() {
switch (_sceneMode) {
+ case 1:
+ R2_GLOBALS._player.enableControl();
+ break;
case 3375:
R2_GLOBALS._sceneManager.changeScene(3400);
break;
@@ -2133,29 +2182,39 @@ void Scene3375::signal() {
case 3377:
// No break on purpose
case 3378:
- _sceneMode = _field1488;
- _field1488 = 0;
- _actor1._effect = 6;
- _actor1._shade = 4;
- _actor2._effect = 6;
- _actor2._shade = 4;
- _actor3._effect = 6;
- _actor3._shade = 4;
- subFC696(_sceneMode);
+ _sceneMode = _newSceneMode;
+ _newSceneMode = 0;
+
+ _companion1._effect = EFFECT_SHADED2;
+ _companion1._shade = 4;
+ _companion2._effect = EFFECT_SHADED2;
+ _companion2._shade = 4;
+ _webbster._effect = EFFECT_SHADED2;
+ _webbster._shade = 4;
+
+ // HACK: Reset zooms in order to avoid giant characters on the upper right of the screen
+ R2_GLOBALS._player.setZoom(-1);
+ _companion1.setZoom(-1);
+ _companion2.setZoom(-1);
+ _webbster.setZoom(-1);
+ //
+
+ enterArea(_sceneMode);
break;
case 3379:
signalCase3379();
break;
case 9999:
- if (_actor1._position.y == 163)
+ if (_companion1._position.y == 163)
R2_GLOBALS._player.setStrip(1);
else
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS._player.enableControl(CURSOR_TALK);
+ break;
default:
- _actor1.setPriority(130);
- _actor2.setPriority(132);
- _actor3.setPriority(134);
+ _companion1.setPriority(130);
+ _companion2.setPriority(132);
+ _webbster.setPriority(134);
signalCase3379();
break;
}
@@ -2163,50 +2222,51 @@ void Scene3375::signal() {
void Scene3375::dispatch() {
if ((R2_GLOBALS._player._position.y >= 168) && (R2_GLOBALS._player._effect == 1))
- R2_GLOBALS._player._effect = 6;
+ R2_GLOBALS._player._effect = EFFECT_SHADED2;
else if ((R2_GLOBALS._player._position.y < 168) && (R2_GLOBALS._player._effect == 6))
- R2_GLOBALS._player._effect = 1;
+ R2_GLOBALS._player._effect = EFFECT_SHADED;
- if ((_actor1._position.y >= 168) && (_actor1._effect == 1))
- _actor1._effect = 6;
- else if ((_actor1._position.y < 168) && (_actor1._effect == 6))
- _actor1._effect = 1;
+ if ((_companion1._position.y >= 168) && (_companion1._effect == 1))
+ _companion1._effect = EFFECT_SHADED2;
+ else if ((_companion1._position.y < 168) && (_companion1._effect == 6))
+ _companion1._effect = EFFECT_SHADED;
- if ((_actor2._position.y >= 168) && (_actor2._effect == 1))
- _actor2._effect = 6;
- else if ((_actor2._position.y < 168) && (_actor2._effect == 6))
- _actor2._effect = 1;
+ if ((_companion2._position.y >= 168) && (_companion2._effect == 1))
+ _companion2._effect = EFFECT_SHADED2;
+ else if ((_companion2._position.y < 168) && (_companion2._effect == 6))
+ _companion2._effect = EFFECT_SHADED;
- if ((_actor3._position.y >= 168) && (_actor3._effect == 1))
- _actor3._effect = 6;
- else if ((_actor3._position.y < 168) && (_actor3._effect == 6))
- _actor3._effect = 1;
+ if ((_webbster._position.y >= 168) && (_webbster._effect == 1))
+ _webbster._effect = EFFECT_SHADED2;
+ else if ((_webbster._position.y < 168) && (_webbster._effect == 6))
+ _webbster._effect = EFFECT_SHADED;
Scene::dispatch();
}
/*--------------------------------------------------------------------------
- * Scene 3385 -
+ * Scene 3385 - Corridor
*
*--------------------------------------------------------------------------*/
+
Scene3385::Scene3385() {
- _field11B2 = 0;
+ _playerStrip = 0;
}
void Scene3385::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field11B2);
+ s.syncAsSint16LE(_playerStrip);
}
-bool Scene3385::Actor1::startAction(CursorType action, Event &event) {
- Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3385::Companion1::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3304, scene);
@@ -2214,14 +2274,14 @@ bool Scene3385::Actor1::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3385::Actor2::startAction(CursorType action, Event &event) {
- Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3385::Companion2::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3301, scene);
@@ -2229,21 +2289,19 @@ bool Scene3385::Actor2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3385::Actor3::startAction(CursorType action, Event &event) {
- Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3385::Webbster::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
scene->_stripManager.start(3303, scene);
return true;
}
-bool Scene3385::Actor4::startAction(CursorType action, Event &event) {
- Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3385::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -2251,20 +2309,26 @@ bool Scene3385::Actor4::startAction(CursorType action, Event &event) {
if (R2_GLOBALS._sceneManager._previousScene == 3375)
R2_GLOBALS._sound2.play(314);
+ Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 3386;
- scene->setAction(&scene->_sequenceManager, scene, 3386, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3386, &R2_GLOBALS._player,
+ &scene->_companion1, &scene->_companion2, &scene->_webbster, &scene->_door,
+ NULL);
return true;
}
-void Scene3385::Exit1::changeScene() {
+void Scene3385::SouthExit::changeScene() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 3387;
if (R2_GLOBALS._sceneManager._previousScene == 3375)
- scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode,
+ &R2_GLOBALS._player, &scene->_companion1, &scene->_companion2,
+ &scene->_webbster, NULL);
else
scene->signal();
}
@@ -2292,103 +2356,103 @@ void Scene3385::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_mirandaSpeaker);
_stripManager.addSpeaker(&_webbsterSpeaker);
- R2_GLOBALS._player._characterScene[1] = 3385;
- R2_GLOBALS._player._characterScene[2] = 3385;
- R2_GLOBALS._player._characterScene[3] = 3385;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3385;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3385;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3385;
if (R2_GLOBALS._sceneManager._previousScene == 3375)
- _field11B2 = 3;
+ _playerStrip = 3;
else
- _field11B2 = 4;
+ _playerStrip = 4;
setZoomPercents(102, 40, 200, 160);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
else
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._player.changeZoom(-1);
- if (R2_GLOBALS._player._characterIndex == 2)
- R2_GLOBALS._player.setup(20, _field11B2, 1);
- else if (R2_GLOBALS._player._characterIndex == 3)
- R2_GLOBALS._player.setup(30, _field11B2, 1);
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ R2_GLOBALS._player.setup(20, _playerStrip, 1);
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ R2_GLOBALS._player.setup(30, _playerStrip, 1);
else
- R2_GLOBALS._player.setup(10, _field11B2, 1);
+ R2_GLOBALS._player.setup(10, _playerStrip, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor1._moveRate = 10;
- _actor1._moveDiff = Common::Point(3, 2);
+ _companion1.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _companion1._moveRate = 10;
+ _companion1._moveDiff = Common::Point(3, 2);
} else {
- _actor1._moveRate = 7;
- _actor1._moveDiff = Common::Point(5, 3);
+ _companion1._moveRate = 7;
+ _companion1._moveDiff = Common::Point(5, 3);
}
- _actor1.changeZoom(-1);
- _actor1._effect = 1;
- if (R2_GLOBALS._player._characterIndex == 2)
- _actor1.setup(10, _field11B2, 1);
+ _companion1.changeZoom(-1);
+ _companion1._effect = EFFECT_SHADED;
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _companion1.setup(10, _playerStrip, 1);
else
- _actor1.setup(20, _field11B2, 1);
- _actor1.animate(ANIM_MODE_1, NULL);
- _actor1.setDetails(3385, -1, -1, -1, 1, (SceneItem *) NULL);
-
- _actor2.postInit();
- _actor2._moveDiff = Common::Point(3, 2);
- _actor2.changeZoom(-1);
- _actor2._effect = 1;
- if (R2_GLOBALS._player._characterIndex == 3)
- _actor2.setup(10, _field11B2, 1);
+ _companion1.setup(20, _playerStrip, 1);
+ _companion1.animate(ANIM_MODE_1, NULL);
+ _companion1.setDetails(3385, -1, -1, -1, 1, (SceneItem *) NULL);
+
+ _companion2.postInit();
+ _companion2._moveDiff = Common::Point(3, 2);
+ _companion2.changeZoom(-1);
+ _companion2._effect = EFFECT_SHADED;
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ _companion2.setup(10, _playerStrip, 1);
else
- _actor2.setup(30, _field11B2, 1);
- _actor2.animate(ANIM_MODE_1, NULL);
- _actor2.setDetails(3385, -1, -1, -1, 1, (SceneItem *) NULL);
-
- _actor3.postInit();
- _actor3._moveDiff = Common::Point(3, 2);
- _actor3.changeZoom(-1);
- _actor3._effect = 1;
- _actor3.setup(40, _field11B2, 1);
- _actor3.animate(ANIM_MODE_1, NULL);
- _actor3.setDetails(3385, 15, -1, -1, 1, (SceneItem *) NULL);
-
- _exit1.setDetails(Rect(103, 152, 217, 170), SHADECURSOR_DOWN, 3395);
- _exit1.setDest(Common::Point(158, 151));
-
- _actor4.postInit();
- _actor4.setPosition(Common::Point(160, 100));
- _actor4.fixPriority(90);
- _actor4.setDetails(3385, 3, 4, -1, 1, (SceneItem *) NULL);
+ _companion2.setup(30, _playerStrip, 1);
+ _companion2.animate(ANIM_MODE_1, NULL);
+ _companion2.setDetails(3385, -1, -1, -1, 1, (SceneItem *) NULL);
+
+ _webbster.postInit();
+ _webbster._moveDiff = Common::Point(3, 2);
+ _webbster.changeZoom(-1);
+ _webbster._effect = EFFECT_SHADED;
+ _webbster.setup(40, _playerStrip, 1);
+ _webbster.animate(ANIM_MODE_1, NULL);
+ _webbster.setDetails(3385, 15, -1, -1, 1, (SceneItem *) NULL);
+
+ _southExit.setDetails(Rect(103, 152, 217, 170), SHADECURSOR_DOWN, 3395);
+ _southExit.setDest(Common::Point(158, 151));
+
+ _door.postInit();
+ _door.setPosition(Common::Point(160, 100));
+ _door.fixPriority(90);
+ _door.setDetails(3385, 3, 4, -1, 1, (SceneItem *) NULL);
if (R2_GLOBALS._sceneManager._previousScene == 3375) {
R2_GLOBALS._player.setPosition(Common::Point(158, 102));
- _actor1.setPosition(Common::Point(164, 100));
- _actor1.fixPriority(98);
- _actor2.setPosition(Common::Point(150, 100));
- _actor2.fixPriority(97);
- _actor3.setPosition(Common::Point(158, 100));
- _actor3.fixPriority(96);
+ _companion1.setPosition(Common::Point(164, 100));
+ _companion1.fixPriority(98);
+ _companion2.setPosition(Common::Point(150, 100));
+ _companion2.fixPriority(97);
+ _webbster.setPosition(Common::Point(158, 100));
+ _webbster.fixPriority(96);
_sceneMode = 3384;
- _actor4.setup(3385, 1, 6);
- _actor4.animate(ANIM_MODE_6, this);
- setAction(&_action1, &_actor4);
+ _door.setup(3385, 1, 6);
+ _door.animate(ANIM_MODE_6, this);
+ setAction(&_action1, &_door);
} else {
R2_GLOBALS._player.setPosition(Common::Point(158, 230));
- _actor1.setPosition(Common::Point(191, 270));
- _actor2.setPosition(Common::Point(124, 255));
- _actor3.setPosition(Common::Point(155, 245));
- _actor4.setup(3385, 1, 1);
+ _companion1.setPosition(Common::Point(191, 270));
+ _companion2.setPosition(Common::Point(124, 255));
+ _webbster.setPosition(Common::Point(155, 245));
+ _door.setup(3385, 1, 1);
_sceneMode = 3385;
- setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_companion1, &_companion2, &_webbster, NULL);
}
- _item1.setDetails(Rect(0, 0, 320, 200), 3385, 0, -1, -1, 1, NULL);
- R2_GLOBALS._v56A9E = 0;
+ _background.setDetails(Rect(0, 0, 320, 200), 3385, 0, -1, -1, 1, NULL);
+ R2_GLOBALS._walkwaySceneNumber = 0;
}
void Scene3385::remove() {
@@ -2412,33 +2476,34 @@ void Scene3385::signal() {
R2_GLOBALS._player.enableControl(CURSOR_TALK);
break;
default:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
/*--------------------------------------------------------------------------
- * Scene 3395 -
+ * Scene 3395 - Walkway
*
*--------------------------------------------------------------------------*/
+
Scene3395::Scene3395() {
- _field142E = 0;
+ _playerStrip = 0;
}
void Scene3395::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field142E);
+ s.syncAsSint16LE(_playerStrip);
}
-bool Scene3395::Actor1::startAction(CursorType action, Event &event) {
- Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3395::Companion1::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3304, scene);
@@ -2446,14 +2511,14 @@ bool Scene3395::Actor1::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3395::Actor2::startAction(CursorType action, Event &event) {
- Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3395::Companion2::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
scene->_stripManager.start(3302, scene);
else
scene->_stripManager.start(3301, scene);
@@ -2461,21 +2526,19 @@ bool Scene3395::Actor2::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3395::Actor3::startAction(CursorType action, Event &event) {
- Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3395::Webbster::startAction(CursorType action, Event &event) {
if (action != CURSOR_TALK)
return SceneActor::startAction(action, event);
+ Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 9999;
scene->_stripManager.start(3303, scene);
return true;
}
-bool Scene3395::Actor4::startAction(CursorType action, Event &event) {
- Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
-
+bool Scene3395::Door::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -2483,8 +2546,12 @@ bool Scene3395::Actor4::startAction(CursorType action, Event &event) {
if (R2_GLOBALS._sceneManager._previousScene == 3385)
R2_GLOBALS._sound2.play(314);
+ Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
+
scene->_sceneMode = 3396;
- scene->setAction(&scene->_sequenceManager, scene, 3396, &R2_GLOBALS._player, &scene->_actor1, &scene->_actor2, &scene->_actor3, &scene->_actor4, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 3396, &R2_GLOBALS._player,
+ &scene->_companion1, &scene->_companion2, &scene->_webbster, &scene->_door,
+ NULL);
return true;
}
@@ -2512,106 +2579,106 @@ void Scene3395::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_mirandaSpeaker);
_stripManager.addSpeaker(&_webbsterSpeaker);
- R2_GLOBALS._player._characterScene[1] = 3395;
- R2_GLOBALS._player._characterScene[2] = 3395;
- R2_GLOBALS._player._characterScene[3] = 3395;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3395;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3395;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3395;
if (R2_GLOBALS._sceneManager._previousScene == 3385)
- _field142E = 3;
+ _playerStrip = 3;
else
- _field142E = 4;
+ _playerStrip = 4;
setZoomPercents(51, 40, 200, 137);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
else
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._player.changeZoom(-1);
- if (R2_GLOBALS._player._characterIndex == 2)
- R2_GLOBALS._player.setup(20, _field142E, 1);
- else if (R2_GLOBALS._player._characterIndex == 3)
- R2_GLOBALS._player.setup(30, _field142E, 1);
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ R2_GLOBALS._player.setup(20, _playerStrip, 1);
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ R2_GLOBALS._player.setup(30, _playerStrip, 1);
else
- R2_GLOBALS._player.setup(10, _field142E, 1);
+ R2_GLOBALS._player.setup(10, _playerStrip, 1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor1._moveRate = 10;
- _actor1._moveDiff = Common::Point(3, 2);
+ _companion1.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _companion1._moveRate = 10;
+ _companion1._moveDiff = Common::Point(3, 2);
} else {
- _actor1._moveRate = 7;
- _actor1._moveDiff = Common::Point(5, 3);
+ _companion1._moveRate = 7;
+ _companion1._moveDiff = Common::Point(5, 3);
}
- _actor1.changeZoom(-1);
- _actor1._effect = 1;
- if (R2_GLOBALS._player._characterIndex == 2)
- _actor1.setup(10, _field142E, 1);
+ _companion1.changeZoom(-1);
+ _companion1._effect = EFFECT_SHADED;
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _companion1.setup(10, _playerStrip, 1);
else
- _actor1.setup(20, _field142E, 1);
- _actor1.animate(ANIM_MODE_1, NULL);
- _actor1.setDetails(3395, -1, -1, -1, 1, (SceneItem *) NULL);
-
- _actor2.postInit();
- _actor2._moveDiff = Common::Point(3, 2);
- _actor2.changeZoom(-1);
- _actor2._effect = 1;
- if (R2_GLOBALS._player._characterIndex == 3)
- _actor2.setup(10, _field142E, 1);
+ _companion1.setup(20, _playerStrip, 1);
+ _companion1.animate(ANIM_MODE_1, NULL);
+ _companion1.setDetails(3395, -1, -1, -1, 1, (SceneItem *) NULL);
+
+ _companion2.postInit();
+ _companion2._moveDiff = Common::Point(3, 2);
+ _companion2.changeZoom(-1);
+ _companion2._effect = EFFECT_SHADED;
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ _companion2.setup(10, _playerStrip, 1);
else
- _actor2.setup(30, _field142E, 1);
- _actor2.animate(ANIM_MODE_1, NULL);
- _actor2.setDetails(3395, -1, -1, -1, 1, (SceneItem *) NULL);
-
- _actor3.postInit();
- _actor3._moveDiff = Common::Point(3, 2);
- _actor3.changeZoom(-1);
- _actor3._effect = 1;
- _actor3.setup(40, _field142E, 1);
- _actor3.animate(ANIM_MODE_1, NULL);
- _actor3.setDetails(3385, 18, -1, -1, 1, (SceneItem *) NULL);
-
- _actor4.postInit();
- _actor4.setPosition(Common::Point(159, 50));
- _actor4.fixPriority(40);
- _actor4.setDetails(3395, 6, 7, -1, 1, (SceneItem *) NULL);
+ _companion2.setup(30, _playerStrip, 1);
+ _companion2.animate(ANIM_MODE_1, NULL);
+ _companion2.setDetails(3395, -1, -1, -1, 1, (SceneItem *) NULL);
+
+ _webbster.postInit();
+ _webbster._moveDiff = Common::Point(3, 2);
+ _webbster.changeZoom(-1);
+ _webbster._effect = EFFECT_SHADED;
+ _webbster.setup(40, _playerStrip, 1);
+ _webbster.animate(ANIM_MODE_1, NULL);
+ _webbster.setDetails(3395, 18, -1, -1, 1, (SceneItem *) NULL);
+
+ _door.postInit();
+ _door.setPosition(Common::Point(159, 50));
+ _door.fixPriority(40);
+ _door.setDetails(3395, 6, 7, -1, 1, (SceneItem *) NULL);
if (R2_GLOBALS._sceneManager._previousScene == 3385) {
R2_GLOBALS._player.setPosition(Common::Point(158, 53));
- _actor1.setPosition(Common::Point(164, 51));
- _actor1.fixPriority(48);
- _actor2.setPosition(Common::Point(150, 51));
- _actor2.fixPriority(47);
- _actor3.setPosition(Common::Point(158, 51));
- _actor3.fixPriority(46);
+ _companion1.setPosition(Common::Point(164, 51));
+ _companion1.fixPriority(48);
+ _companion2.setPosition(Common::Point(150, 51));
+ _companion2.fixPriority(47);
+ _webbster.setPosition(Common::Point(158, 51));
+ _webbster.fixPriority(46);
_sceneMode = 3394;
- _actor4.setup(3395, 1, 7);
- _actor4.animate(ANIM_MODE_6, this);
- setAction(&_action1, &_actor4);
+ _door.setup(3395, 1, 7);
+ _door.animate(ANIM_MODE_6, this);
+ setAction(&_action1, &_door);
} else {
R2_GLOBALS._player.setPosition(Common::Point(158, 200));
- _actor1.setPosition(Common::Point(191, 255));
- _actor2.setPosition(Common::Point(124, 240));
- _actor3.setPosition(Common::Point(155, 242));
- _actor4.setup(3395, 1, 1);
+ _companion1.setPosition(Common::Point(191, 255));
+ _companion2.setPosition(Common::Point(124, 240));
+ _webbster.setPosition(Common::Point(155, 242));
+ _door.setup(3395, 1, 1);
- R2_GLOBALS._walkRegions.enableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(1);
_sceneMode = 3395;
- setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, _sceneMode, &R2_GLOBALS._player, &_companion1, &_companion2, &_webbster, NULL);
}
for (int i = 0; i <= 12; i++) {
- _itemArray[i].setDetails(i, 3995, 0, -1, -1);
+ _itemArray[i].setDetails(i, 3395, 0, -1, -1);
}
- _item1.setDetails(Rect(0, 0, 320, 200), 3395, 3, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 3395, 3, -1, -1, 1, NULL);
}
void Scene3395::remove() {
@@ -2632,31 +2699,32 @@ void Scene3395::signal() {
R2_GLOBALS._player.enableControl(CURSOR_TALK);
break;
default:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
}
/*--------------------------------------------------------------------------
- * Scene 3400 -
+ * Scene 3400 - Confrontation
*
*--------------------------------------------------------------------------*/
+
Scene3400::Scene3400() {
- _field157C = 0;
+ _soundFaded = false;
}
void Scene3400::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field157C);
+ s.syncAsSint16LE(_soundFaded);
}
void Scene3400::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
+ _sceneBounds = Rect(160, 0, 480, 200);
+
loadScene(3400);
- _field157C = 0;
- R2_GLOBALS._v558B6.set(60, 0, 260, 200);
+ _soundFaded = false;
SceneExt::postInit();
R2_GLOBALS._sound1.play(317);
@@ -2669,26 +2737,26 @@ void Scene3400::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_tealSpeaker);
setZoomPercents(51, 46, 180, 200);
- R2_GLOBALS._player._characterScene[1] = 3400;
- R2_GLOBALS._player._characterScene[2] = 3400;
- R2_GLOBALS._player._characterScene[3] = 3400;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3400;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3400;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3400;
- _actor7.postInit();
- _actor7.setup(3403, 1, 1);
- _actor7.setPosition(Common::Point(190, 103));
- _actor7.fixPriority(89);
+ _manholeCover.postInit();
+ _manholeCover.setup(3403, 1, 1);
+ _manholeCover.setPosition(Common::Point(190, 103));
+ _manholeCover.fixPriority(89);
R2_GLOBALS._player.postInit();
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
else
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
R2_GLOBALS._player.changeZoom(-1);
R2_GLOBALS._player.setPosition(Common::Point(239, 64));
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player.setup(20, 5, 1);
- else if (R2_GLOBALS._player._characterIndex == 3)
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
R2_GLOBALS._player.setup(30, 5, 1);
else
R2_GLOBALS._player.setup(10, 5, 1);
@@ -2696,52 +2764,52 @@ void Scene3400::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _actor1.postInit();
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor1._numFrames = 10;
- _actor1._moveDiff = Common::Point(3, 2);
+ _companion1.postInit();
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _companion1._numFrames = 10;
+ _companion1._moveDiff = Common::Point(3, 2);
} else {
- _actor1._numFrames = 7;
- _actor1._moveDiff = Common::Point(5, 3);
+ _companion1._numFrames = 7;
+ _companion1._moveDiff = Common::Point(5, 3);
}
- _actor1.changeZoom(-1);
- _actor1._effect = 1;
- _actor1.setPosition(Common::Point(247, 63));
- if (R2_GLOBALS._player._characterIndex == 2)
- _actor1.setup(10, 5, 1);
+ _companion1.changeZoom(-1);
+ _companion1._effect = EFFECT_SHADED;
+ _companion1.setPosition(Common::Point(247, 63));
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _companion1.setup(10, 5, 1);
else
- _actor1.setup(20, 5, 1);
- _actor1.animate(ANIM_MODE_1, NULL);
-
- _actor2.postInit();
- _actor2._moveDiff = Common::Point(3, 2);
- _actor2.changeZoom(-1);
- _actor2._effect = 1;
- _actor2.setPosition(Common::Point(225, 63));
- if (R2_GLOBALS._player._characterIndex == 3)
- _actor2.setup(10, 5, 1);
+ _companion1.setup(20, 5, 1);
+ _companion1.animate(ANIM_MODE_1, NULL);
+
+ _companion2.postInit();
+ _companion2._moveDiff = Common::Point(3, 2);
+ _companion2.changeZoom(-1);
+ _companion2._effect = EFFECT_SHADED;
+ _companion2.setPosition(Common::Point(225, 63));
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ _companion2.setup(10, 5, 1);
else
- _actor2.setup(30, 5, 1);
- _actor2.animate(ANIM_MODE_1, NULL);
-
- _actor3.postInit();
- _actor3._numFrames = 7;
- _actor3._moveDiff = Common::Point(5, 3);
- _actor3.changeZoom(-1);
- _actor3._effect = 1;
- _actor3.setPosition(Common::Point(235, 61));
- _actor3.setup(40, 3, 1);
- _actor3.animate(ANIM_MODE_1, NULL);
-
- _actor6.postInit();
- _actor6.setup(3400, 1, 6);
- _actor6.setPosition(Common::Point(236, 51));
- _actor6.fixPriority(51);
- _actor6.animate(ANIM_MODE_6, NULL);
+ _companion2.setup(30, 5, 1);
+ _companion2.animate(ANIM_MODE_1, NULL);
+
+ _webbster.postInit();
+ _webbster._numFrames = 7;
+ _webbster._moveDiff = Common::Point(5, 3);
+ _webbster.changeZoom(-1);
+ _webbster._effect = EFFECT_SHADED;
+ _webbster.setPosition(Common::Point(235, 61));
+ _webbster.setup(40, 3, 1);
+ _webbster.animate(ANIM_MODE_1, NULL);
+
+ _door.postInit();
+ _door.setup(3400, 1, 6);
+ _door.setPosition(Common::Point(236, 51));
+ _door.fixPriority(51);
+ _door.animate(ANIM_MODE_6, NULL);
R2_GLOBALS.clearFlag(71);
_sceneMode = 3400;
- setAction(&_sequenceManager, this, 3400, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3400, &R2_GLOBALS._player, &_companion1, &_companion2, &_webbster, NULL);
}
void Scene3400::remove() {
@@ -2753,223 +2821,236 @@ void Scene3400::remove() {
void Scene3400::signal() {
switch (_sceneMode) {
case 3305: {
- warning("STUB: sub_1D227()");
+ // First part of discussion
_tealSpeaker._object1.hide();
- _actor4.show();
- _actor4.setStrip(1);
+ _teal.show();
+ _teal.setStrip(1);
Common::Point pt(158, 190);
NpcMover *mover = new NpcMover();
- _actor4.addMover(mover, &pt, this);
+ _teal.addMover(mover, &pt, this);
_sceneMode = 3402;
- setAction(&_sequenceManager, this, 3402, &R2_GLOBALS._player, &_actor1, &_actor2, &_actor3, NULL);
+ setAction(&_sequenceManager, this, 3402, &R2_GLOBALS._player, &_companion1, &_companion2, &_webbster, NULL);
}
break;
case 3306:
+ // Teal picks up the sapphire
R2_GLOBALS._sound2.play(318);
- _actor1.setStrip(2);
+ _companion1.setStrip(2);
R2_GLOBALS._player.setStrip(6);
- _actor2.setStrip(6);
- _actor3.setStrip(3);
- _actor4.setStrip(1);
- R2_INVENTORY.setObjectScene(34, 0);
+ _companion2.setStrip(6);
+ _webbster.setStrip(3);
+ _teal.setStrip(1);
+ R2_INVENTORY.setObjectScene(R2_SAPPHIRE_BLUE, 0);
_stripManager.start(3307, this);
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_sceneMode = 3400;
- R2_GLOBALS._player.setAction(&_sequenceManager, this, 3400, &R2_GLOBALS._player, &_actor4, &_actor8, NULL);
+ R2_GLOBALS._player.setAction(&_sequenceManager, this, 3400, &R2_GLOBALS._player, &_teal, &_sapphire, NULL);
} else {
_sceneMode = 3408;
- _actor1.setAction(&_sequenceManager, this, 3408, &_actor1, &_actor4, &_actor8, NULL);
+ _companion1.setAction(&_sequenceManager, this, 3408, &_companion1, &_teal, &_sapphire, NULL);
}
break;
case 3307:
case 3404:
case 3408:
- if (_field157C == 0) {
+ // A tasp!
+ if (!_soundFaded) {
R2_GLOBALS._sound2.fadeOut2(NULL);
- _field157C = 1;
+ _soundFaded = true;
} else {
_sceneMode = 3308;
_stripManager.start(3308, this);
}
break;
case 3308:
- warning("STUB: sub_1D227()");
- _actor1.setStrip(2);
+ // Characters teleport one after the other
+ _companion1.setStrip(2);
R2_GLOBALS._player.setStrip(6);
- _actor2.setStrip(6);
- _actor3.setStrip(3);
- _actor4.setStrip(1);
+ _companion2.setStrip(6);
+ _webbster.setStrip(3);
+ _teal.setStrip(1);
_sceneMode = 3403;
- if (R2_GLOBALS._player._characterIndex == 2)
- setAction(&_sequenceManager, this, 3403, &R2_GLOBALS._player, &_actor3, &_actor7, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ setAction(&_sequenceManager, this, 3403, &R2_GLOBALS._player, &_webbster, &_manholeCover, NULL);
else
- setAction(&_sequenceManager, this, 3403, &_actor1, &_actor3, &_actor7, NULL);
+ setAction(&_sequenceManager, this, 3403, &_companion1, &_webbster, &_manholeCover, NULL);
break;
case 3309:
- warning("STUB: sub_1D227()");
- _actor4.setStrip(1);
+ // Miranda teleports away
+ _teal.setStrip(1);
_sceneMode = 3405;
- if (R2_GLOBALS._player._characterIndex == 3)
- setAction(&_sequenceManager, this, 3405, &R2_GLOBALS._player, &_actor7, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ setAction(&_sequenceManager, this, 3405, &R2_GLOBALS._player, &_manholeCover, NULL);
else
- setAction(&_sequenceManager, this, 3405, &_actor2, &_actor7, NULL);
+ setAction(&_sequenceManager, this, 3405, &_companion2, &_manholeCover, NULL);
break;
case 3310:
- warning("STUB: sub_1D227()");
- _actor4.setStrip(1);
+ // Quinn teleports away
+ _teal.setStrip(1);
_sceneMode = 3406;
- if (R2_GLOBALS._player._characterIndex == 1)
- setAction(&_sequenceManager, this, 3406, &R2_GLOBALS._player, &_actor7, NULL);
- else if (R2_GLOBALS._player._characterIndex == 2)
- setAction(&_sequenceManager, this, 3406, &_actor1, &_actor7, NULL);
- else if (R2_GLOBALS._player._characterIndex == 3)
- setAction(&_sequenceManager, this, 3406, &_actor2, &_actor7, NULL);
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
+ setAction(&_sequenceManager, this, 3406, &R2_GLOBALS._player, &_manholeCover, NULL);
+ else if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ setAction(&_sequenceManager, this, 3406, &_companion1, &_manholeCover, NULL);
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
+ setAction(&_sequenceManager, this, 3406, &_companion2, &_manholeCover, NULL);
break;
case 3311:
- warning("STUB: sub_1D227()");
+ // Teal teleports away
_tealSpeaker._object1.hide();
- _actor4.show();
- _actor4.setStrip(1);
+ _teal.show();
+ _teal.setStrip(1);
_sceneMode = 3407;
- setAction(&_sequenceManager, this, 3407, &_actor4, &_actor7, NULL);
+ setAction(&_sequenceManager, this, 3407, &_teal, &_manholeCover, NULL);
break;
case 3400: {
- _actor8.postInit();
- _actor8.hide();
- _actor4.postInit();
- _actor4._numFrames = 7;
- _actor4._moveDiff = Common::Point(3, 2);
- _actor4.changeZoom(-1);
- _actor4._effect = 1;
- _actor4.setPosition(Common::Point(-15, 90));
- _actor4.setup(3402, 1, 1);
- _actor4.animate(ANIM_MODE_1, NULL);
+ // Teal enters the room
+ _sapphire.postInit();
+ _sapphire.hide();
+ _teal.postInit();
+ _teal._numFrames = 7;
+ _teal._moveDiff = Common::Point(3, 2);
+ _teal.changeZoom(-1);
+ _teal._effect = EFFECT_SHADED;
+ _teal.setPosition(Common::Point(-15, 90));
+ _teal.setup(3402, 1, 1);
+ _teal.animate(ANIM_MODE_1, NULL);
Common::Point pt1(115, 90);
NpcMover *mover1 = new NpcMover();
- _actor4.addMover(mover1, &pt1, this);
- R2_GLOBALS._scrollFollower = &_actor4;
+ _teal.addMover(mover1, &pt1, this);
+ R2_GLOBALS._scrollFollower = &_teal;
Common::Point pt2(203, 76);
NpcMover *mover2 = new NpcMover();
- _actor3.addMover(mover2, &pt2, NULL);
+ _webbster.addMover(mover2, &pt2, NULL);
_sceneMode = 3401;
}
break;
case 3401:
+ // Teal first speech
_sceneMode = 3305;
_stripManager.start(3305, this);
break;
case 3402:
+ // Betrayal of Webbster
_sceneMode = 3306;
_stripManager.start(3306, this);
break;
case 3403:
+ // Teal: "Miranda..."
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
_sceneMode = 3309;
_stripManager.start(3309, this);
break;
case 3405:
+ // Teal: "And Quinn..."
_sceneMode = 3310;
_stripManager.start(3310, this);
break;
case 3406:
+ // Teal final sentence before teleporting
_sceneMode = 3311;
_stripManager.start(3311, this);
break;
case 3407:
+ // End of scene
R2_GLOBALS._sceneManager.changeScene(3600);
break;
default:
+ // Unexpected scene mode
R2_GLOBALS._player.enableControl();
break;
}
}
/*--------------------------------------------------------------------------
- * Scene 3500 -
+ * Scene 3500 - Flub tube maze
*
*--------------------------------------------------------------------------*/
+
Scene3500::Action1::Action1() {
- _field1E = 0;
- _field20 = 0;
+ _direction = 0;
+ _field20 = false;
_field22 = 0;
- _field24 = 0;
+ _field24 = false;
}
void Scene3500::Action1::synchronize(Serializer &s) {
Action::synchronize(s);
- s.syncAsSint16LE(_field1E);
+ s.syncAsSint16LE(_direction);
s.syncAsSint16LE(_field20);
s.syncAsSint16LE(_field22);
s.syncAsSint16LE(_field24);
}
-void Scene3500::Action1::sub108670(int arg1) {
+void Scene3500::Action1::handleHorzButton(int direction) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- _field1E = arg1;
- _field20 = 1;
- _field24 = 1;
+ // Direction: -1 == Left, 1 == Right
+ _direction = direction;
+ _field20 = true;
+ _field24 = true;
- scene->_actor9.setStrip(2);
- scene->_actor9.show();
+ scene->_tunnelHorzCircle.setStrip(2);
+ scene->_tunnelHorzCircle.show();
- if (_field1E == 1)
- scene->_actor6.show();
+ if (_direction == 1)
+ scene->_symbolRight.show();
else
- scene->_actor5.show();
+ scene->_symbolLeft.show();
- if (scene->_actor1._frame % 2 == 0)
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ if (scene->_shuttle._frame % 2 == 0) {
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
+ }
setActionIndex(0);
}
-void Scene3500::Action1::sub108732(int arg1) {
+void Scene3500::Action1::turnShuttle(bool arg1) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
_field20 = arg1;
- _field1E = -_field1E;
+ _direction = -_direction;
- if (_field1E == 1) {
- scene->_actor6.show();
- scene->_actor5.hide();
+ if (_direction == 1) {
+ scene->_symbolRight.show();
+ scene->_symbolLeft.hide();
} else {
- scene->_actor5.show();
- scene->_actor6.hide();
+ scene->_symbolLeft.show();
+ scene->_symbolRight.hide();
}
switch (_actionIndex) {
case 4:
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
// No break on purpose
case 3:
_actionIndex = 10;
setDelay(0);
break;
case 5: {
- scene->_fieldAF8 = 160;
+ scene->_moverVertX = 160;
Common::Point pt(160, 73);
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, NULL);
+ scene->_tunnelVertCircle.addMover(mover, &pt, NULL);
- scene->_fieldB9E = 160 - (_field1E * 2 * 160);
- Common::Point pt2(scene->_fieldB9E, 73);
+ scene->_moverHorzX = 160 - (_direction * 2 * 160);
+ Common::Point pt2(scene->_moverHorzX, 73);
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, this);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, this);
_actionIndex = 11;
}
break;
case 6:
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
setDelay(1);
// No break on purpose
case 8:
- scene->_actor9.setStrip(2);
+ scene->_tunnelHorzCircle.setStrip(2);
_actionIndex = 1;
break;
default:
@@ -2977,372 +3058,161 @@ 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;
switch(_actionIndex++) {
case 0:
R2_GLOBALS._player.disableControl();
- scene->_field1286 = 0;
- if (scene->_field1270 != 0) {
- scene->_field1270 = 0;
- scene->_field126E = 0;
- scene->_field1272 = 0;
+ scene->_directionChangesEnabled = false;
+ if (scene->_speed != 0) {
+ scene->_speed = 0;
+ scene->_mazeChangeAmount = 0;
+ scene->_field1272 = false;
scene->_rotation->_idxChange = 0;
}
break;
case 1:
- if ((scene->_actor1._frame % 2) == 0) {
+ if ((scene->_shuttle._frame % 2) == 1) {
setDelay(1);
return;
}
// No break on purpose
case 3:
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
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);
-
- if ((scene->_actor1._frame % 2) != 0) {
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ int cellId = 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->_shuttle._frame % 2) != 0) {
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
}
- int var8 = (scene->_action1._field1E * 2 + scene->_field1276);
- if (var8 > 7)
- var8 = 1;
- else if (var8 < 1)
- var8 = 7;
-
- switch (var8) {
- case 0:
- if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 23) && (si != 24) && (si != 4) && (si != 11))
+ // Get the new direction starting on
+ int direction = (scene->_action1._direction * 2 + scene->_mazeDirection);
+ if (direction > MAZEDIR_NORTHWEST)
+ direction = MAZEDIR_NORTH;
+ else if (direction < MAZEDIR_NORTH)
+ direction = MAZEDIR_WEST;
+
+ // Check whether movement is allowed in that direction. If so, then
+ // movement is started again
+ switch (direction) {
+ case MAZEDIR_NORTH:
+ if ( ((cellId != 2) && (cellId != 3) && (cellId != 6) && (cellId != 1) && (cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 11))
|| (var6 != 0)) {
- if ((si != 25) && (si != 26) && (si != 5) && (si != 14) && (si != 15))
- _field20 = 0;
+ if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId != 15))
+ _field20 = false;
else if ((var6 != 0) || (di <= 3)) // useless, skipped: "|| (di == 0)"
- _field20 = 0;
+ _field20 = false;
else
- _field20 = 1;
+ _field20 = true;
} else
- _field20 = 1;
+ _field20 = true;
break;
- case 2:
- if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 26) && (si != 24) && (si != 15) && (si != 6) && (si != 31))
+ case MAZEDIR_EAST:
+ if ( ((cellId != 12) && (cellId != 13) && (cellId != 11) && (cellId != 16) && (cellId != 26) && (cellId != 24) && (cellId != 15) && (cellId != 6) && (cellId != 31))
|| (di != 0)) {
- if ((si != 25) && (si != 23) && (si != 14) && (si != 5) && (si != 4))
- _field20 = 0;
+ if ((cellId != 25) && (cellId != 23) && (cellId != 14) && (cellId != 5) && (cellId != 4))
+ _field20 = false;
else if ((di != 0) || (var6 <= 3)) // useless, skipped: "|| (var6 == 0)"
- _field20 = 0;
+ _field20 = false;
else
- _field20 = 1;
+ _field20 = true;
} else
- _field20 = 1;
+ _field20 = true;
break;
- case 4:
- if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 25) && (si != 26) && (si != 5) && (si != 16) && (si != 31))
+ case MAZEDIR_SOUTH:
+ if ( ((cellId != 2) && (cellId != 3) && (cellId != 6) && (cellId != 1) && (cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 16) && (cellId != 31))
|| (var6 != 0)) {
- if ((si != 23) && (si != 24) && (si != 4) && (si != 14) && (si != 15))
- _field20 = 0;
+ if ((cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 14) && (cellId != 15))
+ _field20 = false;
else if ((var6 != 0) || (di <= 3)) // useless, skipped: "|| (di == 0)"
- _field20 = 0;
+ _field20 = false;
else
- _field20 = 1;
+ _field20 = true;
} else
- _field20 = 1;
+ _field20 = true;
break;
- case 6:
- if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 25) && (si != 23) && (si != 14) && (si != 1) && (si != 31))
+ case MAZEDIR_WEST:
+ if ( ((cellId != 12) && (cellId != 13) && (cellId != 11) && (cellId != 16) && (cellId != 25) && (cellId != 23) && (cellId != 14) && (cellId != 1) && (cellId != 31))
|| (var6 != 0)) {
- if ((si != 26) && (si != 24) && (si != 15) && (si != 5) && (si != 4))
- _field20 = 0;
+ if ((cellId != 26) && (cellId != 24) && (cellId != 15) && (cellId != 5) && (cellId != 4))
+ _field20 = false;
else if ((var6 <= 0) || (di != 0)) // useless, skipped: "|| (var6 == 0)"
- _field20 = 0;
+ _field20 = false;
else
- _field20 = 1;
+ _field20 = true;
} else
- _field20 = 1;
+ _field20 = true;
default:
break;
}
}
// No break on purpose
case 2: {
- scene->_actor8.setPosition(Common::Point(160, 73));
- scene->_actor8._moveDiff.x = 160 - scene->_field126E;
- scene->_fieldAF8 = 160 - ((_field1E * 2) * 160);
- Common::Point pt(scene->_fieldAF8, 73);
+ scene->_tunnelVertCircle.setPosition(Common::Point(160, 73));
+ scene->_tunnelVertCircle._moveDiff.x = 160 - scene->_mazeChangeAmount;
+ scene->_moverVertX = 160 - ((_direction * 2) * 160);
+ Common::Point pt(scene->_moverVertX, 73);
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, this);
+ scene->_tunnelVertCircle.addMover(mover, &pt, this);
- scene->_actor9.setPosition(Common::Point(160 + ((_field1E * 2) * 160), 73));
- scene->_actor9._moveDiff.x = 160 - scene->_field126E;
- scene->_fieldB9E = 160;
- Common::Point pt2(scene->_fieldB9E, 73);
+ scene->_tunnelHorzCircle.setPosition(Common::Point(160 + ((_direction * 2) * 160), 73));
+ scene->_tunnelHorzCircle._moveDiff.x = 160 - scene->_mazeChangeAmount;
+ scene->_moverHorzX = 160;
+ Common::Point pt2(scene->_moverHorzX, 73);
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, NULL);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, NULL);
}
break;
case 5:
- scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ scene->_shuttle._frameChange = _direction;
+ scene->_mazeDirection = scene->_shuttle.changeFrame();
+ scene->_shuttle.setFrame(scene->_mazeDirection);
setDelay(1);
break;
case 6:
- scene->_actor8.setPosition(Common::Point(160, 73));
- if (_field20 == 0)
- scene->_actor8.setStrip(1);
+ scene->_tunnelVertCircle.setPosition(Common::Point(160, 73));
+ if (!_field20)
+ scene->_tunnelVertCircle.setStrip(1);
else
- scene->_actor8.setStrip(2);
- scene->_actor8.fixPriority(1);
+ scene->_tunnelVertCircle.setStrip(2);
+ scene->_tunnelVertCircle.fixPriority(1);
- scene->_actor9.setPosition(Common::Point(-160, 73));
- scene->_actor9.setStrip(9);
- scene->_actor9.fixPriority(11);
- scene->_actor9.hide();
+ scene->_tunnelHorzCircle.setPosition(Common::Point(-160, 73));
+ scene->_tunnelHorzCircle.setStrip(9);
+ scene->_tunnelHorzCircle.fixPriority(11);
+ scene->_tunnelHorzCircle.hide();
setDelay(1);
break;
case 7:
- if ((scene->_actor1._frame % 2) == 0) {
- scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ if ((scene->_shuttle._frame % 2) == 0) {
+ scene->_shuttle._frameChange = _direction;
+ scene->_mazeDirection = scene->_shuttle.changeFrame();
+ scene->_shuttle.setFrame(scene->_mazeDirection);
}
setDelay(1);
break;
case 8: {
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
- scene->_field1286 = 1;
- if ((scene->_actor1._frame % 2) == 0) {
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ scene->_directionChangesEnabled = true;
+ if ((scene->_shuttle._frame % 2) == 0) {
+ scene->_shuttle._frameChange = _direction;
+ scene->_shuttle.setFrame(scene->_shuttle.changeFrame());
}
- // All the var_8 initialization was missing in the original
+ // CHECKME: All the var_8 initialization was missing in the original
// 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 = (_direction * 2 + scene->_mazeDirection);
if (var_8 > 7)
var_8 = 1;
else if (var_8 < 1)
@@ -3353,57 +3223,57 @@ 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;
}
- scene->_actor5.hide();
- scene->_actor6.hide();
- _field24 = 0;
- if (_field20 == 0) {
- scene->_actor7.sub1094ED();
- if (scene->_field126E == scene->_field1270)
+ scene->_symbolLeft.hide();
+ scene->_symbolRight.hide();
+ _field24 = false;
+ if (!_field20) {
+ scene->_throttle.updateSpeed();
+ if (scene->_mazeChangeAmount == scene->_speed)
scene->_aSound1.play(276);
}
break;
}
case 10: {
- scene->_fieldAF8 = 160;
+ scene->_moverVertX = 160;
Common::Point pt(160, 73);
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, NULL);
+ scene->_tunnelVertCircle.addMover(mover, &pt, NULL);
- scene->_fieldB9E = 160 - (_field1E * 2 * 160);
- Common::Point pt2(scene->_fieldB9E, 73);
+ scene->_moverHorzX = 160 - (_direction * 2 * 160);
+ Common::Point pt2(scene->_moverHorzX, 73);
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, this);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, this);
_actionIndex = 6;
}
break;
case 11: {
- scene->_actor8.setStrip(2);
- scene->_actor8.setPosition(Common::Point(160, 73));
- scene->_fieldAF8 = 160 - (_field1E * 2 * 160);
- Common::Point pt(scene->_fieldAF8, 73);
+ scene->_tunnelVertCircle.setStrip(2);
+ scene->_tunnelVertCircle.setPosition(Common::Point(160, 73));
+ scene->_moverVertX = 160 - (_direction * 2 * 160);
+ Common::Point pt(scene->_moverVertX, 73);
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, NULL);
- scene->_actor8.fixPriority(11);
- if (_field20 == 0)
- scene->_actor9.setStrip(1);
+ scene->_tunnelVertCircle.addMover(mover, &pt, NULL);
+ scene->_tunnelVertCircle.fixPriority(11);
+ if (!_field20)
+ scene->_tunnelHorzCircle.setStrip(1);
else
- scene->_actor9.setStrip(2);
- scene->_actor9.setPosition(Common::Point(160 - (_field1E * 2 * 160), 73));
- scene->_fieldB9E = 160;
- Common::Point pt2(scene->_fieldB9E, 73);
+ scene->_tunnelHorzCircle.setStrip(2);
+ scene->_tunnelHorzCircle.setPosition(Common::Point(160 - (_direction * 2 * 160), 73));
+ scene->_moverHorzX = 160;
+ Common::Point pt2(scene->_moverHorzX, 73);
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, this);
- scene->_actor9.fixPriority(1);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, this);
+ scene->_tunnelHorzCircle.fixPriority(1);
_actionIndex = 5;
}
break;
@@ -3416,20 +3286,33 @@ 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();
}
}
-void Scene3500::Action2::sub10831F(int arg1) {
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Action2::Action2() {
+ _direction = 0;
+}
+
+void Scene3500::Action2::synchronize(Serializer &s) {
+ Action::synchronize(s);
+
+ s.syncAsSint16LE(_direction);
+}
+
+void Scene3500::Action2::handleVertButton(int direction) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- _field1E = arg1;
- if (_field1E == -1)
- scene->_actor3.setFrame2(3);
+ // Directions : 2 == up, -1 == down
+ _direction = direction;
+ if (_direction == -1)
+ scene->_horizontalSpeedDisplay.setFrame2(3);
else
- scene->_actor3.setFrame2(1);
+ scene->_horizontalSpeedDisplay.setFrame2(1);
setActionIndex(0);
}
@@ -3437,57 +3320,57 @@ void Scene3500::Action2::sub10831F(int arg1) {
void Scene3500::Action2::signal() {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- int si;
- int di;
+ int vertX;
+ int horzX;
switch (_actionIndex++) {
case 0: {
- if (scene->_actor8._mover) {
- si = scene->_fieldAF8;
- di = scene->_fieldB9E;
+ if (scene->_tunnelVertCircle._mover) {
+ vertX = scene->_moverVertX;
+ horzX = scene->_moverHorzX;
} else {
- scene->_fieldAF8 = scene->_actor8._position.x;
- si = scene->_fieldAF8;
- scene->_fieldB9E = scene->_actor9._position.y;
- di = scene->_fieldB9E;
+ scene->_moverVertX = scene->_tunnelVertCircle._position.x;
+ vertX = scene->_moverVertX;
+ scene->_moverHorzX = scene->_tunnelHorzCircle._position.y;
+ horzX = scene->_moverHorzX;
}
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
- Common::Point pt(si, 73 - (_field1E * 12));
+ scene->_tunnelVertCircle._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
+ Common::Point pt(vertX, 73 - (_direction * 12));
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, NULL);
+ scene->_tunnelVertCircle.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
- Common::Point pt2(di, 73 - (_field1E * 12));
+ scene->_tunnelHorzCircle._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
+ Common::Point pt2(horzX, 73 - (_direction * 12));
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, NULL);
- scene->_field126E = (scene->_field126E / 2) + (scene->_field126E % 2);
- setDelay(17 - scene->_field126E);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, NULL);
+ scene->_mazeChangeAmount = (scene->_mazeChangeAmount / 2) + (scene->_mazeChangeAmount % 2);
+ setDelay(17 - scene->_mazeChangeAmount);
}
break;
case 1: {
R2_GLOBALS._sound2.play(339);
- if (scene->_actor8._mover) {
- si = scene->_fieldAF8;
- di = scene->_fieldB9E;
+ if (scene->_tunnelVertCircle._mover) {
+ vertX = scene->_moverVertX;
+ horzX = scene->_moverHorzX;
} else {
- si = scene->_actor8._position.x;
- di = scene->_actor9._position.x;
+ vertX = scene->_tunnelVertCircle._position.x;
+ horzX = scene->_tunnelHorzCircle._position.x;
}
- scene->_actor7.sub1094ED();
+ scene->_throttle.updateSpeed();
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
- Common::Point pt(si, 73);
+ scene->_tunnelVertCircle._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
+ Common::Point pt(vertX, 73);
NpcMover *mover = new NpcMover();
- scene->_actor8.addMover(mover, &pt, NULL);
+ scene->_tunnelVertCircle.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
- Common::Point pt2(di, 73);
+ scene->_tunnelHorzCircle._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
+ Common::Point pt2(horzX, 73);
NpcMover *mover2 = new NpcMover();
- scene->_actor9.addMover(mover2, &pt2, NULL);
+ scene->_tunnelHorzCircle.addMover(mover2, &pt2, NULL);
- scene->_actor3.setFrame2(2);
+ scene->_horizontalSpeedDisplay.setFrame2(2);
}
break;
default:
@@ -3495,88 +3378,208 @@ void Scene3500::Action2::signal() {
}
}
-bool Scene3500::Item4::startAction(CursorType action, Event &event) {
+/*--------------------------------------------------------------------------*/
+
+Scene3500::DirectionButton::DirectionButton() {
+ _movementId = 0;
+}
+
+void Scene3500::DirectionButton::synchronize(Serializer &s) {
+ NamedHotspot::synchronize(s);
+
+ s.syncAsSint16LE(_movementId);
+}
+
+bool Scene3500::DirectionButton::startAction(CursorType action, Event &event) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- if (scene->_field1286 == 0)
+ if (!scene->_directionChangesEnabled) {
return true;
-
- if (scene->_field1286 != 4)
+ } else if (action == CURSOR_USE) {
+ R2_GLOBALS._sound2.play(14, nullptr, 63);
+ scene->doMovement(_movementId);
+ return true;
+ } else {
return SceneHotspot::startAction(action, event);
+ }
+}
- R2_GLOBALS._sound2.play(14);
- scene->sub107F71(_field34);
+/*--------------------------------------------------------------------------*/
- return true;
+Scene3500::Throttle::Throttle() {
+ _deltaX = 1;
+ _deltaY = 0;
+ _slideDeltaY = 0;
+ _deltaMouseY = 0;
+}
+
+void Scene3500::Throttle::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_pos.x);
+ s.syncAsSint16LE(_pos.y);
+ s.syncAsSint16LE(_deltaX);
+ s.syncAsSint16LE(_deltaY);
+ s.syncAsSint16LE(_slideDeltaY);
+ s.syncAsSint16LE(_deltaMouseY);
+}
+
+void Scene3500::Throttle::init(int xp, int yp, int dx, int dy, int speed) {
+ _deltaMouseY = 0;
+ _pos = Common::Point(xp, yp);
+ _deltaX = dx;
+ _deltaY = dy;
+ _slideDeltaY = _deltaY / _deltaX;
+
+ postInit();
+ setup(1050, 3, 1);
+ fixPriority(255);
+ setSpeed(speed);
+}
+
+void Scene3500::Throttle::updateSpeed() {
+ Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_speed = _position.x - _pos.x;
+}
+
+void Scene3500::Throttle::setSpeed(int arg1){
+ changePosition(Common::Point(_pos.x + arg1, _pos.y - (_slideDeltaY * arg1)));
+}
+
+void Scene3500::Throttle::changePosition(const Common::Point &pt) {
+ setPosition(pt);
}
-void Scene3500::Actor7::process(Event &event) {
+void Scene3500::Throttle::process(Event &event) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- if (scene->_field1286 == 0)
+ if (!scene->_directionChangesEnabled)
return;
if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE) && (_bounds.contains(event.mousePos))) {
- _fieldAE = 1 + event.mousePos.y - _position.y;
+ _deltaMouseY = 1 + event.mousePos.y - _position.y;
event.eventType = EVENT_NONE;
}
- if ((event.eventType == EVENT_BUTTON_UP) && (_fieldAE != 0)) {
- _fieldAE = 0;
+ if ((event.eventType == EVENT_BUTTON_UP) && (_deltaMouseY != 0)) {
+ _deltaMouseY = 0;
event.handled = true;
- if (scene->_action1._field24 == 0)
- sub1094ED();
+ if (!scene->_action1._field24)
+ updateSpeed();
}
- if (_fieldAE == 0)
+ if (_deltaMouseY == 0)
return;
R2_GLOBALS._sound2.play(338);
event.handled = true;
- int cx = event.mousePos.y - _fieldAE + 1;
- if (_fieldA6 >= cx) {
- if (_fieldA6 - _fieldAA <= cx)
- sub109693(Common::Point(((_fieldA6 - cx) / 2) + _fieldA4 + ((_fieldA6 - cx) % 2), cx));
+ int cx = event.mousePos.y - _deltaMouseY + 1;
+ if (_pos.y >= cx) {
+ if (_pos.y - _deltaY <= cx)
+ changePosition(Common::Point(((_pos.y - cx) / 2) + _pos.x + ((_pos.y - cx) % 2), cx));
else
- sub109693(Common::Point(_fieldA4 + _fieldA8, _fieldA6 - _fieldAA));
+ changePosition(Common::Point(_pos.x + _deltaX, _pos.y - _deltaY));
} else {
- sub109693(Common::Point(_fieldA4, _fieldA6));
+ changePosition(Common::Point(_pos.x, _pos.y));
}
}
-bool Scene3500::Actor7::startAction(CursorType action, Event &event) {
+bool Scene3500::Throttle::startAction(CursorType action, Event &event) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
- if (scene->_field1286 == 0)
+ if (!scene->_directionChangesEnabled) {
return true;
-
- if (scene->_field1286 == 4)
+ } else if (action == CURSOR_USE) {
return false;
+ } else {
+ return SceneActor::startAction(action, event);
+ }
+}
- return SceneActor::startAction(action, event);
+/*--------------------------------------------------------------------------*/
+
+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() {
+ _moverVertX = 0;
+ _moverHorzX = 0;
+ _rotation = NULL;
+ _mazeChangeAmount = 0;
+ _speed = 0;
+ _field1272 = false;
+ _mazeDirection = MAZEDIR_NONE;
+ _nextMove = 0;
+ _mazePosition.x = 0;
+ _mazePosition.y = 0;
+ _field1282 = true; // Set to true in fixup()
+ _field1284 = 0;
+ _directionChangesEnabled = false;
+}
+
+void Scene3500::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+ SYNC_POINTER(_rotation);
+
+ s.syncAsSint16LE(_moverVertX);
+ s.syncAsSint16LE(_moverHorzX);
+ s.syncAsSint16LE(_mazeChangeAmount);
+ s.syncAsSint16LE(_speed);
+ s.syncAsSint16LE(_field1272);
+ s.syncAsSint16LE(_mazeDirection);
+ s.syncAsSint16LE(_nextMove);
+ s.syncAsSint16LE(_mazePosition.x);
+ s.syncAsSint16LE(_mazePosition.y);
+ s.syncAsSint16LE(_field1282);
+ s.syncAsSint16LE(_field1284);
+ s.syncAsSint16LE(_directionChangesEnabled);
}
void Scene3500::postInit(SceneObjectList *OwnerList) {
byte tmpPal[768];
- Rect tmpRect;
loadScene(1050);
R2_GLOBALS._uiElements._active = false;
- R2_GLOBALS._v5589E.set(0, 0, 320, 200);
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
R2_GLOBALS._sound1.play(305);
R2_GLOBALS._player._characterIndex = R2_QUINN;
- R2_GLOBALS._player._characterScene[1] = 3500;
- R2_GLOBALS._player._characterScene[2] = 3500;
- R2_GLOBALS._player._characterScene[3] = 3500;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3500;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3500;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3500;
_field1284 = 0;
- _field1282 = 0;
- _field1278 = 0;
- _field1272 = 1;
- _field1270 = 4;
- _field126E = 4;
- _field127A = 860;
- _field127C = 891;
+ _field1282 = false;
+ _nextMove = 0;
+ _field1272 = true;
+ _speed = 4;
+ _mazeChangeAmount = 4;
+ _mazePosition = Common::Point(860, 891);
_rotation = R2_GLOBALS._scenePalette.addRotation(240, 254, -1);
_rotation->setDelay(0);
_rotation->_idxChange = 1;
@@ -3598,81 +3601,78 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._scenePalette._palette[(3 * i) + 2] = tmpPal[(3 * i) + 2];
}
- _actor7.sub109466(38, 165, 16, 32, _field1270);
- _actor7.setDetails(3500, 6, 7, -1, 1, (SceneItem *)NULL);
+ _throttle.init(38, 165, 16, 32, _speed);
+ _throttle.setDetails(3500, 6, 7, -1, 1, (SceneItem *)NULL);
R2_GLOBALS._sound1.play(276);
- _item4._field34 = 88;
- _item4.setDetails(88, 3500, 18, 10, -1);
-
- _item5._field34 = 112;
- _item5.setDetails(112, 3500, 9, 10, -1);
-
- _item6._field34 = 104;
- _item6.setDetails(104, 3500, 15, 10, -1);
-
- _item7._field34 = 96;
- _item7.setDetails(96, 3500, 12, 10, -1);
-
- _actor8.postInit();
- _actor8.setup(10501, 1, 1);
- _actor8.setPosition(Common::Point(160, 73));
- _actor8.fixPriority(1);
-
- _actor9.postInit();
- _actor9.setup(1050, 2, 1);
- _actor9.setPosition(Common::Point(-160, 73));
- _actor9.fixPriority(11);
- _actor9.hide();
-
- _item2.setDetails(27, 3500, 21, -1, -1);
- _item3.setDetails(Rect(160, 89, 299, 182), 3500, 3, -1, -1, 1, NULL);
- _item1.setDetails(Rect(0, 0, 320, 200), 3500, 0, -1, 2, 1, NULL);
-
- _actor1.postInit();
- _field1276 = 1;
- _actor1.setup(1004, 1, _field1276);
- _actor1.setPosition(Common::Point(230, 135));
- _actor1.fixPriority(200);
- _actor1._frameChange = 1;
-
- _actor5.postInit();
- _actor5.setup(1004, 3, 1);
- _actor5.setPosition(Common::Point(117, 163));
- _actor5.fixPriority(200);
- _actor5.hide();
-
- _actor4.postInit();
- _actor4.setup(1004, 3, 2);
- _actor4.setPosition(Common::Point(126, 163));
- _actor4.fixPriority(200);
-
- _actor6.postInit();
- _actor6.setup(1004, 3, 3);
- _actor6.setPosition(Common::Point(135, 163));
- _actor6.fixPriority(200);
- _actor6.hide();
-
- _actor2.postInit();
- _actor2.setup(1004, 4, _field126E + 1);
- _actor2.setPosition(Common::Point(126, 137));
- _actor2.fixPriority(200);
-
- _actor3.postInit();
- _actor3.setup(1004, 5, 2);
- _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));
-
- _action1._field24 = 0;
- warning("gfx_set_pane_p()");
- _unkObj1.sub51B02();
- warning("gfx_set_pane_p()");
- _field1286 = 1;
+ _pitchDown._movementId = 88;
+ _pitchDown.setDetails(88, 3500, 18, 10, -1);
+
+ _turnLeft._movementId = 112;
+ _turnLeft.setDetails(112, 3500, 9, 10, -1);
+
+ _pitchUp._movementId = 104;
+ _pitchUp.setDetails(104, 3500, 15, 10, -1);
+
+ _turnRight._movementId = 96;
+ _turnRight.setDetails(96, 3500, 12, 10, -1);
+
+ _tunnelVertCircle.postInit();
+ _tunnelVertCircle.setup(1050, 1, 1);
+ _tunnelVertCircle.setPosition(Common::Point(160, 73));
+ _tunnelVertCircle.fixPriority(1);
+
+ _tunnelHorzCircle.postInit();
+ _tunnelHorzCircle.setup(1050, 2, 1);
+ _tunnelHorzCircle.setPosition(Common::Point(-160, 73));
+ _tunnelHorzCircle.fixPriority(11);
+ _tunnelHorzCircle.hide();
+
+ _outsideView.setDetails(27, 3500, 21, -1, -1);
+ _mapScreen.setDetails(Rect(160, 89, 299, 182), 3500, 3, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 320, 200), 3500, 0, -1, 2, 1, NULL);
+
+ _shuttle.postInit();
+ _mazeDirection = MAZEDIR_NORTH;
+ _shuttle.setup(1004, 1, _mazeDirection);
+ _shuttle.setPosition(Common::Point(230, 135));
+ _shuttle.fixPriority(200);
+ _shuttle._frameChange = 1;
+
+ _symbolLeft.postInit();
+ _symbolLeft.setup(1004, 3, 1);
+ _symbolLeft.setPosition(Common::Point(117, 163));
+ _symbolLeft.fixPriority(200);
+ _symbolLeft.hide();
+
+ _symbolVertical.postInit();
+ _symbolVertical.setup(1004, 3, 2);
+ _symbolVertical.setPosition(Common::Point(126, 163));
+ _symbolVertical.fixPriority(200);
+
+ _symbolRight.postInit();
+ _symbolRight.setup(1004, 3, 3);
+ _symbolRight.setPosition(Common::Point(135, 163));
+ _symbolRight.fixPriority(200);
+ _symbolRight.hide();
+
+ _verticalSpeedDisplay.postInit();
+ _verticalSpeedDisplay.setup(1004, 4, _mazeChangeAmount + 1);
+ _verticalSpeedDisplay.setPosition(Common::Point(126, 137));
+ _verticalSpeedDisplay.fixPriority(200);
+
+ _horizontalSpeedDisplay.postInit();
+ _horizontalSpeedDisplay.setup(1004, 5, 2);
+ _horizontalSpeedDisplay.setPosition(Common::Point(126, 108));
+ _horizontalSpeedDisplay.fixPriority(200);
+
+ _mazeUI.setDisplayBounds(Rect(160, 89, 299, 182));
+ _mazeUI.load(2);
+ _mazeUI.setMazePosition(_mazePosition);
+
+ _action1._field24 = false;
+ _mazeUI.draw();
+ _directionChangesEnabled = true;
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.hide();
@@ -3681,8 +3681,100 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._canWalk = false;
}
+void Scene3500::doMovement(int id) {
+ switch (id) {
+ case -1:
+ _throttle.updateSpeed();
+ if (_speed != 0) {
+ _speed--;
+ _throttle.setSpeed(_speed);
+ }
+ if (_action1._field24)
+ _speed = 0;
+ break;
+ case 1:
+ _throttle.updateSpeed();
+ if (_speed < 16) {
+ ++_speed;
+ _throttle.setSpeed(_speed);
+ }
+ if (_action1._field24)
+ _speed = 0;
+ break;
+ case 88:
+ // Up button has been pressed
+ // The original was doing a double check on action, only one is here.
+ if (!_action || (!_action1._field24)) {
+ _action2.handleVertButton(2);
+ if (_action && ((_action2.getActionIndex() != 0) || (_action2._direction != 2))) {
+ _action2.signal();
+ } else {
+ _tunnelHorzCircle.setAction(&_action2, &_tunnelHorzCircle, NULL);
+ }
+ }
+ break;
+ case 96:
+ // Right button has been pressed
+ if (!_action || !_action1._field24 || (_action1._direction == 1)) {
+ if (_action && (_nextMove == 0) && (_action1._field24)) {
+ _nextMove = id;
+ } else if (_action && (!_action1._field24)) {
+ _action1.handleHorzButton(1);
+ _action1.signal();
+ } else if (!_action) {
+ _action1.handleHorzButton(1);
+ setAction(&_action1, &_shuttle, NULL);
+ }
+
+ } else {
+ if (_nextMove != 0)
+ _nextMove = 0;
+
+ _action1.turnShuttle(false);
+ }
+ break;
+ case 104:
+ // Down button has been pressed
+ if (!_action || (!_action1._field24)) {
+ _action2.handleVertButton(-1);
+ if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._direction != -1))) {
+ _action2.signal();
+ } else {
+ _tunnelHorzCircle.setAction(&_action2, &_tunnelHorzCircle, NULL);
+ }
+ }
+ break;
+ case 112:
+ // Left button has been pressed
+ if (!_action || !_action1._field24 || (_action1._direction == 1)) {
+ if (_action && (_nextMove == 0) && (_action1._field24)) {
+ _nextMove = id;
+ } else if (_action && (!_action1._field24)) {
+ _action1.handleHorzButton(-1);
+ _action1.signal();
+ } else if (!_action) {
+ _action1.handleHorzButton(-1);
+ setAction(&_action1, &_shuttle, NULL);
+ }
+
+ } else {
+ if (_nextMove != 0)
+ _nextMove = 0;
+
+ _action1.turnShuttle(false);
+ }
+ break;
+ default:
+ _speed = id;
+ _throttle.setSpeed(id);
+ if (_action1._field24) {
+ _speed = 0;
+ }
+ break;
+ }
+}
+
void Scene3500::remove() {
- _rotation->remove();
R2_GLOBALS._sound2.fadeOut2(NULL);
SceneExt::remove();
}
@@ -3690,75 +3782,69 @@ void Scene3500::remove() {
void Scene3500::signal() {
R2_GLOBALS._player.enableControl(CURSOR_USE);
R2_GLOBALS._player._canWalk = false;
- _field1286 = 1;
+ _directionChangesEnabled = true;
}
void Scene3500::process(Event &event) {
- if (_field1286 == 0)
+ if (!_directionChangesEnabled)
return;
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);
+ doMovement(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);
+ doMovement(88);
event.handled = true;
break;
- case Common::KEYCODE_3:
- warning("FIXME: keycode = 0x4900");
- if (_field1270 < 16)
+ case Common::KEYCODE_KP9:
+ if (_speed < 16)
R2_GLOBALS._sound2.play(338);
- sub107F71(1);
+ doMovement(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);
+ doMovement(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);
+ doMovement(96);
event.handled = true;
break;
- case Common::KEYCODE_6:
- warning("FIXME: keycode = 0x4F00");
+ case Common::KEYCODE_KP1:
R2_GLOBALS._sound2.play(338);
- sub107F71(0);
+ doMovement(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);
+ doMovement(104);
event.handled = true;
break;
- case Common::KEYCODE_8:
- warning("FIXME: keycode = 0x5100");
- if (_field1270 != 0)
+ case Common::KEYCODE_KP3:
+ if (_speed != 0)
R2_GLOBALS._sound2.play(338);
- sub107F71(-1);
+ doMovement(-1);
event.handled = true;
break;
- case Common::KEYCODE_9:
- warning("FIXME: keycode = 0x5200");
+ case Common::KEYCODE_KP0:
R2_GLOBALS._sound2.play(338);
- sub107F71(8);
+ doMovement(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);
+ doMovement(4);
event.handled = true;
break;
default:
@@ -3767,19 +3853,19 @@ void Scene3500::process(Event &event) {
}
if (!event.handled)
- _actor7.process(event);
+ _throttle.process(event);
if (!event.handled)
- _item4.process(event);
+ _pitchDown.process(event);
if (!event.handled)
- _item5.process(event);
+ _turnLeft.process(event);
if (!event.handled)
- _item6.process(event);
+ _pitchUp.process(event);
if (!event.handled)
- _item7.process(event);
+ _turnRight.process(event);
Scene::process(event);
}
@@ -3787,104 +3873,105 @@ 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;
+
+ if (((_shuttle._frame % 2) == 0) && (!_action1._field24)) {
+ _shuttle.setFrame(_shuttle.changeFrame());
+ _mazeDirection = _shuttle._frame;
}
- int oldField1278;
- if ((_field1278 != 0) && (_action1._field24 == 0)) {
- oldField1278 = _field1278;
- _field1278 = 0;
- sub107F71(oldField1278);
+
+ if ((_nextMove != 0) && (!_action1._field24)) {
+ int move = _nextMove;
+ _nextMove = 0;
+ doMovement(move);
}
if (!_rotation)
return;
- int var_field127A = 0;
- int di = 0;
- int var_4 = 0;
- int var_6 = 0;
- int var_8 = 0;
- int var_a = 0;
- int dx = 0;
- int tmpVar = 0;
+ int newMazeX = 0;
+ int newMazeY = 0;
+ int mazePosX = 0;
+ int mazePosY = 0;
+ int deltaX = 0;
+ int deltaY = 0;
+ int tmpCellId = 0;
+ int cellId = 0;
- if ((_field126E == 0) && (_field1282 == 0)) {
+ if ((_mazeChangeAmount == 0) && !_field1282) {
if (_field1284 == 2)
R2_GLOBALS._sceneManager.changeScene(1000);
} else {
- _field1282 = 0;
+ _field1282 = false;
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);
- 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)) ) {
+ newMazeX = _mazePosition.x;
+ newMazeY = _mazePosition.y;
+ mazePosX = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ mazePosY = _mazeUI.cellFromY(_mazePosition.y + 46) - 46;
+ deltaX = abs(mazePosX - newMazeX);
+ deltaY = abs(mazePosY - newMazeY);
+ tmpCellId = 0;
+
+ 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) && deltaX > 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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;
+ mazePosY = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y - _mazeChangeAmount;
+ tmpCellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (cellId != tmpCellId)) {
+ newMazeY = mazePosY;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 11) && (tmpVar != dx)) {
- di = var_6 + 3;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 11) && (cellId != tmpCellId)) {
+ newMazeY = mazePosY + 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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))
+ mazePosY = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ deltaY = abs(mazePosY - newMazeY);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= mazePosY) && (_mazePosition.y>= mazePosY))
+ || (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= deltaY) && (_mazeChangeAmount > 3) && (_action1._field24 != 0)) ) {
+ newMazeY = mazePosY;
+ if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 11) && (var_6 + 3 >= di) && (_field127C >= var_6 + 3)) {
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 11) && (mazePosY + 3 >= newMazeY) && (_mazePosition.y >= mazePosY + 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (deltaX != 0) && (deltaX <= 3)) {
+ newMazeX = mazePosX;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3892,65 +3979,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)) && (deltaY > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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;
+ mazePosX = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x + _mazeChangeAmount;
+ tmpCellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (cellId != tmpCellId)) {
+ newMazeX = mazePosX;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 6) && (tmpVar != dx)) {
- var_field127A = var_4 - 5;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 6) && (cellId != tmpCellId)) {
+ newMazeX = mazePosX - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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))
+ mazePosX = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ deltaX = abs(newMazeX - mazePosX);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (newMazeX >= mazePosX) && (_mazePosition.x <= mazePosX))
+ || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= deltaX) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) {
+ newMazeX = mazePosX;
+ if ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 6) && (mazePosX - 5 <= newMazeX) && (_mazePosition.x <= mazePosX - 5)) {
+ newMazeX = mazePosX - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (deltaY != 0) && (deltaY <= 3)) {
+ newMazeY = mazePosY;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3958,84 +4045,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)) && (deltaX > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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)) {
+ mazePosY = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y + _mazeChangeAmount;
+ tmpCellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (cellId != tmpCellId)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 16) && (tmpVar == dx)) {
- di = var_6 - 3;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 16) && (cellId != tmpCellId)) {
+ newMazeY = mazePosY - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 31) && (tmpVar == dx)) {
- di = var_6 + 4;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 31) && (cellId != tmpCellId)) {
+ newMazeY = mazePosY + 4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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))
+ mazePosY = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ deltaY = abs(newMazeY - mazePosY);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (newMazeY >= mazePosY) && (_mazePosition.y <= mazePosY))
+ || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= deltaY) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ){
+ newMazeY = mazePosY;
+
+ if ((cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 14) && (cellId != 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 16) && (mazePosY - 3 <= newMazeY) && (_mazePosition.y <= mazePosY - 3)) {
+ newMazeY = mazePosY - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 31) && (mazePosY + 4 <= newMazeY) && (_mazePosition.y <= mazePosY + 4)) {
+ newMazeY = mazePosY + 4;
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- if ((var_field127A == 660) && (_field126E + 306 <= di) && (di <= 307))
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ 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)) && (deltaX != 0) && (deltaX <= 3)) {
+ newMazeX = mazePosX;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4043,65 +4133,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)) && (deltaY > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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;
+ mazePosX = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x - _mazeChangeAmount;
+ tmpCellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (cellId != tmpCellId)) {
+ newMazeX = mazePosX;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
- } else if ((tmpVar == 1) && (tmpVar != dx)) {
- var_field127A = var_4 + 5;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 1) && (cellId != tmpCellId)) {
+ newMazeX = mazePosX + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 0;
- _field1272 = 0;
- if (_action1._field24 == 0)
- _actor8.hide();
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.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))
+ mazePosX = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ deltaX = abs(mazePosX - newMazeX);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (newMazeX <= mazePosX) && (_mazePosition.x >= mazePosX))
+ || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= deltaX) && (_mazeChangeAmount <= 3) && (_action1._field24)) ) {
+ newMazeX = mazePosX;
+ if ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if ((cellId == 1) && (newMazeX >= mazePosX + 5) && (_mazePosition.x >= mazePosX + 5)) {
+ newMazeX = mazePosX + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
- _field1270 = 0;
- _field126E = 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;
+ _speed = 0;
+ _mazeChangeAmount = 0;
+ _field1272 = false;
+ if (!_action1._field24)
+ _tunnelVertCircle.hide();
+ } else if (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (deltaY != 0) && (deltaY <= 3)) {
+ newMazeY = mazePosY;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4114,101 +4204,94 @@ void Scene3500::dispatch() {
}
if (_field1284 < 2) {
- _field127A = var_field127A;
- _field127C = di;
- if (_unkObj1.sub109C5E(_field127A, _field127C) != 0) {
- _field1272 = 0;
- _field126E = 0;
- _field1270 = 0;
+ _mazePosition.x = newMazeX;
+ _mazePosition.y = newMazeY;
+ if (_mazeUI.setMazePosition2(_mazePosition) != 0) {
+ _field1272 = false;
+ _mazeChangeAmount = 0;
+ _speed = 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 (_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 (!_field1272) {
+ if (_mazeChangeAmount != _speed) {
+ if (_mazeChangeAmount >= _speed) {
+ if (_mazeChangeAmount == 1) {
+ if (_action1._field24) {
+ if ( ((_mazeDirection == 1) && (deltaX == 0) && (deltaY != 0) && (deltaY <= 3) && ((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 3) && (deltaY == 0) && (deltaX != 0) && (deltaX <= 3) && ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)))
+ || ((_mazeDirection == 5) && (deltaX == 0) && (deltaY != 0) && (deltaY <= 3) && ((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 7) && (deltaY == 0) && (deltaX != 0) && (deltaX <= 3) && ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))) ){
+ _mazeChangeAmount = 1;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- ++_field126E;
- _field1272 = 1;
+ ++_mazeChangeAmount;
+ _field1272 = true;
}
- _actor2.setFrame2(_field126E);
+ _verticalSpeedDisplay.setFrame2(_mazeChangeAmount + 1);
}
- if (_field1272 == 1) {
- if (_field126E == 0)
+ if (_field1272) {
+ if (_mazeChangeAmount == 0)
_rotation->_idxChange = 0;
- else if (_field126E > 8)
+ else if (_mazeChangeAmount > 8)
_rotation->_idxChange = 2;
else
_rotation->_idxChange = 1;
- }
- if (_field1272 != 0)
- _field1272--;
+ _field1272 = false;
+ }
- if (_field126E != 0) {
+ if (_mazeChangeAmount != 0) {
R2_GLOBALS._player._uiEnabled = false;
- if (_field126E != _field1270)
+ if (_mazeChangeAmount != _speed)
_aSound1.play(276);
} else {
R2_GLOBALS._player._uiEnabled = true;
_aSound1.fadeOut2(NULL);
}
-
- if (_rotation->_currIndex != _field1274)
- _field1274 = _rotation->_currIndex;
}
/*--------------------------------------------------------------------------
- * Scene 3600 -
+ * Scene 3600 - Cutscene - walking at gunpoint
*
*--------------------------------------------------------------------------*/
+
Scene3600::Scene3600() {
- _field2548 = 0;
- _field254A = 0;
- _field254C = 0;
- _field254E = 0;
- _field2550 = false;
+ _tealDead = false;
+ _lightEntered = false;
+ _ghoulTeleported = false;
}
void Scene3600::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field2548);
- s.syncAsSint16LE(_field254A);
- s.syncAsSint16LE(_field254C);
- s.syncAsSint16LE(_field254E);
- s.syncAsSint16LE(_field2550);
+ s.syncAsSint16LE(_tealDead);
+ s.syncAsSint16LE(_lightEntered);
+ s.syncAsSint16LE(_ghoulTeleported);
}
Scene3600::Action3600::Action3600() {
- _field1E = 0;
- _field20 = 0;
+ _field1E = false;
+ _fadePct = 0;
}
void Scene3600::Action3600::synchronize(Serializer &s) {
Action::synchronize(s);
s.syncAsSint16LE(_field1E);
- s.syncAsSint16LE(_field20);
+ s.syncAsSint16LE(_fadePct);
}
void Scene3600::Action3600::signal() {
@@ -4220,17 +4303,17 @@ void Scene3600::Action3600::signal() {
setDelay(60);
break;
case 1:
- if (_field1E == 0) {
- _field1E = 1;
- scene->_actor2.setAction(NULL);
+ if (!_field1E) {
+ _field1E = true;
+ scene->_steppingDisk.setAction(NULL);
R2_GLOBALS._sound2.play(330, NULL, 0);
R2_GLOBALS._sound2.fade(127, 5, 10, false, NULL);
}
+
setDelay(1);
- warning("TODO: Palette fader using parameter 2 = 256");
- R2_GLOBALS._scenePalette.fade((const byte *)&scene->_palette1._palette, true, _field20);
- if (_field20 > 0)
- _field20 -= 2;
+ R2_GLOBALS._scenePalette.fade((const byte *)&scene->_palette1._palette, true, _fadePct);
+ if (_fadePct > 0)
+ _fadePct -= 2;
break;
case 2:
R2_GLOBALS._sound2.stop();
@@ -4255,14 +4338,14 @@ void Scene3600::Action2::signal() {
R2_GLOBALS._events.proc1();
R2_GLOBALS._player.enableControl();
_actionIndex = 3619;
- scene->_actor13._state = 0;
+ scene->_protector._state = 0;
// No break on purpose
case 3619: {
++_actionIndex;
- scene->_actor13.setup(3127, 2, 1);
- scene->_actor13.animate(ANIM_MODE_1, NULL);
+ scene->_protector.setup(3127, 2, 1);
+ scene->_protector.animate(ANIM_MODE_1, NULL);
NpcMover *mover = new NpcMover();
- scene->_actor13.addMover(mover, &scene->_actor13._field8A, scene);
+ scene->_protector.addMover(mover, &scene->_protector._actorDestPos, scene);
}
break;
default:
@@ -4272,25 +4355,25 @@ void Scene3600::Action2::signal() {
}
}
-bool Scene3600::Item5::startAction(CursorType action, Event &event) {
+bool Scene3600::LightShaft::startAction(CursorType action, Event &event) {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- if ((action != CURSOR_USE) || (scene->_action1._field1E == 0))
+ if ((action != CURSOR_USE) || !scene->_action1._field1E)
return SceneItem::startAction(action, event);
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(7);
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 3624;
- scene->_actor10.setStrip2(-1);
- scene->_actor11.setStrip2(-1);
- scene->_actor12.setStrip2(-1);
- scene->_actor4.setStrip2(-1);
+ scene->_quinn.setStrip2(-1);
+ scene->_seeker.setStrip2(-1);
+ scene->_miranda.setStrip2(-1);
+ scene->_webbster.setStrip2(-1);
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
R2_GLOBALS._player.setAction(&scene->_sequenceManager3, scene, 3611, &R2_GLOBALS._player, NULL);
- else if (R2_GLOBALS._player._characterIndex == 3)
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
R2_GLOBALS._player.setAction(&scene->_sequenceManager4, scene, 3612, &R2_GLOBALS._player, NULL);
else
R2_GLOBALS._player.setAction(&scene->_sequenceManager2, scene, 3610, &R2_GLOBALS._player, NULL);
@@ -4298,25 +4381,25 @@ bool Scene3600::Item5::startAction(CursorType action, Event &event) {
return true;
}
-bool Scene3600::Actor13::startAction(CursorType action, Event &event) {
+bool Scene3600::Protector::startAction(CursorType action, Event &event) {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
switch(action) {
case CURSOR_TALK:
- if (!_action)
+ if (_action)
return SceneActor::startAction(action, event);
scene->_protectorSpeaker._displayMode = 1;
if (!R2_GLOBALS._player._mover)
R2_GLOBALS._player.addMover(NULL);
- if (!scene->_actor10._mover)
- scene->_actor10.addMover(NULL);
- if (!scene->_actor11._mover)
- scene->_actor11.addMover(NULL);
- if (!scene->_actor12._mover)
- scene->_actor12.addMover(NULL);
- if (!scene->_actor4._mover)
- scene->_actor4.addMover(NULL);
+ if (!scene->_quinn._mover)
+ scene->_quinn.addMover(NULL);
+ if (!scene->_seeker._mover)
+ scene->_seeker.addMover(NULL);
+ if (!scene->_miranda._mover)
+ scene->_miranda.addMover(NULL);
+ if (!scene->_webbster._mover)
+ scene->_webbster.addMover(NULL);
setup(3127, 2, 1);
scene->_sceneMode = 3327;
@@ -4330,6 +4413,7 @@ bool Scene3600::Actor13::startAction(CursorType action, Event &event) {
R2_GLOBALS._sound3.play(43);
else
R2_GLOBALS._sound3.play(99);
+
if (_state != 0) {
_state = 1;
setup(3128, 1, 1);
@@ -4353,16 +4437,13 @@ bool Scene3600::Actor13::startAction(CursorType action, Event &event) {
void Scene3600::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._sceneManager._previousScene == 3600) {
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
- R2_GLOBALS._v558B6.set(60, 0, 260, 200);
} else {
- R2_GLOBALS._scrollFollower = &_actor2;
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
- R2_GLOBALS._v558B6.set(25, 0, 260, 200);
+ R2_GLOBALS._scrollFollower = &_steppingDisk;
+ _sceneBounds = Rect(160, 0, 480, 200);
}
loadScene(3600);
SceneExt::postInit();
- _field254C = 0;
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
@@ -4373,186 +4454,183 @@ void Scene3600::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_protectorSpeaker);
setZoomPercents(142, 80, 167, 105);
- R2_GLOBALS._player._characterScene[1] = 3600;
- R2_GLOBALS._player._characterScene[2] = 3600;
- R2_GLOBALS._player._characterScene[3] = 3600;
+ R2_GLOBALS._player._characterScene[R2_QUINN] = 3600;
+ R2_GLOBALS._player._characterScene[R2_SEEKER] = 3600;
+ R2_GLOBALS._player._characterScene[R2_MIRANDA] = 3600;
- _item2.setDetails(33, 3600, 6, -1, -1);
- _item3.setDetails(Rect(3, 3, 22, 45), 3600, 9, -1, -1, 1, NULL);
- _item4.setDetails(Rect(449, 3, 475, 45), 3600, 9, -1, -1, 1, NULL);
+ _console.setDetails(33, 3600, 6, -1, -1);
+ _tapestry1.setDetails(Rect(3, 3, 22, 45), 3600, 9, -1, -1, 1, NULL);
+ _tapestry2.setDetails(Rect(449, 3, 475, 45), 3600, 9, -1, -1, 1, NULL);
- _actor10.postInit();
- _actor10._moveDiff = Common::Point(3, 2);
- _actor10.changeZoom(-1);
- _actor10._effect = 1;
+ _quinn.postInit();
+ _quinn._moveDiff = Common::Point(3, 2);
+ _quinn.changeZoom(-1);
+ _quinn._effect = EFFECT_SHADED;
if (R2_GLOBALS._player._characterIndex != 1)
- _actor10.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
+ _quinn.setDetails(9001, 0, -1, -1, 1, (SceneItem *) NULL);
- _actor11.postInit();
- _actor11._numFrames = 7;
- _actor11._moveDiff = Common::Point(5, 3);
- _actor11.changeZoom(-1);
- _actor11._effect = 1;
+ _seeker.postInit();
+ _seeker._numFrames = 7;
+ _seeker._moveDiff = Common::Point(5, 3);
+ _seeker.changeZoom(-1);
+ _seeker._effect = EFFECT_SHADED;
if (R2_GLOBALS._player._characterIndex != 2)
- _actor11.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
+ _seeker.setDetails(9002, 1, -1, -1, 1, (SceneItem *) NULL);
- _actor12.postInit();
- _actor12._moveDiff = Common::Point(3, 2);
- _actor12.changeZoom(-1);
- _actor12._effect = 1;
+ _miranda.postInit();
+ _miranda._moveDiff = Common::Point(3, 2);
+ _miranda.changeZoom(-1);
+ _miranda._effect = EFFECT_SHADED;
if (R2_GLOBALS._player._characterIndex != 3)
- _actor12.setDetails(9003, 1, -1, -1, 1, (SceneItem *) NULL);
+ _miranda.setDetails(9003, 1, -1, -1, 1, (SceneItem *) NULL);
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.changeZoom(-1);
R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
R2_GLOBALS._player.disableControl();
- _actor4.postInit();
- _actor4._numFrames = 7;
- _actor4._moveDiff = Common::Point(5, 3);
- _actor4.changeZoom(-1);
- _actor4._effect = 1;
- _actor4.setDetails(3600, 27, -1, -1, 1, (SceneItem *) NULL);
+ _webbster.postInit();
+ _webbster._numFrames = 7;
+ _webbster._moveDiff = Common::Point(5, 3);
+ _webbster.changeZoom(-1);
+ _webbster._effect = EFFECT_SHADED;
+ _webbster.setDetails(3600, 27, -1, -1, 1, (SceneItem *) NULL);
- _actor5.postInit();
- _actor5._numFrames = 7;
- _actor5._moveDiff = Common::Point(3, 2);
- _actor5.changeZoom(-1);
- _actor5._effect = 1;
- _actor5.setDetails(3600, 12, -1, -1, 1, (SceneItem *) NULL);
+ _teal.postInit();
+ _teal._numFrames = 7;
+ _teal._moveDiff = Common::Point(3, 2);
+ _teal.changeZoom(-1);
+ _teal._effect = EFFECT_SHADED;
+ _teal.setDetails(3600, 12, -1, -1, 1, (SceneItem *) NULL);
_palette1.loadPalette(0);
_palette1.loadPalette(3601);
if (R2_GLOBALS._sceneManager._previousScene == 3600) {
- _item5._sceneRegionId = 200;
- _item5.setDetails(3600, 30, -1, -1, 5, &_actor4);
- _field254A = 1;
- _field2548 = 1;
+ _lightShaft._sceneRegionId = 200;
+ _lightShaft.setDetails(3600, 30, -1, -1, 5, &_webbster);
+ _tealDead = true;
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(14);
- R2_GLOBALS._walkRegions.enableRegion(15);
- R2_GLOBALS._walkRegions.enableRegion(16);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(14);
+ R2_GLOBALS._walkRegions.disableRegion(15);
+ R2_GLOBALS._walkRegions.disableRegion(16);
- _actor10.setup(10, 5, 11);
- _actor10.animate(ANIM_MODE_1, NULL);
+ _quinn.setup(10, 5, 11);
+ _quinn.animate(ANIM_MODE_1, NULL);
- _actor11.setup(20, 5, 11);
- _actor11.animate(ANIM_MODE_1, NULL);
+ _seeker.setup(20, 5, 11);
+ _seeker.animate(ANIM_MODE_1, NULL);
- _actor12.setup(30, 5, 11);
- _actor12.animate(ANIM_MODE_1, NULL);
+ _miranda.setup(30, 5, 11);
+ _miranda.animate(ANIM_MODE_1, NULL);
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor10.setPosition(Common::Point(76, 148));
- _actor11.setPosition(Common::Point(134, 148));
- _actor12.setPosition(Common::Point(100, 148));
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _quinn.setPosition(Common::Point(76, 148));
+ _seeker.setPosition(Common::Point(134, 148));
+ _miranda.setPosition(Common::Point(100, 148));
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- R2_GLOBALS._player.setup(20, _actor11._strip, 1);
- R2_GLOBALS._player.setPosition(_actor11._position);
- _actor11.hide();
- } else if (R2_GLOBALS._player._characterIndex == 3) {
- _actor10.setPosition(Common::Point(110, 148));
- _actor11.setPosition(Common::Point(76, 148));
- _actor12.setPosition(Common::Point(134, 148));
+ R2_GLOBALS._player.setup(20, _seeker._strip, 1);
+ R2_GLOBALS._player.setPosition(_seeker._position);
+ _seeker.hide();
+ } else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA) {
+ _quinn.setPosition(Common::Point(110, 148));
+ _seeker.setPosition(Common::Point(76, 148));
+ _miranda.setPosition(Common::Point(134, 148));
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- R2_GLOBALS._player.setup(30, _actor12._strip, 1);
- R2_GLOBALS._player.setPosition(_actor12._position);
- _actor12.hide();
+ R2_GLOBALS._player.setup(30, _miranda._strip, 1);
+ R2_GLOBALS._player.setPosition(_miranda._position);
+ _miranda.hide();
} else {
- _actor10.setPosition(Common::Point(134, 148));
- _actor11.setPosition(Common::Point(76, 148));
- _actor12.setPosition(Common::Point(110, 148));
+ _quinn.setPosition(Common::Point(134, 148));
+ _seeker.setPosition(Common::Point(76, 148));
+ _miranda.setPosition(Common::Point(110, 148));
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- R2_GLOBALS._player.setup(10, _actor10._strip, 1);
- R2_GLOBALS._player.setPosition(_actor10._position);
- _actor10.hide();
+ R2_GLOBALS._player.setup(10, _quinn._strip, 1);
+ R2_GLOBALS._player.setPosition(_quinn._position);
+ _quinn.hide();
}
- _actor4.setPosition(Common::Point(47, 149));
- _actor4.setup(40, 1, 11);
- _actor4.animate(ANIM_MODE_1, NULL);
+ _webbster.setPosition(Common::Point(47, 149));
+ _webbster.setup(40, 1, 11);
+ _webbster.animate(ANIM_MODE_1, NULL);
- _actor5.setPosition(Common::Point(367, 148));
- _actor5.setup(3601, 7, 5);
+ _teal.setPosition(Common::Point(367, 148));
+ _teal.setup(3601, 7, 5);
if (!R2_GLOBALS.getFlag(71)) {
- _actor13.postInit();
- _actor13._state = 0;
- _actor13._field8A = Common::Point(226, 152);
- _actor13._moveDiff = Common::Point(3, 2);
- _actor13.setPosition(Common::Point(284, 152));
- _actor13.setup(3127, 2, 1);
- _actor13.changeZoom(-1);
- _actor13.setDetails(3600, 15, -1, 17, 1, (SceneItem *) NULL);
+ _protector.postInit();
+ _protector._state = 0;
+ _protector._actorDestPos = Common::Point(226, 152);
+ _protector._moveDiff = Common::Point(3, 2);
+ _protector.setPosition(Common::Point(284, 152));
+ _protector.setup(3127, 2, 1);
+ _protector.changeZoom(-1);
+ _protector.setDetails(3600, 15, -1, 17, 1, (SceneItem *) NULL);
}
R2_GLOBALS._sound2.play(330);
- _actor3.postInit();
- _actor3.setPosition(Common::Point(84, 156));
- _actor3.fixPriority(158);
- _actor3.setup(3601, 5, 1);
- _actor3.animate(ANIM_MODE_2, NULL);
-
- _action1._field1E = 1;
- _action1._field20 = 0;
+ _consoleLights.postInit();
+ _consoleLights.setPosition(Common::Point(84, 156));
+ _consoleLights.fixPriority(158);
+ _consoleLights.setup(3601, 5, 1);
+ _consoleLights.animate(ANIM_MODE_2, NULL);
+
+ _action1._field1E = true;
+ _action1._fadePct = 0;
_action1.setActionIndex(1);
- _actor3.setAction(&_action1);
+ _consoleLights.setAction(&_action1);
_sceneMode = 3623;
g_globals->_events.setCursor(CURSOR_ARROW);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
} else {
- _field254A = 0;
- _field2548 = 0;
+ _tealDead = false;
- R2_GLOBALS._walkRegions.enableRegion(17);
- R2_GLOBALS._walkRegions.enableRegion(18);
+ R2_GLOBALS._walkRegions.disableRegion(17);
+ R2_GLOBALS._walkRegions.disableRegion(18);
- _actor10.setPosition(Common::Point(393, 148));
- _actor11.setPosition(Common::Point(364, 153));
- _actor12.setPosition(Common::Point(413, 164));
+ _quinn.setPosition(Common::Point(393, 148));
+ _seeker.setPosition(Common::Point(364, 153));
+ _miranda.setPosition(Common::Point(413, 164));
R2_GLOBALS._player.hide();
- _actor4.setPosition(Common::Point(373, 164));
+ _webbster.setPosition(Common::Point(373, 164));
- _actor5.setup(3403, 8, 11);
- _actor5.setPosition(Common::Point(403, 155));
+ _teal.setup(3403, 8, 11);
+ _teal.setPosition(Common::Point(403, 155));
- _actor12.setup(3403, 7, 1);
+ _protector.setup(3403, 7, 1);
+ _protector.setPosition(Common::Point(405, 155));
- _actor13.setPosition(Common::Point(405, 155));
+ _steppingDisk.postInit();
+ _steppingDisk.setup(3600, 2, 1);
+ _steppingDisk.setPosition(Common::Point(403, 161));
+ _steppingDisk.fixPriority(149);
+ _steppingDisk.changeZoom(-1);
- _actor2.postInit();
- _actor2.setup(3600, 2, 1);
- _actor2.setPosition(Common::Point(403, 161));
- _actor2.fixPriority(149);
- _actor2.changeZoom(-1);
-
- _action1._field1E = 0;
- _action1._field20 = 90;
+ _action1._field1E = false;
+ _action1._fadePct = 90;
_sceneMode = 3600;
- setAction(&_sequenceManager1, this, 3600, &_actor11, &_actor10, &_actor12, &_actor4, &_actor5, &_actor2, NULL);
- _field254E = 0;
+ setAction(&_sequenceManager1, this, 3600, &_seeker, &_quinn, &_miranda,
+ &_webbster, &_teal, &_steppingDisk, NULL);
}
- _field254E = 0;
- _field2550 = R2_GLOBALS.getFlag(71);
+ _lightEntered = false;
+ _ghoulTeleported = R2_GLOBALS.getFlag(71);
R2_GLOBALS._sound1.play(326);
- _item1.setDetails(Rect(0, 0, 480, 200), 3600, 0, -1, -1, 1, NULL);
+ _background.setDetails(Rect(0, 0, 480, 200), 3600, 0, -1, -1, 1, NULL);
}
void Scene3600::remove() {
- _actor3.animate(ANIM_MODE_NONE, NULL);
- _actor3.setAction(NULL);
+ _consoleLights.animate(ANIM_MODE_NONE, NULL);
+ _consoleLights.setAction(NULL);
R2_GLOBALS._sound2.fadeOut2(NULL);
R2_GLOBALS._sound1.fadeOut2(NULL);
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
@@ -4562,136 +4640,143 @@ void Scene3600::remove() {
void Scene3600::signal() {
switch (_sceneMode) {
case 3320:
- warning("STUB: sub_1D227()");
- R2_GLOBALS._walkRegions.enableRegion(14);
- R2_GLOBALS._scrollFollower = &_actor11;
+ // Move to the console
+ R2_GLOBALS._walkRegions.disableRegion(14);
+ R2_GLOBALS._scrollFollower = &_seeker;
_tealSpeaker._object1.hide();
- _actor5.show();
- _actor5.setStrip(2);
- if (R2_GLOBALS._player._characterIndex == 2)
+ _teal.show();
+ _teal.setStrip(2);
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_sceneMode = 3602;
- else if (R2_GLOBALS._player._characterIndex == 3)
+ else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_sceneMode = 3603;
else
_sceneMode = 3601;
- setAction(&_sequenceManager1, this, _sceneMode, &_actor11, &_actor10, &_actor12, &_actor4, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, _sceneMode, &_seeker, &_quinn,
+ &_miranda, &_webbster, &_teal, NULL);
break;
case 3321:
- warning("STUB: sub_1D227()");
+ // Teal activates console
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
- _tealSpeaker.proc16();
- _actor5.show();
- _actor5.setStrip(1);
- _actor3.postInit();
+ _tealSpeaker.stopSpeaking();
+ _teal.show();
+ _teal.setStrip(1);
+ _consoleLights.postInit();
_sceneMode = 3604;
- setAction(&_sequenceManager1, this, _sceneMode, &_actor5, &_actor3, &_actor10, &_actor11, &_actor12, &_actor4, NULL);
+ setAction(&_sequenceManager1, this, _sceneMode, &_teal, &_consoleLights,
+ &_quinn, &_seeker, &_miranda, &_webbster, NULL);
break;
case 3322:
- warning("STUB: sub_1D227()");
- _quinnSpeaker.proc16();
+ // Teal walks toward the teleport pod, the goule protector appears
+ _quinnSpeaker.stopSpeaking();
_quinnSpeaker._displayMode = 1;
- _tealSpeaker.proc16();
+ _tealSpeaker.stopSpeaking();
_tealSpeaker._displayMode = 7;
- R2_GLOBALS._scrollFollower = &_actor5;
+ R2_GLOBALS._scrollFollower = &_teal;
_sceneMode = 3605;
- setAction(&_sequenceManager1, this, _sceneMode, &_actor5, &_actor13, &_actor2, NULL);
+ setAction(&_sequenceManager1, this, _sceneMode, &_teal, &_protector, &_steppingDisk, NULL);
break;
case 3323:
- if (_field254A == 0)
- _field254A = 1;
+ // Goule protector eats Teal guts then moves
+
+ if (!_tealDead)
+ _tealDead = true;
else {
- warning("STUB: sub_1D227()");
- _protectorSpeaker.proc16();
- _actor13.show();
- _actor13.setup(3258, 6, 1);
+ _protectorSpeaker.stopSpeaking();
+ _protector.show();
+ _protector.setup(3258, 6, 1);
+
_sceneMode = 3607;
- _actor13.setAction(&_sequenceManager1, this, _sceneMode, &_actor13, NULL);
- R2_GLOBALS._v558C2 = 1;
- _protectorSpeaker.proc16();
+ _protector.setAction(&_sequenceManager1, this, _sceneMode, &_protector, NULL);
+
+ _protectorSpeaker.stopSpeaking();
_protectorSpeaker._displayMode = 1;
_quinnSpeaker._displayMode = 1;
- _actor13.show();
+ _protector.show();
+
R2_GLOBALS._scrollFollower = &R2_GLOBALS._player;
- R2_GLOBALS._walkRegions.disableRegion(17);
- R2_GLOBALS._walkRegions.disableRegion(18);
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._walkRegions.enableRegion(14);
- R2_GLOBALS._walkRegions.enableRegion(15);
- R2_GLOBALS._walkRegions.enableRegion(16);
- _actor13.setAction(&_action1);
+ R2_GLOBALS._walkRegions.enableRegion(17);
+ R2_GLOBALS._walkRegions.enableRegion(18);
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(14);
+ R2_GLOBALS._walkRegions.disableRegion(15);
+ R2_GLOBALS._walkRegions.disableRegion(16);
+
+ _consoleLights.setAction(&_action1);
}
break;
case 3324:
// No break on purpose
case 3607:
g_globals->_events.setCursor(CURSOR_ARROW);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
- _actor13.fixPriority(-1);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ _protector.fixPriority(-1);
_sceneMode = 3623;
- _field2548 = 1;
break;
case 3327:
g_globals->_events.setCursor(CURSOR_ARROW);
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
_sceneMode = 3623;
break;
case 3450:
+ // Speech of Teal and Quinn
R2_GLOBALS._sound1.stop();
- _actor1.hide();
- _actor6.hide();
- g_globals->gfxManager()._bounds.moveTo(Common::Point(40, 0));
+ _protector3400.hide();
+ _door3400.hide();
+
+ _sceneBounds = Rect(40, 0, SCREEN_WIDTH + 40, SCREEN_HEIGHT);
setZoomPercents(142, 80, 167, 105);
loadScene(3600);
R2_GLOBALS._uiElements.show();
- _item5._sceneRegionId = 200;
- _item5.setDetails(3600, 30, -1, -1, 5, &_actor4);
-
- _actor3.show();
- _actor10.show();
- _actor11.show();
- _actor12.show();
- _actor4.show();
- _actor5.show();
-
- _actor5.setPosition(Common::Point(298, 151));
-
- _actor13.postInit();
- _actor13._state = 0;
- _actor13._field8A = Common::Point(226, 152);
- _actor13._moveDiff = Common::Point(5, 3);
- _actor13.setup(3403, 7, 1);
- _actor13.setPosition(Common::Point(405, 155));
- _actor13.changeZoom(-1);
- _actor13.addMover(NULL);
- _actor13.animate(ANIM_MODE_NONE);
- _actor13.hide();
- _actor13.setDetails(3600, 15, -1, 17, 5, &_item5);
-
- _actor2.setup(3600, 2, 1);
- _actor2.setPosition(Common::Point(403, 161));
- _actor2.fixPriority(149);
- _actor2.changeZoom(-1);
- _actor2.show();
+ _lightShaft._sceneRegionId = 200;
+ _lightShaft.setDetails(3600, 30, -1, -1, 5, &_webbster);
+
+ _consoleLights.show();
+ _quinn.show();
+ _seeker.show();
+ _miranda.show();
+ _webbster.show();
+ _teal.show();
+
+ _teal.setPosition(Common::Point(298, 151));
+
+ _protector.postInit();
+ _protector._state = 0;
+ _protector._actorDestPos = Common::Point(226, 152);
+ _protector._moveDiff = Common::Point(5, 3);
+ _protector.setup(3403, 7, 1);
+ _protector.setPosition(Common::Point(405, 155));
+ _protector.changeZoom(-1);
+ _protector.addMover(NULL);
+ _protector.animate(ANIM_MODE_NONE);
+ _protector.hide();
+ _protector.setDetails(3600, 15, -1, 17, 5, &_lightShaft);
+
+ _steppingDisk.setup(3600, 2, 1);
+ _steppingDisk.setPosition(Common::Point(403, 161));
+ _steppingDisk.fixPriority(149);
+ _steppingDisk.changeZoom(-1);
+ _steppingDisk.show();
_quinnSpeaker._displayMode = 2;
_tealSpeaker._displayMode = 2;
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- R2_GLOBALS._player.setup(20, _actor11._strip, 1);
- R2_GLOBALS._player.setPosition(_actor11._position);
- _actor11.hide();
- } else if (R2_GLOBALS._player._characterIndex == 3) {
+ R2_GLOBALS._player.setup(20, _seeker._strip, 1);
+ R2_GLOBALS._player.setPosition(_seeker._position);
+ _seeker.hide();
+ } else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA) {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- R2_GLOBALS._player.setup(30, _actor12._strip, 1);
- R2_GLOBALS._player.setPosition(_actor12._position);
- _actor12.hide();
+ R2_GLOBALS._player.setup(30, _miranda._strip, 1);
+ R2_GLOBALS._player.setPosition(_miranda._position);
+ _miranda.hide();
} else {
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- R2_GLOBALS._player.setup(10, _actor10._strip, 1);
- R2_GLOBALS._player.setPosition(_actor10._position);
- _actor10.hide();
+ R2_GLOBALS._player.setup(10, _quinn._strip, 1);
+ R2_GLOBALS._player.setPosition(_quinn._position);
+ _quinn.hide();
}
R2_GLOBALS._player.show();
R2_GLOBALS._sound1.play(326);
@@ -4700,6 +4785,7 @@ void Scene3600::signal() {
R2_GLOBALS._sound2.play(329);
break;
case 3600:
+ // First speech by Teal
_sceneMode = 3320;
_stripManager.start(3320, this);
break;
@@ -4708,53 +4794,56 @@ void Scene3600::signal() {
case 3602:
// No break on purpose
case 3603:
- R2_GLOBALS._walkRegions.enableRegion(2);
- R2_GLOBALS._walkRegions.enableRegion(7);
- R2_GLOBALS._v558B6.set(60, 0, 260, 200);
+ // Teal speech near the console
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(7);
_tealSpeaker._displayMode = 1;
_sceneMode = 3321;
_stripManager.start(3321, this);
break;
case 3604:
+ // Goule Protector forces the door
R2_GLOBALS._sound2.fadeOut2(NULL);
R2_GLOBALS._sound1.stop();
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(7);
- _actor2.hide();
- _actor3.hide();
+ _steppingDisk.hide();
+ _consoleLights.hide();
R2_GLOBALS._player.hide();
- _actor10.hide();
- _actor11.hide();
- _actor12.hide();
- _actor4.hide();
- _actor5.hide();
+ _quinn.hide();
+ _seeker.hide();
+ _miranda.hide();
+ _webbster.hide();
+ _teal.hide();
- g_globals->gfxManager()._bounds.moveTo(Common::Point(60, 0));
+ _sceneBounds = Rect(60, 0, SCREEN_WIDTH + 60, SCREEN_HEIGHT);
setZoomPercents(51, 46, 180, 200);
loadScene(3400);
R2_GLOBALS._uiElements.show();
- _actor1.postInit();
+ _protector3400.postInit();
- _actor2.setup(3403, 1, 1);
- _actor2.setPosition(Common::Point(190, 103));
- _actor2.fixPriority(89);
- _actor2.show();
+ _steppingDisk.setup(3403, 1, 1);
+ _steppingDisk.setPosition(Common::Point(190, 103));
+ _steppingDisk.fixPriority(89);
+ _steppingDisk.show();
- _actor6.postInit();
- _actor6.setup(3400, 1, 6);
- _actor6.setPosition(Common::Point(236, 51));
- _actor6.fixPriority(51);
- R2_GLOBALS._scrollFollower = &_actor6;
+ _door3400.postInit();
+ _door3400.setup(3400, 1, 6);
+ _door3400.setPosition(Common::Point(236, 51));
+ _door3400.fixPriority(51);
+ R2_GLOBALS._scrollFollower = &_door3400;
R2_GLOBALS._sound1.play(323);
_sceneMode = 3450;
- setAction(&_sequenceManager1, this, 3450, &_actor1, &_actor6, NULL);
+ setAction(&_sequenceManager1, this, 3450, &_protector3400, &_door3400, NULL);
break;
case 3605:
- _actor13.setup(3258, 4, 1);
- _actor13.setAction(&_sequenceManager1, this, 3606, &_actor5, &_actor13, &_actor2, NULL);
+ // Goule protector jumps on Teal
+ _protector.setup(3258, 4, 1);
+ _protector.setAction(&_sequenceManager1, this, 3606, &_teal, &_protector,
+ &_steppingDisk, NULL);
_sceneMode = 3323;
_stripManager.start(3323, this);
@@ -4762,21 +4851,22 @@ void Scene3600::signal() {
case 3620:
// No break on purpose
case 3623:
- if ((_actor13._position.x == 226) && (_actor13._position.y == 152) && (_action1._field1E != 0) && (_actor13._visage == 3127) && (!R2_GLOBALS.getFlag(71))) {
+ if ((_protector._position.x == 226) && (_protector._position.y == 152)
+ && _action1._field1E && (_protector._visage == 3127) && (!R2_GLOBALS.getFlag(71))) {
R2_GLOBALS._sound2.stop();
R2_GLOBALS._sound2.play(331);
R2_GLOBALS.setFlag(71);
_sceneMode = 3626;
- setAction(&_sequenceManager1, this, 3626, &_actor13, NULL);
+ setAction(&_sequenceManager1, this, 3626, &_protector, NULL);
}
break;
case 3624:
R2_GLOBALS._player.disableControl();
- if ((_field254E != 0) && (_actor10._position.x == 229) && (_actor10._position.y == 154) && (_actor11._position.x == 181) && (_actor11._position.y == 154) && (_actor12._position.x == 207) && (_actor12._position.y == 154) && (_actor4._position.x == 155) && (_actor4._position.y == 154)) {
+ if (_lightEntered && (_quinn._position.x == 229) && (_quinn._position.y == 154) && (_seeker._position.x == 181) && (_seeker._position.y == 154) && (_miranda._position.x == 207) && (_miranda._position.y == 154) && (_webbster._position.x == 155) && (_webbster._position.y == 154)) {
R2_GLOBALS._sound2.stop();
R2_GLOBALS._sound2.play(331);
_sceneMode = 3625;
- setAction(&_sequenceManager1, this, 3625, &_actor10, &_actor11, &_actor12, &_actor4, NULL);
+ setAction(&_sequenceManager1, this, 3625, &_quinn, &_seeker, &_miranda, &_webbster, NULL);
}
break;
case 3625:
@@ -4784,7 +4874,7 @@ void Scene3600::signal() {
R2_GLOBALS._sceneManager.changeScene(3700);
break;
case 3626:
- _actor13.setPosition(Common::Point(0, 0));
+ _protector.setPosition(Common::Point(0, 0));
_action1.setActionIndex(2);
if (R2_GLOBALS._events.getCursor() > R2_LAST_INVENT) {
R2_GLOBALS._events.setCursor(CURSOR_USE);
@@ -4801,72 +4891,74 @@ void Scene3600::signal() {
}
void Scene3600::process(Event &event) {
- if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_ARROW) && (event.mousePos.x > 237) && (!R2_GLOBALS.getFlag(71))) {
- SceneItem::display(3600, 17, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7 -999);
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_ARROW)
+ && (event.mousePos.x > 237) && (!R2_GLOBALS.getFlag(71))) {
+ SceneItem::display(3600, 17, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
event.handled = true;
}
Scene::process(event);
}
void Scene3600::dispatch() {
- if ((R2_GLOBALS._player.getRegionIndex() == 200) && (_action1._field1E != 0) && (_field254E == 0)){
+ if ((R2_GLOBALS._player.getRegionIndex() == 200) && _action1._field1E && !_lightEntered) {
R2_GLOBALS._sound2.fadeOut2(NULL);
- if (_actor13._mover)
- _actor13.addMover(NULL);
+ if (_protector._mover)
+ _protector.addMover(NULL);
+
if (R2_GLOBALS._player._action)
R2_GLOBALS._player.setAction(NULL);
if (R2_GLOBALS._player._mover)
R2_GLOBALS._player.addMover(NULL);
- _field254C = 0;
- _field254E = 1;
+ _lightEntered = true;
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.enableRegion(2);
+ R2_GLOBALS._walkRegions.enableRegion(7);
R2_GLOBALS._player.disableControl();
_sceneMode = 3624;
- _actor10.setStrip(-1);
- _actor11.setStrip(-1);
- _actor12.setStrip(-1);
- _actor4.setStrip(-1);
+ _quinn.setStrip(-1);
+ _seeker.setStrip(-1);
+ _miranda.setStrip(-1);
+ _webbster.setStrip(-1);
R2_GLOBALS._player.hide();
- if (R2_GLOBALS._player._characterIndex == 2) {
- _actor11.setPosition(R2_GLOBALS._player._position);
- _actor11.show();
- } else if (R2_GLOBALS._player._characterIndex == 3) {
- _actor12.setPosition(R2_GLOBALS._player._position);
- _actor12.show();
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _seeker.setPosition(R2_GLOBALS._player._position);
+ _seeker.show();
+ } else if (R2_GLOBALS._player._characterIndex == R2_MIRANDA) {
+ _miranda.setPosition(R2_GLOBALS._player._position);
+ _miranda.show();
} else {
- _actor10.setPosition(R2_GLOBALS._player._position);
- _actor10.show();
+ _quinn.setPosition(R2_GLOBALS._player._position);
+ _quinn.show();
}
- _actor10.setAction(&_sequenceManager2, this, 3610, &_actor10, NULL);
- _actor11.setAction(&_sequenceManager3, this, 3611, &_actor11, NULL);
- _actor12.setAction(&_sequenceManager4, this, 3612, &_actor12, NULL);
- _actor4.setAction(&_sequenceManager1, this, 3613, &_actor4, NULL);
+ _quinn.setAction(&_sequenceManager2, this, 3610, &_quinn, NULL);
+ _seeker.setAction(&_sequenceManager3, this, 3611, &_seeker, NULL);
+ _miranda.setAction(&_sequenceManager4, this, 3612, &_miranda, NULL);
+ _webbster.setAction(&_sequenceManager1, this, 3613, &_webbster, NULL);
}
- if ((_actor13.getRegionIndex() == 200) && (_action1._field1E != 0) && (_field254E == 0)){
+ if ((_protector.getRegionIndex() == 200) && _action1._field1E && !_ghoulTeleported) {
R2_GLOBALS._sound2.fadeOut2(NULL);
_sceneMode = 3620;
- _field2550 = 1;
+ _ghoulTeleported = true;
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._mover)
R2_GLOBALS._player.addMover(NULL);
- if (_actor10._mover)
- _actor10.addMover(NULL);
- if (_actor11._mover)
- _actor11.addMover(NULL);
- if (_actor12._mover)
- _actor12.addMover(NULL);
- if (_actor4._mover)
- _actor4.addMover(NULL);
+ if (_quinn._mover)
+ _quinn.addMover(NULL);
+ if (_seeker._mover)
+ _seeker.addMover(NULL);
+ if (_miranda._mover)
+ _miranda.addMover(NULL);
+ if (_webbster._mover)
+ _webbster.addMover(NULL);
}
+
Scene::dispatch();
}
@@ -4874,10 +4966,13 @@ void Scene3600::dispatch() {
* Scene 3700 - Cutscene - Teleport outside
*
*--------------------------------------------------------------------------*/
+
void Scene3700::postInit(SceneObjectList *OwnerList) {
loadScene(3700);
R2_GLOBALS._uiElements._active = false;
+ R2_GLOBALS._uiElements._visible = false;
SceneExt::postInit();
+ R2_GLOBALS._interfaceY = SCREEN_HEIGHT;
_stripManager.setColors(60, 255);
_stripManager.setFontNumber(3);
@@ -4885,30 +4980,31 @@ void Scene3700::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_seekerSpeaker);
_stripManager.addSpeaker(&_mirandaSpeaker);
- _actor1.postInit();
- _actor1._moveDiff = Common::Point(3, 2);
+ _quinn.postInit();
+ _quinn._moveDiff = Common::Point(3, 2);
- _actor2.postInit();
- _actor2._numFrames = 7;
- _actor2._moveDiff = Common::Point(5, 3);
- _actor2.hide();
+ _seeker.postInit();
+ _seeker._numFrames = 7;
+ _seeker._moveDiff = Common::Point(5, 3);
+ _seeker.hide();
- _actor3.postInit();
- _actor3._moveDiff = Common::Point(3, 2);
- _actor3.hide();
+ _miranda.postInit();
+ _miranda._moveDiff = Common::Point(3, 2);
+ _miranda.hide();
- _actor4.postInit();
- _actor4._numFrames = 7;
- _actor4._moveDiff = Common::Point(5, 3);
- _actor4.hide();
+ _webbster.postInit();
+ _webbster._numFrames = 7;
+ _webbster._moveDiff = Common::Point(5, 3);
+ _webbster.hide();
- _actor5.postInit();
+ _teleportPad.postInit();
- R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.disableControl();
R2_GLOBALS._sound1.play(332);
_sceneMode = 3700;
- setAction(&_sequenceManager, this, 3700, &_actor1, &_actor2, &_actor3, &_actor4, &_actor5, NULL);
+ setAction(&_sequenceManager, this, 3700, &_quinn, &_seeker, &_miranda,
+ &_webbster, &_teleportPad, NULL);
}
void Scene3700::remove() {
@@ -4921,13 +5017,12 @@ void Scene3700::signal() {
case 3328:
// No break on purpose
case 3329:
- warning("STUB: sub_1D227()");
_sceneMode = 3701;
- setAction(&_sequenceManager, this, 3701, &_actor2, &_actor3, &_actor4, NULL);
+ setAction(&_sequenceManager, this, 3701, &_seeker, &_miranda, &_webbster, NULL);
break;
case 3700:
- _actor1.setup(10, 6, 1);
- _actor2.setup(20, 5, 1);
+ _quinn.setup(10, 6, 1);
+ _seeker.setup(20, 5, 1);
if (R2_GLOBALS.getFlag(71)) {
_sceneMode = 3329;
_stripManager.start(3329, this);
@@ -4946,45 +5041,47 @@ void Scene3700::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 3800 -
+ * Scene 3800 - Desert
*
*--------------------------------------------------------------------------*/
+
Scene3800::Scene3800() {
- _field412 = 0;
+ _desertDirection = 0;
}
+
void Scene3800::synchronize(Serializer &s) {
SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
+ s.syncAsSint16LE(_desertDirection);
}
-void Scene3800::Exit1::changeScene() {
+void Scene3800::NorthExit::changeScene() {
Scene3800 *scene = (Scene3800 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->_field412 = 1;
+ R2_GLOBALS._player.disableControl();
+ scene->_desertDirection = 1;
if (R2_GLOBALS.getFlag(46)) {
- if (scene->_field412 == R2_GLOBALS._v566A9) {
- R2_GLOBALS._v566AA = 3;
- if (R2_GLOBALS._v56A93 + 1 == 0) {
- R2_GLOBALS._v566A8--;
- R2_GLOBALS._v566A9 = 0;
+ if (scene->_desertDirection == R2_GLOBALS._desertCorrectDirection) {
+ R2_GLOBALS._desertPreviousDirection = 3;
+ if (R2_GLOBALS._desertWrongDirCtr + 1 == 0) {
+ R2_GLOBALS._desertStepsRemaining--;
+ R2_GLOBALS._desertCorrectDirection = 0;
} else {
- R2_GLOBALS._v566A9 = R2_GLOBALS._v566AB[R2_GLOBALS._v56A93];
- R2_GLOBALS._v56A93--;
+ R2_GLOBALS._desertCorrectDirection = R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr];
+ R2_GLOBALS._desertWrongDirCtr--;
}
} else {
- ++R2_GLOBALS._v56A93;
- if (R2_GLOBALS._v56A93 > 999)
- R2_GLOBALS._v56A93 = 999;
- R2_GLOBALS._v566AB[R2_GLOBALS._v56A93] = R2_GLOBALS._v566A9;
- R2_GLOBALS._v566A9 = 3;
+ ++R2_GLOBALS._desertWrongDirCtr;
+ if (R2_GLOBALS._desertWrongDirCtr > 999)
+ R2_GLOBALS._desertWrongDirCtr = 999;
+ R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr] = R2_GLOBALS._desertCorrectDirection;
+ R2_GLOBALS._desertCorrectDirection = 3;
}
}
- if (R2_GLOBALS._v566A8 == 0)
+ if (R2_GLOBALS._desertStepsRemaining == 0)
scene->_sceneMode = 16;
else
scene->_sceneMode = 11;
@@ -4994,33 +5091,33 @@ void Scene3800::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3800::Exit2::changeScene() {
+void Scene3800::EastExit::changeScene() {
Scene3800 *scene = (Scene3800 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->_field412 = 2;
+ scene->_desertDirection = 2;
if (R2_GLOBALS.getFlag(46)) {
- if (scene->_field412 == R2_GLOBALS._v566A9) {
- R2_GLOBALS._v566AA = 4;
- if (R2_GLOBALS._v56A93 + 1 == 0) {
- R2_GLOBALS._v566A8--;
- R2_GLOBALS._v566A9 = 0;
+ if (scene->_desertDirection == R2_GLOBALS._desertCorrectDirection) {
+ R2_GLOBALS._desertPreviousDirection = 4;
+ if (R2_GLOBALS._desertWrongDirCtr + 1 == 0) {
+ R2_GLOBALS._desertStepsRemaining--;
+ R2_GLOBALS._desertCorrectDirection = 0;
} else {
- R2_GLOBALS._v566A9 = R2_GLOBALS._v566AB[R2_GLOBALS._v56A93];
- R2_GLOBALS._v56A93--;
+ R2_GLOBALS._desertCorrectDirection = R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr];
+ R2_GLOBALS._desertWrongDirCtr--;
}
} else {
- ++R2_GLOBALS._v56A93;
- if (R2_GLOBALS._v56A93 > 999)
- R2_GLOBALS._v56A93 = 999;
- R2_GLOBALS._v566AB[R2_GLOBALS._v56A93] = R2_GLOBALS._v566A9;
- R2_GLOBALS._v566A9 = 4;
+ ++R2_GLOBALS._desertWrongDirCtr;
+ if (R2_GLOBALS._desertWrongDirCtr > 999)
+ R2_GLOBALS._desertWrongDirCtr = 999;
+ R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr] = R2_GLOBALS._desertCorrectDirection;
+ R2_GLOBALS._desertCorrectDirection = 4;
}
}
- if (R2_GLOBALS._v566A8 == 0)
+ if (R2_GLOBALS._desertStepsRemaining == 0)
scene->_sceneMode = 16;
else
scene->_sceneMode = 12;
@@ -5030,33 +5127,33 @@ void Scene3800::Exit2::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3800::Exit3::changeScene() {
+void Scene3800::SouthExit::changeScene() {
Scene3800 *scene = (Scene3800 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->_field412 = 3;
+ scene->_desertDirection = 3;
if (R2_GLOBALS.getFlag(46)) {
- if (scene->_field412 == R2_GLOBALS._v566A9) {
- R2_GLOBALS._v566AA = 1;
- if (R2_GLOBALS._v56A93 + 1 == 0) {
- R2_GLOBALS._v566A8--;
- R2_GLOBALS._v566A9 = 0;
+ if (scene->_desertDirection == R2_GLOBALS._desertCorrectDirection) {
+ R2_GLOBALS._desertPreviousDirection = 1;
+ if (R2_GLOBALS._desertWrongDirCtr + 1 == 0) {
+ R2_GLOBALS._desertStepsRemaining--;
+ R2_GLOBALS._desertCorrectDirection = 0;
} else {
- R2_GLOBALS._v566A9 = R2_GLOBALS._v566AB[R2_GLOBALS._v56A93];
- R2_GLOBALS._v56A93--;
+ R2_GLOBALS._desertCorrectDirection = R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr];
+ R2_GLOBALS._desertWrongDirCtr--;
}
} else {
- ++R2_GLOBALS._v56A93;
- if (R2_GLOBALS._v56A93 > 999)
- R2_GLOBALS._v56A93 = 999;
- R2_GLOBALS._v566AB[R2_GLOBALS._v56A93] = R2_GLOBALS._v566A9;
- R2_GLOBALS._v566A9 = 1;
+ ++R2_GLOBALS._desertWrongDirCtr;
+ if (R2_GLOBALS._desertWrongDirCtr > 999)
+ R2_GLOBALS._desertWrongDirCtr = 999;
+ R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr] = R2_GLOBALS._desertCorrectDirection;
+ R2_GLOBALS._desertCorrectDirection = 1;
}
}
- if (R2_GLOBALS._v566A8 == 0)
+ if (R2_GLOBALS._desertStepsRemaining == 0)
scene->_sceneMode = 16;
else
scene->_sceneMode = 13;
@@ -5066,33 +5163,33 @@ void Scene3800::Exit3::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3800::Exit4::changeScene() {
+void Scene3800::WestExit::changeScene() {
Scene3800 *scene = (Scene3800 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- scene->_field412 = 4;
+ scene->_desertDirection = 4;
if (R2_GLOBALS.getFlag(46)) {
- if (scene->_field412 == R2_GLOBALS._v566A9) {
- R2_GLOBALS._v566AA = 2;
- if (R2_GLOBALS._v56A93 + 1 == 0) {
- R2_GLOBALS._v566A8--;
- R2_GLOBALS._v566A9 = 0;
+ if (scene->_desertDirection == R2_GLOBALS._desertCorrectDirection) {
+ R2_GLOBALS._desertPreviousDirection = 2;
+ if (R2_GLOBALS._desertWrongDirCtr + 1 == 0) {
+ R2_GLOBALS._desertStepsRemaining--;
+ R2_GLOBALS._desertCorrectDirection = 0;
} else {
- R2_GLOBALS._v566A9 = R2_GLOBALS._v566AB[R2_GLOBALS._v56A93];
- R2_GLOBALS._v56A93--;
+ R2_GLOBALS._desertCorrectDirection = R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr];
+ R2_GLOBALS._desertWrongDirCtr--;
}
} else {
- ++R2_GLOBALS._v56A93;
- if (R2_GLOBALS._v56A93 > 999)
- R2_GLOBALS._v56A93 = 999;
- R2_GLOBALS._v566AB[R2_GLOBALS._v56A93] = R2_GLOBALS._v566A9;
- R2_GLOBALS._v566A9 = 2;
+ ++R2_GLOBALS._desertWrongDirCtr;
+ if (R2_GLOBALS._desertWrongDirCtr > 999)
+ R2_GLOBALS._desertWrongDirCtr = 999;
+ R2_GLOBALS._desertMovements[R2_GLOBALS._desertWrongDirCtr] = R2_GLOBALS._desertCorrectDirection;
+ R2_GLOBALS._desertCorrectDirection = 2;
}
}
- if (R2_GLOBALS._v566A8 == 0)
+ if (R2_GLOBALS._desertStepsRemaining == 0)
scene->_sceneMode = 16;
else
scene->_sceneMode = 14;
@@ -5102,28 +5199,28 @@ void Scene3800::Exit4::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3800::initScene3800() {
- _exit1._enabled = true;
- _exit2._enabled = true;
- _exit3._enabled = true;
- _exit4._enabled = true;
- _exit1._insideArea = false;
- _exit2._insideArea = false;
- _exit3._insideArea = false;
- _exit4._insideArea = false;
- _exit1._moving = false;
- _exit2._moving = false;
- _exit3._moving = false;
- _exit4._moving = false;
+void Scene3800::initExits() {
+ _northExit._enabled = true;
+ _eastExit._enabled = true;
+ _southExit._enabled = true;
+ _westExit._enabled = true;
+ _northExit._insideArea = false;
+ _eastExit._insideArea = false;
+ _southExit._insideArea = false;
+ _westExit._insideArea = false;
+ _northExit._moving = false;
+ _eastExit._moving = false;
+ _southExit._moving = false;
+ _westExit._moving = false;
- loadScene(R2_GLOBALS._v566A6);
+ loadScene(R2_GLOBALS._maze3800SceneNumb);
R2_GLOBALS._uiElements.draw();
}
-void Scene3800::sub110BBD() {
+void Scene3800::enterArea() {
R2_GLOBALS._player.disableControl();
- switch (_field412) {
+ switch (_desertDirection) {
case 0:
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setVisage(10);
@@ -5132,24 +5229,27 @@ void Scene3800::sub110BBD() {
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS._player.changeZoom(-1);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- _actor1.postInit();
- _actor1.fixPriority(10);
- _actor1.changeZoom(-1);
- _actor1.setVisage(1110);
- _actor1._effect = 5;
- _actor1._field9C = this->_field312;
- R2_GLOBALS._player._linkedActor = &_actor1;
+
+ _quinnShadow.postInit();
+ _quinnShadow.fixPriority(10);
+ _quinnShadow.changeZoom(-1);
+ _quinnShadow.setVisage(1110);
+ _quinnShadow._effect = EFFECT_SHADOW_MAP;
+ _quinnShadow._shadowMap = this->_shadowPaletteMap;
+ R2_GLOBALS._player._linkedActor = &_quinnShadow;
+
switch (R2_GLOBALS._sceneManager._previousScene) {
case 2600:
- _object1.postInit();
- _object2.postInit();
- _actor1.hide();
+ _balloon.postInit();
+ _harness.postInit();
+ _quinnShadow.hide();
_sceneMode = 3800;
- setAction(&_sequenceManager1, this, 3800, &R2_GLOBALS._player, &_object1, &_object2, NULL);
+ setAction(&_sequenceManager1, this, 3800, &R2_GLOBALS._player,
+ &_balloon, &_harness, NULL);
break;
case 3900:
_sceneMode = 15;
- switch (R2_GLOBALS._v566AA - 1) {
+ switch (R2_GLOBALS._desertPreviousDirection - 1) {
case 0: {
R2_GLOBALS._player.setPosition(Common::Point(160, 220));
Common::Point pt(160, 160);
@@ -5181,8 +5281,9 @@ void Scene3800::sub110BBD() {
default:
break;
}
+ break;
default:
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
}
break;
@@ -5224,9 +5325,9 @@ void Scene3800::sub110BBD() {
}
void Scene3800::postInit(SceneObjectList *OwnerList) {
- _field412 = 0;
+ _desertDirection = 0;
- initScene3800();
+ initExits();
SceneExt::postInit();
R2_GLOBALS._sound1.play(231);
@@ -5235,79 +5336,77 @@ void Scene3800::postInit(SceneObjectList *OwnerList) {
setZoomPercents(87, 40, 144, 100);
- _exit1.setDetails(Rect(14, 87, 305, 125), SHADECURSOR_UP, 3800);
- _exit1.setDest(Common::Point(160, 126));
- _exit2.setDetails(Rect(305, 87, 320, 128), EXITCURSOR_E, 3800);
- _exit2.setDest(Common::Point(312, 145));
- _exit3.setDetails(Rect(14, 160, 305, 168), SHADECURSOR_DOWN, 3800);
- _exit3.setDest(Common::Point(160, 165));
- _exit4.setDetails(Rect(0, 87, 14, 168), EXITCURSOR_W, 3800);
- _exit4.setDest(Common::Point(7, 145));
+ _northExit.setDetails(Rect(14, 87, 305, 125), SHADECURSOR_UP, 3800);
+ _northExit.setDest(Common::Point(160, 126));
+ _eastExit.setDetails(Rect(305, 87, 320, 168), EXITCURSOR_E, 3800);
+ _eastExit.setDest(Common::Point(312, 145));
+ _southExit.setDetails(Rect(14, 160, 305, 168), SHADECURSOR_DOWN, 3800);
+ _southExit.setDest(Common::Point(160, 165));
+ _westExit.setDetails(Rect(0, 87, 14, 168), EXITCURSOR_W, 3800);
+ _westExit.setDest(Common::Point(7, 145));
- _rect1.set(0, 0, 320, 87);
- _item1.setDetails(Rect(0, 0, 320, 200), 3800, 0, 1, 2, 1, (SceneItem *) NULL);
+ _skylineRect.set(0, 0, 320, 87);
+ _background.setDetails(Rect(0, 0, 320, 200), 3800, 0, 1, 2, 1, (SceneItem *) NULL);
- sub110BBD();
+ enterArea();
}
void Scene3800::signal() {
switch (_sceneMode) {
case 11:
- R2_GLOBALS._v566A6 += 15;
- if (R2_GLOBALS._v566A6 > 3815)
- R2_GLOBALS._v566A6 -= 20;
- initScene3800();
- sub110BBD();
+ R2_GLOBALS._maze3800SceneNumb += 15;
+ if (R2_GLOBALS._maze3800SceneNumb > 3815)
+ R2_GLOBALS._maze3800SceneNumb -= 20;
+ initExits();
+ enterArea();
break;
case 12:
- R2_GLOBALS._v566A6 += 5;
- if (R2_GLOBALS._v566A6 > 3815)
- R2_GLOBALS._v566A6 = 3800;
- initScene3800();
- sub110BBD();
+ R2_GLOBALS._maze3800SceneNumb += 5;
+ if (R2_GLOBALS._maze3800SceneNumb > 3815)
+ R2_GLOBALS._maze3800SceneNumb = 3800;
+ initExits();
+ enterArea();
break;
case 13:
- R2_GLOBALS._v566A6 -= 15;
- if (R2_GLOBALS._v566A6 < 3800)
- R2_GLOBALS._v566A6 += 20;
- initScene3800();
- sub110BBD();
+ R2_GLOBALS._maze3800SceneNumb -= 15;
+ if (R2_GLOBALS._maze3800SceneNumb < 3800)
+ R2_GLOBALS._maze3800SceneNumb += 20;
+ initExits();
+ enterArea();
break;
case 14:
- R2_GLOBALS._v566A6 -= 5;
- if (R2_GLOBALS._v566A6 < 3800)
- R2_GLOBALS._v566A6 = 3815;
- initScene3800();
- sub110BBD();
+ R2_GLOBALS._maze3800SceneNumb -= 5;
+ if (R2_GLOBALS._maze3800SceneNumb < 3800)
+ R2_GLOBALS._maze3800SceneNumb = 3815;
+ initExits();
+ enterArea();
break;
case 15:
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl();
break;
case 16:
g_globals->_sceneManager.changeScene(3900);
break;
case 3800:
- _actor1.show();
- _object1.remove();
- _object2.remove();
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ _quinnShadow.show();
+ _balloon.remove();
+ _harness.remove();
+ R2_GLOBALS._player.enableControl();
break;
case 3805:
- _exit1._enabled = false;
- _exit2._enabled = false;
- _exit3._enabled = false;
- _exit4._enabled = false;
+ _northExit._enabled = false;
+ _eastExit._enabled = false;
+ _southExit._enabled = false;
+ _westExit._enabled = false;
R2_GLOBALS._player._canWalk = false;
R2_GLOBALS._events.setCursor(CURSOR_USE);
break;
case 3806:
- _exit1._enabled = true;
- _exit2._enabled = true;
- _exit3._enabled = true;
- _exit4._enabled = true;
- R2_GLOBALS._player.disableControl(CURSOR_ARROW);
+ _northExit._enabled = true;
+ _eastExit._enabled = true;
+ _southExit._enabled = true;
+ _westExit._enabled = true;
+ R2_GLOBALS._player.enableControl();
break;
default:
break;
@@ -5315,18 +5414,19 @@ void Scene3800::signal() {
}
void Scene3800::process(Event &event) {
- if ((R2_GLOBALS._player._uiEnabled) && (event.eventType == 1) && (_rect1.contains(event.mousePos))) {
+ if ((R2_GLOBALS._player._uiEnabled) && (event.eventType == EVENT_BUTTON_DOWN)
+ && (_skylineRect.contains(event.mousePos))) {
event.handled = true;
switch (R2_GLOBALS._events.getCursor()) {
- case R2_NEGATOR_GUN:
+ case CURSOR_WALK:
R2_GLOBALS._player.addMover(NULL);
R2_GLOBALS._player.updateAngle(event.mousePos);
break;
- case R2_STEPPING_DISKS:
- SceneItem::display(3800, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ case CURSOR_LOOK:
+ SceneItem::display(3800, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
- case R2_ATTRACTOR_UNIT:
- SceneItem::display(3800, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ case CURSOR_USE:
+ SceneItem::display(3800, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
default:
event.handled = false;
@@ -5338,17 +5438,18 @@ void Scene3800::process(Event &event) {
}
/*--------------------------------------------------------------------------
- * Scene 3900 -
+ * Scene 3900 - Forest Entrance
*
*--------------------------------------------------------------------------*/
-void Scene3900::Exit1::changeScene() {
+
+void Scene3900::NorthExit::changeScene() {
Scene3900 *scene = (Scene3900 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A9 = 3;
- R2_GLOBALS._v566AA = 1;
- R2_GLOBALS._v566A8 = 1;
+ R2_GLOBALS._desertCorrectDirection = 3;
+ R2_GLOBALS._desertPreviousDirection = 1;
+ R2_GLOBALS._desertStepsRemaining = 1;
scene->_sceneMode = 14;
Common::Point pt(160, 115);
@@ -5356,14 +5457,14 @@ void Scene3900::Exit1::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3900::Exit2::changeScene() {
+void Scene3900::EastExit::changeScene() {
Scene3900 *scene = (Scene3900 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A9 = 4;
- R2_GLOBALS._v566AA = 2;
- R2_GLOBALS._v566A8 = 1;
+ R2_GLOBALS._desertCorrectDirection = 4;
+ R2_GLOBALS._desertPreviousDirection = 2;
+ R2_GLOBALS._desertStepsRemaining = 1;
scene->_sceneMode = 14;
Common::Point pt(330, 145);
@@ -5371,14 +5472,14 @@ void Scene3900::Exit2::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3900::Exit3::changeScene() {
+void Scene3900::SouthExit::changeScene() {
Scene3900 *scene = (Scene3900 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A9 = 1;
- R2_GLOBALS._v566AA = 3;
- R2_GLOBALS._v566A8 = 1;
+ R2_GLOBALS._desertCorrectDirection = 1;
+ R2_GLOBALS._desertPreviousDirection = 3;
+ R2_GLOBALS._desertStepsRemaining = 1;
scene->_sceneMode = 14;
Common::Point pt(160, 220);
@@ -5386,14 +5487,14 @@ void Scene3900::Exit3::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
-void Scene3900::Exit4::changeScene() {
+void Scene3900::WestExit::changeScene() {
Scene3900 *scene = (Scene3900 *)R2_GLOBALS._sceneManager._scene;
_enabled = false;
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
- R2_GLOBALS._v566A9 = 2;
- R2_GLOBALS._v566AA = 4;
- R2_GLOBALS._v566A8 = 1;
+ R2_GLOBALS._desertCorrectDirection = 2;
+ R2_GLOBALS._desertPreviousDirection = 4;
+ R2_GLOBALS._desertStepsRemaining = 1;
scene->_sceneMode = 14;
Common::Point pt(-10, 145);
@@ -5408,7 +5509,7 @@ void Scene3900::Exit5::changeScene() {
R2_GLOBALS._player.disableControl(CURSOR_ARROW);
scene->_sceneMode = 13;
- if (R2_GLOBALS._v566A9 == 4) {
+ if (R2_GLOBALS._desertCorrectDirection == 4) {
Common::Point pt(-10, 135);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, scene);
@@ -5418,17 +5519,20 @@ void Scene3900::Exit5::changeScene() {
R2_GLOBALS._player.addMover(mover, &pt, scene);
}
- R2_GLOBALS._v566A9 = 0;
+ R2_GLOBALS._desertCorrectDirection = 0;
}
void Scene3900::postInit(SceneObjectList *OwnerList) {
- if ((R2_GLOBALS._v566AA == 2) && (R2_GLOBALS._sceneManager._previousScene != 2700))
+ if ((R2_GLOBALS._desertPreviousDirection == 2)
+ && (R2_GLOBALS._sceneManager._previousScene != 2700))
loadScene(3825);
else
loadScene(3820);
SceneExt::postInit();
+
R2_GLOBALS._sound1.changeSound(231);
setZoomPercents(87, 40, 144, 100);
+
R2_GLOBALS._player.disableControl();
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setVisage(10);
@@ -5436,92 +5540,97 @@ void Scene3900::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.setStrip(3);
R2_GLOBALS._player.changeZoom(-1);
R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
- _actor1.postInit();
- _actor1.fixPriority(10);
- _actor1.changeZoom(-1);
- _actor1.setVisage(1110);
- _actor1._effect = 5;
- _actor1._field9C = _field312;
- R2_GLOBALS._player._linkedActor = &_actor1;
- if ((R2_GLOBALS._v566AA == 2) && (R2_GLOBALS._sceneManager._previousScene != 2700)) {
+
+ _quinnShadow.postInit();
+ _quinnShadow.fixPriority(10);
+ _quinnShadow.changeZoom(-1);
+ _quinnShadow.setVisage(1110);
+ _quinnShadow._effect = EFFECT_SHADOW_MAP;
+ _quinnShadow._shadowMap = _shadowPaletteMap;
+ R2_GLOBALS._player._linkedActor = &_quinnShadow;
+
+ if ((R2_GLOBALS._desertPreviousDirection == 2) && (R2_GLOBALS._sceneManager._previousScene != 2700)) {
// loadScene(3825);
- R2_GLOBALS._v566AA = 4;
- _exit1.setDetails(Rect(29, 87, 305, 125), SHADECURSOR_UP, 3900);
- _exit3.setDetails(Rect(29, 160, 305, 168), SHADECURSOR_DOWN, 3900);
+ R2_GLOBALS._desertCorrectDirection = 4;
+ _northExit.setDetails(Rect(29, 87, 305, 125), SHADECURSOR_UP, 3900);
+ _southExit.setDetails(Rect(29, 160, 305, 168), SHADECURSOR_DOWN, 3900);
- _exit2.setDetails(Rect(305, 87, 320, 168), EXITCURSOR_E, 3900);
- _exit2.setDest(Common::Point(312, 145));
- _exit2._enabled = true;
- _exit2._insideArea = false;
- _exit2._moving = false;
+ _eastExit.setDetails(Rect(305, 87, 320, 168), EXITCURSOR_E, 3900);
+ _eastExit.setDest(Common::Point(312, 145));
+ _eastExit._enabled = true;
+ _eastExit._insideArea = false;
+ _eastExit._moving = false;
- _exit4._enabled = false;
+ _westExit._enabled = false;
- _exit5.setDetails(Rect(0, 87, 29, 168), EXITCURSOR_W, 3900);
- _exit5.setDest(Common::Point(24, 135));
+ _westEnterForest.setDetails(Rect(0, 87, 29, 168), EXITCURSOR_W, 3900);
+ _westEnterForest.setDest(Common::Point(24, 135));
} else {
// loadScene(3820);
- R2_GLOBALS._v566AA = 2;
- _exit1.setDetails(Rect(14, 87, 290, 125), SHADECURSOR_UP, 3900);
- _exit3.setDetails(Rect(14, 160, 290, 168), SHADECURSOR_DOWN, 3900);
-
+ R2_GLOBALS._desertCorrectDirection = 2;
+ _northExit.setDetails(Rect(14, 87, 290, 125), SHADECURSOR_UP, 3900);
+ _southExit.setDetails(Rect(14, 160, 290, 168), SHADECURSOR_DOWN, 3900);
- _exit2._enabled = false;
+ _eastExit._enabled = false;
- _exit4.setDetails(Rect(0, 87, 14, 168), EXITCURSOR_W, 3900);
- _exit4.setDest(Common::Point(7, 145));
- _exit4._enabled = true;
- _exit4._insideArea = false;
- _exit4._moving = false;
+ _westExit.setDetails(Rect(0, 87, 14, 168), EXITCURSOR_W, 3900);
+ _westExit.setDest(Common::Point(7, 145));
+ _westExit._enabled = true;
+ _westExit._insideArea = false;
+ _westExit._moving = false;
- _exit5.setDetails(Rect(290, 87, 320, 168), EXITCURSOR_E, 3900);
- _exit5.setDest(Common::Point(295, 135));
+ _westEnterForest.setDetails(Rect(290, 87, 320, 168), EXITCURSOR_E, 3900);
+ _westEnterForest.setDest(Common::Point(295, 135));
}
- _exit5._enabled = true;
- _exit5._insideArea = false;
- _exit5._moving = false;
+ _westEnterForest._enabled = true;
+ _westEnterForest._insideArea = false;
+ _westEnterForest._moving = false;
scalePalette(65, 65, 65);
- _exit1.setDest(Common::Point(160, 126));
- _exit1._enabled = true;
- _exit1._insideArea = false;
- _exit1._moving = false;
+ _northExit.setDest(Common::Point(160, 126));
+ _northExit._enabled = true;
+ _northExit._insideArea = false;
+ _northExit._moving = false;
- _exit3.setDest(Common::Point(160, 165));
- _exit3._enabled = true;
- _exit3._insideArea = false;
- _exit3._moving = false;
+ _southExit.setDest(Common::Point(160, 165));
+ _southExit._enabled = true;
+ _southExit._insideArea = false;
+ _southExit._moving = false;
R2_GLOBALS._uiElements.draw();
- _rect1.set(0, 0, 320, 87);
- _item1.setDetails(Rect(0, 0, 320, 200), 3800, 0, 1, 2, 1, (SceneItem *)NULL);
+ _skylineRect.set(0, 0, 320, 87);
+ _background.setDetails(Rect(0, 0, 320, 200), 3800, 0, 1, 2, 1, (SceneItem *)NULL);
if (R2_GLOBALS._sceneManager._previousScene == 3800) {
_sceneMode = 11;
- switch (R2_GLOBALS._v566AA - 1) {
- case 0: {
+ switch (R2_GLOBALS._desertPreviousDirection) {
+ case 1: {
+ // Entering from the north
R2_GLOBALS._player.setPosition(Common::Point(160, 115));
Common::Point pt(160, 120);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
- case 1: {
+ case 2: {
+ // Entering from the east
R2_GLOBALS._player.setPosition(Common::Point(330, 145));
Common::Point pt(300, 145);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
- case 2: {
+ case 3: {
+ // Entering from the south
R2_GLOBALS._player.setPosition(Common::Point(160, 220));
Common::Point pt(160, 160);
NpcMover *mover = new NpcMover();
R2_GLOBALS._player.addMover(mover, &pt, this);
}
break;
- case 3: {
+ case 4: {
+ // Entering from the west
R2_GLOBALS._player.setPosition(Common::Point(-10, 145));
Common::Point pt(19, 145);
NpcMover *mover = new NpcMover();
@@ -5539,7 +5648,7 @@ void Scene3900::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.addMover(mover, &pt, this);
} else {
R2_GLOBALS._player.setPosition(Common::Point(160, 145));
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
}
}
@@ -5548,8 +5657,7 @@ void Scene3900::signal() {
case 11:
// No break on purpose
case 12:
- R2_GLOBALS._v56AAB = 0;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
case 13:
R2_GLOBALS._sceneManager.changeScene(2700);
@@ -5558,19 +5666,19 @@ void Scene3900::signal() {
R2_GLOBALS._sceneManager.changeScene(3800);
break;
case 3805:
- _exit1._enabled = false;
- _exit2._enabled = false;
- _exit3._enabled = false;
- _exit4._enabled = false;
+ _northExit._enabled = false;
+ _eastExit._enabled = false;
+ _southExit._enabled = false;
+ _westExit._enabled = false;
R2_GLOBALS._player._canWalk = false;
- R2_GLOBALS._events.setCursor(R2_STEPPING_DISKS);
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
break;
case 3806:
- _exit1._enabled = true;
- _exit2._enabled = true;
- _exit3._enabled = true;
- _exit4._enabled = true;
- R2_GLOBALS._player.enableControl(CURSOR_ARROW);
+ _northExit._enabled = true;
+ _eastExit._enabled = true;
+ _southExit._enabled = true;
+ _westExit._enabled = true;
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
break;
default:
break;
@@ -5578,18 +5686,19 @@ void Scene3900::signal() {
}
void Scene3900::process(Event &event) {
- if ((R2_GLOBALS._player._uiEnabled) && (event.eventType == 1) && (_rect1.contains(event.mousePos))) {
+ if ((R2_GLOBALS._player._uiEnabled) && (event.eventType == EVENT_BUTTON_DOWN)
+ && (_skylineRect.contains(event.mousePos))) {
event.handled = true;
switch (R2_GLOBALS._events.getCursor()) {
- case R2_NEGATOR_GUN:
+ case CURSOR_WALK:
R2_GLOBALS._player.addMover(NULL);
R2_GLOBALS._player.updateAngle(event.mousePos);
break;
- case R2_STEPPING_DISKS:
- SceneItem::display(3800, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ case CURSOR_USE:
+ SceneItem::display(3800, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
- case R2_ATTRACTOR_UNIT:
- SceneItem::display(3800, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ case CURSOR_LOOK:
+ SceneItem::display(3800, 3, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
break;
default:
event.handled = false;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.h b/engines/tsage/ringworld2/ringworld2_scenes3.h
index 44787b9eef..398d09a01e 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.h
@@ -45,16 +45,15 @@ class Scene3100 : public SceneExt {
virtual bool startAction(CursorType action, Event &event);
};
public:
-
- int _field412;
+ bool _fadeSound;
SpeakerGuard _guardSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
+ NamedHotspot _background;
+ NamedHotspot _hammerHead2;
+ SceneActor _hammerHead;
+ SceneActor _miranda;
+ SceneActor _ghoul;
+ SceneActor _technicians;
+ SceneActor _deadBodies;
Guard _guard;
ASoundExt _sound1;
SequenceManager _sequenceManager;
@@ -68,36 +67,33 @@ public:
};
class Scene3125 : public SceneExt {
- class Item1 : public NamedHotspot {
+ class Background : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item2 : public Item1 {
+ class Table : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item3 : public Item1 {
+ class Computer : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor1 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
public:
-
- int _field412;
- Item1 _item1;
- Actor1 _actor1;
- Item2 _item2;
- Item3 _item3;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SequenceManager _sequenceManager1;
- // Second sequence manager... Unused?
- SequenceManager _sequenceManager2;
+ bool _soundPlayed;
+ Background _background;
+ Door _door;
+ Table _table;
+ Computer _computer;
+ SceneActor _ghoul1;
+ SceneActor _ghoul2;
+ SceneActor _ghoul3;
+ SceneActor _ghoul4;
+ SequenceManager _sequenceManager;
Scene3125();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -107,52 +103,51 @@ public:
};
class Scene3150 : public SceneExt {
- class Item5 : public NamedHotspot {
+ class LightFixture : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Item6 : public NamedHotspot {
+ class Toilet : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Water : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor5 : public SceneActor {
+ class FoodTray : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class ToiletFlush : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class AirVent : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class DoorExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class VentExit : public SceneExit {
public:
virtual void changeScene();
};
public:
-
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- Item5 _item5;
- Item6 _item6;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- Actor4 _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
- Exit1 _exit1;
- Exit2 _exit2;
+ NamedHotspot _background;
+ NamedHotspot _bed;
+ NamedHotspot _lightFixture2;
+ NamedHotspot _bars;
+ LightFixture _lightFixture;
+ Toilet _toilet;
+ SceneActor _guard;
+ SceneActor _doorBars;
+ SceneActor _bulbOrWire;
+ Water _water;
+ FoodTray _foodTray;
+ ToiletFlush _toiletFlush;
+ AirVent _airVent;
+ DoorExit _doorExit;
+ VentExit _ventExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -161,25 +156,24 @@ public:
};
class Scene3175 : public SceneExt {
- class Item1 : public NamedHotspot {
+ class RoomItem : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor1 : public Actor3 {
+ class Corpse : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
public:
-
- Item1 _item1;
- Item1 _item2;
- Item1 _item3;
- Actor1 _actor1;
- SceneActor _actor2;
- Actor3 _actor3;
+ RoomItem _background;
+ RoomItem _table;
+ RoomItem _autopsies;
+ Door _door;
+ SceneActor _computer;
+ Corpse _corpse;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -191,9 +185,9 @@ public:
SpeakerRocko3200 _rockoSpeaker;
SpeakerJocko3200 _jockoSpeaker;
SpeakerSocko3200 _sockoSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
+ SceneActor _rocko;
+ SceneActor _jocko;
+ SceneActor _socko;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -204,8 +198,8 @@ class Scene3210 : public SceneExt {
public:
SpeakerCaptain3210 _captainSpeaker;
SpeakerPrivate3210 _privateSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
+ SceneActor _captain;
+ SceneActor _private;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -216,8 +210,8 @@ class Scene3220 : public SceneExt {
public:
SpeakerRocko3220 _rockoSpeaker;
SpeakerJocko3220 _jockoSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
+ SceneActor _rocko;
+ SceneActor _jocko;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -228,9 +222,9 @@ class Scene3230 : public SceneExt {
public:
SpeakerRocko3230 _rockoSpeaker;
SpeakerJocko3230 _jockoSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
+ SceneActor _rocko;
+ SceneActor _jocko;
+ SceneActor _ghoul;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -242,8 +236,8 @@ public:
SpeakerTeal3240 _tealSpeaker;
SpeakerWebbster3240 _webbsterSpeaker;
SpeakerMiranda _mirandaSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
+ SceneActor _teal;
+ SceneActor _webbster;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -254,8 +248,8 @@ class Scene3245 : public SceneExt {
public:
SpeakerRalf3245 _ralfSpeaker;
SpeakerTomko3245 _tomkoSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
+ SceneActor _ralf;
+ SceneActor _tomko;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -268,22 +262,21 @@ class Scene3250 : public SceneExt {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
public:
-
- Item _item1;
- Item _item2;
- Item _item3;
- Item _item4;
- Actor _actor1;
- Actor _actor2;
- Actor _actor3;
- Actor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
+ Item _background;
+ Item _tnuctipunShip;
+ Item _floodLights;
+ Item _negator;
+ Door _leftDoor;
+ Door _topDoor;
+ Door _rightDoor;
+ Door _grate;
+ SceneActor _ghoul1;
+ SceneActor _ghoul2;
+ SceneActor _ghoul3;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -293,13 +286,13 @@ public:
class Scene3255 : public SceneExt {
public:
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
+ SceneActor _teal;
+ SceneActor _guard;
+ SceneActor _door;
+ SceneActor _quinn;
+ SceneActor _ghoul1;
+ SceneActor _ghoul2;
+ SceneActor _ghoul3;
SpeakerQuinn3255 _quinnSpeaker;
SpeakerMiranda3255 _mirandaSpeaker;
SequenceManager _sequenceManager;
@@ -310,10 +303,10 @@ public:
};
class Scene3260 : public SceneExt {
- class Actor13 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor14 : public SceneActor {
+ class Toolbox : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
@@ -322,22 +315,21 @@ class Scene3260 : public SceneExt {
void signal();
};
public:
-
- NamedHotspot _item1;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
- SceneActor _actor10;
- SceneActor _actor11;
- SceneActor _actor12;
- Actor13 _actor13;
- Actor14 _actor14;
+ NamedHotspot _background;
+ SceneActor _sceeen1;
+ SceneActor _screen2;
+ SceneActor _screen3;
+ SceneActor _screen4;
+ SceneActor _screen5;
+ SceneActor _screen6;
+ SceneActor _screen7;
+ SceneActor _screen8;
+ SceneActor _screen9;
+ SceneActor _securityConsole;
+ SceneActor _computerConsole;
+ SceneActor _lightingConsole;
+ Door _door;
+ Toolbox _toolbox;
Action1 _action1;
Action1 _action2;
Action1 _action3;
@@ -358,23 +350,23 @@ public:
};
class Scene3275 : public SceneExt {
- class Actor2 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class CellExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- NamedHotspot _item5;
- SceneActor _actor1;
- Actor2 _actor2;
- Exit1 _exit1;
+ NamedHotspot _background;
+ NamedHotspot _emptyCell1;
+ NamedHotspot _emptyCell2;
+ NamedHotspot _securityBeams1;
+ NamedHotspot _securityBeams2;
+ SceneActor _doorFrame;
+ Door _door;
+ CellExit _cellExit;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -383,15 +375,15 @@ public:
class Scene3350 : public SceneExt {
public:
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
+ SceneActor _miranda;
+ SceneActor _seeker;
+ SceneActor _webbster;
+ SceneActor _seatedPeople;
+ SceneActor _ship;
+ SceneActor _landedShip;
+ SceneActor _shipShadow;
+ SceneActor _canopy;
+ SceneActor _shipFront;
SequenceManager _sequenceManager;
PaletteRotation *_rotation;
@@ -401,53 +393,52 @@ public:
};
class Scene3375 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion1 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Companion2 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Webbster : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class LeftExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class DownExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class RightExit : public SceneExit {
public:
virtual void changeScene();
};
void signalCase3379();
- void subFC696(int sceneMode);
+ void enterArea(int sceneMode);
public:
SpeakerQuinn3375 _quinnSpeaker;
SpeakerSeeker3375 _seekerSpeaker;
SpeakerMiranda3375 _mirandaSpeaker;
SpeakerWebbster3375 _webbsterSpeaker;
- NamedHotspot _item1;
+ NamedHotspot _background;
NamedHotspot _itemArray[13];
- Actor1 _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
+ Companion1 _companion1;
+ Companion2 _companion2;
+ Webbster _webbster;
+ Door _door;
+ LeftExit _leftExit;
+ DownExit _downExit;
+ RightExit _rightExit;
SequenceManager _sequenceManager;
- int _field1488;
- int _field148A[4];
- int _field1492;
+ int _newSceneMode;
+ int _sceneAreas[4];
Scene3375();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -458,20 +449,20 @@ public:
};
class Scene3385 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion1 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Companion2 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Webbster : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Exit1 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -486,16 +477,16 @@ public:
SpeakerSeeker3385 _seekerSpeaker;
SpeakerMiranda3385 _mirandaSpeaker;
SpeakerWebbster3385 _webbsterSpeaker;
- NamedHotspot _item1;
- Actor1 _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
- Exit1 _exit1;
+ NamedHotspot _background;
+ Companion1 _companion1;
+ Companion2 _companion2;
+ Webbster _webbster;
+ Door _door;
+ SouthExit _southExit;
Action1 _action1;
SequenceManager _sequenceManager;
- int _field11B2;
+ int _playerStrip;
Scene3385();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -505,16 +496,16 @@ public:
};
class Scene3395 : public SceneExt {
- class Actor1 : public SceneActor {
+ class Companion1 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor2 : public SceneActor {
+ class Companion2 : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor3 : public SceneActor {
+ class Webbster : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
- class Actor4 : public SceneActor {
+ class Door : public SceneActor {
virtual bool startAction(CursorType action, Event &event);
};
@@ -528,16 +519,16 @@ public:
SpeakerSeeker3395 _seekerSpeaker;
SpeakerMiranda3395 _mirandaSpeaker;
SpeakerWebbster3395 _webbsterSpeaker;
- NamedHotspot _item1;
+ NamedHotspot _background;
NamedHotspot _itemArray[13];
- Actor1 _actor1;
- Actor2 _actor2;
- Actor3 _actor3;
- Actor4 _actor4;
+ Companion1 _companion1;
+ Companion2 _companion2;
+ Webbster _webbster;
+ Door _door;
Action1 _action1;
SequenceManager _sequenceManager;
- int _field142E;
+ int _playerStrip;
Scene3395();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -553,16 +544,15 @@ public:
SpeakerMiranda3400 _mirandaSpeaker;
SpeakerWebbster3400 _webbsterSpeaker;
SpeakerTeal3400 _tealSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
+ SceneActor _companion1;
+ SceneActor _companion2;
+ SceneActor _webbster;
+ SceneActor _teal;
+ SceneActor _door;
+ SceneActor _manholeCover;
+ SceneActor _sapphire;
SequenceManager _sequenceManager;
- int16 _field157C;
+ bool _soundFaded;
Scene3400();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -574,114 +564,105 @@ public:
class Scene3500 : public SceneExt {
class Action1: public Action {
public:
- int _field1E;
- int _field20;
- int _field22;
- int _field24;
+ int _direction;
+ bool _field20;
+ int _field22; // CHECKME: Useless field
+ bool _field24;
Action1();
virtual void synchronize(Serializer &s);
- void sub108670(int arg1);
- void sub108732(int arg1);
+ void handleHorzButton(int direction);
+ void turnShuttle(bool arg1);
virtual void signal();
virtual void dispatch();
};
class Action2: public Action {
public:
- int _field1E;
+ int _direction;
Action2();
virtual void synchronize(Serializer &s);
- void sub10831F(int arg1);
+ void handleVertButton(int direction);
virtual void signal();
};
- class Item4 : public NamedHotspot {
+ class DirectionButton : public NamedHotspot {
public:
- int _field34;
+ int _movementId;
- Item4();
+ DirectionButton();
virtual void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class Throttle : public SceneActor {
public:
- int _fieldA4;
- int _fieldA6;
- int _fieldA8;
- int _fieldAA;
- int _fieldAC;
- int _fieldAE;
+ Common::Point _pos;
+ int _deltaX;
+ int _deltaY;
+ int _slideDeltaY;
+ int _deltaMouseY;
- Actor7();
+ Throttle();
virtual void synchronize(Serializer &s);
- void sub109466(int arg1, int arg2, int arg3, int arg4, int arg5);
- void sub1094ED();
- void sub109663(int arg1);
- void sub109693(Common::Point Pt);
+ void init(int xp, int yp, int dx, int dy, int speed);
+ void updateSpeed();
+ void setSpeed(int arg1);
+ void changePosition(const Common::Point &pt);
virtual void process(Event &event);
virtual bool startAction(CursorType action, Event &event);
};
- class Actor8 : public SceneActor {
- public:
- // 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;
Action2 _action2;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- Item4 _item4;
- Item4 _item5;
- Item4 _item6;
- Item4 _item7;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- Actor7 _actor7;
- Actor8 _actor8;
- Actor8 _actor9;
+ NamedHotspot _background;
+ NamedHotspot _outsideView;
+ NamedHotspot _mapScreen;
+ DirectionButton _pitchDown;
+ DirectionButton _turnLeft;
+ DirectionButton _pitchUp;
+ DirectionButton _turnRight;
+ // Glyph of vessel on top of the maze ui
+ SceneActor _shuttle;
+ SceneActor _verticalSpeedDisplay;
+ SceneActor _horizontalSpeedDisplay;
+ SceneActor _symbolVertical;
+ SceneActor _symbolLeft;
+ SceneActor _symbolRight;
+ Throttle _throttle;
+ SceneActor _tunnelVertCircle;
+ SceneActor _tunnelHorzCircle;
ASoundExt _aSound1;
- UnkObject3500 _unkObj1;
+ MazeUI3500 _mazeUI;
SequenceManager _sequenceManager;
- int _fieldAF8;
- int _fieldB9E;
+ int _moverVertX;
+ int _moverHorzX;
PaletteRotation *_rotation;
- int _field126E;
- int _field1270;
- int _field1272;
- int _field1274;
- int _field1276;
- int _field1278;
- int _field127A;
- int _field127C;
- int _field127E;
- int _field1280;
- int _field1282;
+ int _mazeChangeAmount;
+ int _speed;
+ bool _field1272;
+ int _mazeDirection;
+ int _nextMove;
+ Common::Point _mazePosition;
+ bool _field1282;
int _field1284;
- int _field1286;
+ bool _directionChangesEnabled;
Scene3500();
- void sub107F71(int arg1);
+ void doMovement(int id);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
@@ -694,7 +675,8 @@ public:
class Scene3600 : public SceneExt {
class Action3600: public ActionExt {
public:
- int _field1E, _field20;
+ bool _field1E;
+ int _fadePct;
Action3600();
virtual void synchronize(Serializer &s);
@@ -705,12 +687,12 @@ class Scene3600 : public SceneExt {
virtual void signal();
};
- class Item5 : public NamedHotspot {
+ class LightShaft : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor13 : public SceneActorExt {
+ class Protector : public SceneActorExt {
virtual bool startAction(CursorType action, Event &event);
};
public:
@@ -721,35 +703,30 @@ public:
SpeakerMiranda3600 _mirandaSpeaker;
SpeakerTeal3600 _tealSpeaker;
SpeakerProtector3600 _protectorSpeaker;
- NamedHotspot _item1;
- NamedHotspot _item2;
- NamedHotspot _item3;
- NamedHotspot _item4;
- Item5 _item5;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
- SceneActor _actor6;
- SceneActor _actor7;
- SceneActor _actor8;
- SceneActor _actor9;
- SceneActor _actor10;
- SceneActor _actor11;
- SceneActor _actor12;
- Actor13 _actor13;
+ NamedHotspot _background;
+ NamedHotspot _console;
+ NamedHotspot _tapestry1;
+ NamedHotspot _tapestry2;
+ LightShaft _lightShaft;
+ SceneActor _protector3400;
+ SceneActor _steppingDisk;
+ SceneActor _consoleLights;
+ SceneActor _webbster;
+ SceneActor _teal;
+ SceneActor _door3400;
+ SceneActor _quinn;
+ SceneActor _seeker;
+ SceneActor _miranda;
+ Protector _protector;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
SequenceManager _sequenceManager3;
SequenceManager _sequenceManager4;
ScenePalette _palette1;
- int _field2548;
- int _field254A;
- int _field254C;
- int _field254E;
- bool _field2550;
+ bool _tealDead;
+ bool _lightEntered;
+ bool _ghoulTeleported;
Scene3600();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -765,11 +742,11 @@ public:
SpeakerQuinn3700 _quinnSpeaker;
SpeakerSeeker3700 _seekerSpeaker;
SpeakerMiranda3700 _mirandaSpeaker;
- SceneActor _actor1;
- SceneActor _actor2;
- SceneActor _actor3;
- SceneActor _actor4;
- SceneActor _actor5;
+ SceneActor _quinn;
+ SceneActor _seeker;
+ SceneActor _miranda;
+ SceneActor _webbster;
+ SceneActor _teleportPad;
SequenceManager _sequenceManager;
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -778,43 +755,43 @@ public:
};
class Scene3800 : public SceneExt {
- class Exit1 : public SceneExit {
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit4 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
public:
- SceneObject _object1;
- SceneObject _object2;
- SceneActor _actor1;
- NamedHotspot _item1;
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
- Exit4 _exit4;
- Rect _rect1;
+ SceneObject _balloon;
+ SceneObject _harness;
+ SceneActor _quinnShadow;
+ NamedHotspot _background;
+ NorthExit _northExit;
+ EastExit _eastExit;
+ SouthExit _southExit;
+ WestExit _westExit;
+ Rect _skylineRect;
SequenceManager _sequenceManager1;
- int _field412;
+ int _desertDirection;
Scene3800();
- void initScene3800();
- void sub110BBD();
+ void initExits();
+ void enterArea();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
@@ -823,22 +800,22 @@ public:
};
class Scene3900 : public SceneExt {
- class Exit1 : public SceneExit {
+ class NorthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit2 : public SceneExit {
+ class EastExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit3 : public SceneExit {
+ class SouthExit : public SceneExit {
public:
virtual void changeScene();
};
- class Exit4 : public SceneExit {
+ class WestExit : public SceneExit {
public:
virtual void changeScene();
};
@@ -848,14 +825,14 @@ class Scene3900 : public SceneExt {
virtual void changeScene();
};
public:
- SceneActor _actor1;
- NamedHotspot _item1;
- Exit1 _exit1;
- Exit2 _exit2;
- Exit3 _exit3;
- Exit4 _exit4;
- Exit5 _exit5;
- Rect _rect1;
+ SceneActor _quinnShadow;
+ NamedHotspot _background;
+ NorthExit _northExit;
+ EastExit _eastExit;
+ SouthExit _southExit;
+ WestExit _westExit;
+ Exit5 _westEnterForest;
+ Rect _skylineRect;
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp
index da1449efdf..675511ac10 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.cpp
+++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp
@@ -36,40 +36,131 @@ namespace Ringworld2 {
VisualSpeaker::VisualSpeaker(): Speaker() {
_delayAmount = 0;
+ _voiceDelayAmount = 0;
_frameNumber = R2_GLOBALS._events.getFrameNumber();
_color1 = 8;
_color2 = 0;
_displayMode = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
+
+ _object2 = nullptr;
+ _fieldF8 = 0;
+ _soundId = 0;
+ _removeObject = false;
+ _numFrames = 0;
+ _voiceFrameNumber = 0;
}
void VisualSpeaker::remove() {
+ _numFrames = 0;
+ _delayAmount = 0;
+ R2_GLOBALS._playStream.stop();
+
if (_object2) {
if (_fieldF8) {
_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: Handle _field18 if used in Action. It looks only used in the original in remove()
+ // _action->_field18 = 1;
+ if (_speakerMode == 0xff)
+ stopSpeaking();
+
+ _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) {
+ setVoiceFrame(1);
+ }
+ } else if (_action && _object2) {
+ _action->setDelay(1);
+ _sceneText.remove();
+
+ R2_GLOBALS._playStream.stop();
+ }
+}
+
+void VisualSpeaker::dispatch() {
+ uint32 frameNumber = R2_GLOBALS._events.getFrameNumber();
+ assert(_action);
+
+ // 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 (_voiceDelayAmount) {
+ if (frameNumber >= _voiceFrameNumber) {
+ _voiceDelayAmount = _voiceDelayAmount - (frameNumber - _voiceFrameNumber);
+ _voiceFrameNumber = frameNumber;
+
+ if (_voiceDelayAmount <= 0) {
+ _voiceDelayAmount = 0;
+ if (R2_GLOBALS._playStream.play(_soundId, 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)) {
+ // Don't bother waiting for a mouse click to start the next speech segment
+ _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(_voiceDelayAmount);
+ s.syncAsUint32LE(_voiceFrameNumber);
}
void VisualSpeaker::setText(const Common::String &msg) {
@@ -127,13 +218,12 @@ void VisualSpeaker::setText(const Common::String &msg) {
_sceneText._textMode = _textMode;
_sceneText.setup(s);
- //_sceneText.clone();
-
_sceneText.setPosition(_textPos);
_sceneText.fixPriority(256);
// If subtitles are turned off, don't show the text
- if (!(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) {
+ if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) &&
+ !(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) {
_sceneText.hide();
}
@@ -159,25 +249,29 @@ 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 {
if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) && _soundId) {
- if (!R2_GLOBALS._playStream.play(_soundId, NULL))
+ if (!R2_GLOBALS._playStream.play(_soundId, NULL)) {
+ // Couldn't play voice, so fall back on showing text
_sceneText.show();
+ } else {
+ _numFrames = 2;
+ _soundId = 0;
+ }
}
}
}
-void VisualSpeaker::proc16() {
+void VisualSpeaker::stopSpeaking() {
R2_GLOBALS._playStream.stop();
- _fieldF6 = 0;
+ _speakerMode = 0;
_object1.remove();
- assert(_object2);
- _object2->show();
+ if (_object2)
+ _object2->show();
_object2 = NULL;
_fieldF8 = 0;
}
@@ -187,6 +281,11 @@ void VisualSpeaker::setFrame(int numFrames) {
_frameNumber = R2_GLOBALS._events.getFrameNumber();
}
+void VisualSpeaker::setVoiceFrame(int numFrames) {
+ _voiceDelayAmount = numFrames;
+ _voiceFrameNumber = R2_GLOBALS._events.getFrameNumber();
+}
+
void VisualSpeaker::setDelay(int delay) {
_delayAmount = delay;
_frameNumber = R2_GLOBALS._events.getFrameNumber();
@@ -211,7 +310,7 @@ SpeakerCaptain3210::SpeakerCaptain3210() {
_speakerName = "Captain";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -219,12 +318,12 @@ SpeakerCaptain3210::SpeakerCaptain3210() {
_numFrames = 0;
}
-void SpeakerCaptain3210::proc15() {
- int v = _fieldF6;
+void SpeakerCaptain3210::animateSpeaker() {
+ int v = _speakerMode;
Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_captain;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -250,7 +349,7 @@ SpeakerCaretaker2450::SpeakerCaretaker2450() {
_speakerName = "CARETAKER";
_color1 = 43;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -266,7 +365,7 @@ SpeakerChief1100::SpeakerChief1100() {
_speakerName = "CHIEF";
_color1 = 8;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -274,12 +373,12 @@ SpeakerChief1100::SpeakerChief1100() {
_numFrames = 0;
}
-void SpeakerChief1100::proc15() {
- int v = _fieldF6;
+void SpeakerChief1100::animateSpeaker() {
+ int v = _speakerMode;
Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor18;
+ _object2 = &scene->_chief;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -324,7 +423,7 @@ SpeakerGuard::SpeakerGuard() {
_speakerName = "GUARD";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -332,12 +431,12 @@ SpeakerGuard::SpeakerGuard() {
_numFrames = 0;
}
-void SpeakerGuard2800::proc15() {
- int v = _fieldF6;
- Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
+void SpeakerGuard2800::animateSpeaker() {
+ int v = _speakerMode;
+ Scene2800 *scene = (Scene2800 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_guard;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -364,7 +463,7 @@ SpeakerJocko::SpeakerJocko() {
_speakerName = "Jocko";
_color1 = 45;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -372,12 +471,12 @@ SpeakerJocko::SpeakerJocko() {
_numFrames = 0;
}
-void SpeakerJocko3200::proc15() {
- int v = _fieldF6;
+void SpeakerJocko3200::animateSpeaker() {
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_jocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -395,12 +494,12 @@ void SpeakerJocko3200::proc15() {
}
}
-void SpeakerJocko3220::proc15() {
- int v = _fieldF6;
+void SpeakerJocko3220::animateSpeaker() {
+ int v = _speakerMode;
Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_jocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -418,12 +517,12 @@ void SpeakerJocko3220::proc15() {
}
}
-void SpeakerJocko3230::proc15() {
- int v = _fieldF6;
+void SpeakerJocko3230::animateSpeaker() {
+ int v = _speakerMode;
Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_jocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -449,7 +548,7 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() {
_speakerName = "MIRANDA";
_color1 = 154;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -457,11 +556,11 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() {
_numFrames = 0;
}
-void SpeakerMiranda300::proc15() {
- int v = _fieldF6;
+void SpeakerMiranda300::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA) {
_object2 = &R2_GLOBALS._player;
} else {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -497,12 +596,12 @@ void SpeakerMiranda300::proc15() {
}
}
-void SpeakerMiranda1625::proc15() {
- int v = _fieldF6;
+void SpeakerMiranda1625::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor3;
+ _object2 = &scene->_mirandaMouth;
_object2->hide();
_object1.postInit();
_object1.setPosition(Common::Point(196, 65));
@@ -520,8 +619,8 @@ void SpeakerMiranda1625::proc15() {
}
}
-void SpeakerMiranda3255::proc15() {
- int v = _fieldF6;
+void SpeakerMiranda3255::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -541,25 +640,25 @@ void SpeakerMiranda3255::proc15() {
}
}
-void SpeakerMiranda3375::proc15() {
+void SpeakerMiranda3375::animateSpeaker() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
- if (scene->_actor1._position.y != 163)
+ if (scene->_companion1._position.y != 163)
R2_GLOBALS._player.setStrip(8);
else
R2_GLOBALS._player.setStrip(2);
@@ -591,22 +690,22 @@ void SpeakerMiranda3375::proc15() {
}
}
-void SpeakerMiranda3385::proc15() {
+void SpeakerMiranda3385::animateSpeaker() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3375)
@@ -640,22 +739,22 @@ void SpeakerMiranda3385::proc15() {
}
}
-void SpeakerMiranda3395::proc15() {
+void SpeakerMiranda3395::animateSpeaker() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3385)
@@ -690,22 +789,22 @@ void SpeakerMiranda3395::proc15() {
}
}
-void SpeakerMiranda3400::proc15() {
+void SpeakerMiranda3400::animateSpeaker() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -721,12 +820,12 @@ void SpeakerMiranda3400::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4051, 5, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4050, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -734,22 +833,22 @@ void SpeakerMiranda3400::proc15() {
}
}
-void SpeakerMiranda3600::proc15() {
+void SpeakerMiranda3600::animateSpeaker() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3)
+ if (R2_GLOBALS._player._characterIndex == R2_MIRANDA)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor12;
+ _object2 = &scene->_miranda;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -780,13 +879,13 @@ void SpeakerMiranda3600::proc15() {
}
}
-void SpeakerMiranda3700::proc15() {
+void SpeakerMiranda3700::animateSpeaker() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_miranda;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -806,25 +905,25 @@ void SpeakerMiranda3700::proc15() {
break;
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor1.setup(10, 6, 1);
- scene->_actor2.setup(20, 5, 1);
+ scene->_quinn.setup(10, 6, 1);
+ scene->_seeker.setup(20, 5, 1);
_object2->setup(30, 1, 1);
- scene->_actor4.setup(40, 1, 1);
+ scene->_webbster.setup(40, 1, 1);
_object1.setup(4050, 5, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor3.setup(30, 8, 1);
+ scene->_miranda.setup(30, 8, 1);
_object1.setup(4052, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor2.setup(20, 1, 1);
- scene->_actor3.setup(30, 1, 1);
+ scene->_seeker.setup(20, 1, 1);
+ scene->_miranda.setup(30, 1, 1);
_object1.setup(4051, 7, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -840,7 +939,7 @@ SpeakerNej::SpeakerNej() {
_speakerName = "NEJ";
_color1 = 171;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -848,12 +947,12 @@ SpeakerNej::SpeakerNej() {
_numFrames = 0;
}
-void SpeakerNej2700::proc15() {
- int v = _fieldF6;
+void SpeakerNej2700::animateSpeaker() {
+ int v = _speakerMode;
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_nej;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -883,12 +982,12 @@ void SpeakerNej2700::proc15() {
}
}
-void SpeakerNej2750::proc15() {
- int v = _fieldF6;
+void SpeakerNej2750::animateSpeaker() {
+ int v = _speakerMode;
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_nej;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -915,12 +1014,12 @@ void SpeakerNej2750::proc15() {
}
}
-void SpeakerNej2800::proc15() {
- int v = _fieldF6;
- Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
+void SpeakerNej2800::animateSpeaker() {
+ int v = _speakerMode;
+ Scene2800 *scene = (Scene2800 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_nej;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -948,7 +1047,7 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() {
_speakerName = "PHARISHA";
_color1 = 151;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -956,12 +1055,12 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() {
_numFrames = 0;
}
-void SpeakerPharisha2435::proc15() {
- int v = _fieldF6;
+void SpeakerPharisha2435::animateSpeaker() {
+ int v = _speakerMode;
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_astor;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -984,7 +1083,7 @@ SpeakerPrivate3210::SpeakerPrivate3210() {
_speakerName = "Private";
_color1 = 45;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -992,12 +1091,12 @@ SpeakerPrivate3210::SpeakerPrivate3210() {
_numFrames = 0;
}
-void SpeakerPrivate3210::proc15() {
- int v = _fieldF6;
+void SpeakerPrivate3210::animateSpeaker() {
+ int v = _speakerMode;
Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_private;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1023,7 +1122,7 @@ SpeakerProtector3600::SpeakerProtector3600() {
_speakerName = "Protector";
_color1 = 170;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1031,17 +1130,17 @@ SpeakerProtector3600::SpeakerProtector3600() {
_numFrames = 0;
}
-void SpeakerProtector3600::proc15() {
- int v = _fieldF6;
+void SpeakerProtector3600::animateSpeaker() {
+ int v = _speakerMode;
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor13;
+ _object2 = &scene->_protector;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
@@ -1084,7 +1183,7 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() {
_speakerName = "QUINN";
_color1 = 60;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1092,13 +1191,14 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() {
_numFrames = 0;
}
-void SpeakerQuinn300::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn300::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 300);
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
_object2 = &scene->_quinn;
}
@@ -1106,9 +1206,6 @@ void SpeakerQuinn300::proc15() {
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
-
- if (_object2->_mover)
- _object2->addMover(NULL);
}
if (v == 0) {
@@ -1133,24 +1230,72 @@ void SpeakerQuinn300::proc15() {
case 308:
_object1.setup(308, 5, 1);
break;
+ default:
+ break;
+ }
+
+ _object1.animate(ANIM_MODE_5, this);
+ }
+}
+
+void SpeakerQuinn500::animateSpeaker() {
+ int v = _speakerMode;
+
+ if (!_object2) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
+ _object2 = &R2_GLOBALS._player;
+ } else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 500);
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+ _object2 = &scene->_seeker;
+ }
+
+ _object2->hide();
+
+ _object1.postInit();
+ _object1._effect = _object2->_effect;
+ _object1._shade = _object2->_shade;
+ _object1.setPosition(_object2->_position);
+
+ if (_object2->_mover)
+ _object2->addMover(NULL);
+ }
+
+ if (v == 0) {
+ _object1.animate(ANIM_MODE_2, NULL);
+ } else {
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+
+ switch (_object2->_visage) {
+ case 10:
+ _object1.setup(4021, (v == 1) ? 5 : 7, 1);
+ break;
+
+ case 1500:
+ _object1.setup(4021, (v == 1) ? 1 : 3, 1);
+ break;
+
+ default:
+ break;
}
_object1.animate(ANIM_MODE_5, this);
}
}
-void SpeakerQuinn1100::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn1100::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
if (v == 0)
return;
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 1100);
Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor16;
+ _object2 = &scene->_seeker;
}
_object2->hide();
@@ -1187,15 +1332,16 @@ void SpeakerQuinn1100::proc15() {
}
}
-void SpeakerQuinn2435::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn2435::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 2435);
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion;
}
_object2->hide();
@@ -1213,15 +1359,16 @@ void SpeakerQuinn2435::proc15() {
}
}
-void SpeakerQuinn2450::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn2450::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 2435);
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion;
}
_object2->hide();
@@ -1241,8 +1388,8 @@ void SpeakerQuinn2450::proc15() {
}
}
-void SpeakerQuinn2700::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn2700::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1272,8 +1419,8 @@ void SpeakerQuinn2700::proc15() {
}
}
-void SpeakerQuinn2750::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn2750::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1294,7 +1441,7 @@ void SpeakerQuinn2750::proc15() {
_object1.setup(4022, 5, 1);
break;
case 2752:
- _object1.setup(2752, 1, 1);
+ _object1.setup(2752, 3, 1);
break;
default:
break;
@@ -1303,8 +1450,8 @@ void SpeakerQuinn2750::proc15() {
}
}
-void SpeakerQuinn2800::proc15() {
- int v = _fieldF6;
+void SpeakerQuinn2800::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1342,13 +1489,13 @@ void SpeakerQuinn2800::proc15() {
}
}
-void SpeakerQuinn3255::proc15() {
+void SpeakerQuinn3255::animateSpeaker() {
Scene3255 *scene = (Scene3255 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor4;
+ _object2 = &scene->_quinn;
_object2->hide();
_object1.postInit();
_object1._effect = _object2->_effect;
@@ -1365,27 +1512,27 @@ void SpeakerQuinn3255::proc15() {
}
}
-void SpeakerQuinn3375::proc15() {
+void SpeakerQuinn3375::animateSpeaker() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_object2 = &R2_GLOBALS._player;
- else if (R2_GLOBALS._player._characterIndex == 2)
- _object2 = &scene->_actor1;
+ else if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _object2 = &scene->_companion1;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
- if (scene->_actor1._position.y != 163)
+ if (scene->_companion1._position.y != 163)
R2_GLOBALS._player.setStrip(8);
else
R2_GLOBALS._player.setStrip(2);
@@ -1416,24 +1563,24 @@ void SpeakerQuinn3375::proc15() {
}
}
-void SpeakerQuinn3385::proc15() {
+void SpeakerQuinn3385::animateSpeaker() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_object2 = &R2_GLOBALS._player;
- else if (R2_GLOBALS._player._characterIndex == 2)
- _object2 = &scene->_actor1;
+ else if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _object2 = &scene->_companion1;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3375)
@@ -1458,7 +1605,7 @@ void SpeakerQuinn3385::proc15() {
break;
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object1.setup(4010, 3, 1);
else
_object1.setup(4010, 5, 1);
@@ -1471,24 +1618,24 @@ void SpeakerQuinn3385::proc15() {
}
}
-void SpeakerQuinn3395::proc15() {
+void SpeakerQuinn3395::animateSpeaker() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_object2 = &R2_GLOBALS._player;
- else if (R2_GLOBALS._player._characterIndex == 2)
- _object2 = &scene->_actor1;
+ else if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _object2 = &scene->_companion1;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3385)
@@ -1513,7 +1660,7 @@ void SpeakerQuinn3395::proc15() {
break;
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object1.setup(4010, 3, 1);
else
_object1.setup(4010, 5, 1);
@@ -1526,24 +1673,24 @@ void SpeakerQuinn3395::proc15() {
}
}
-void SpeakerQuinn3400::proc15() {
+void SpeakerQuinn3400::animateSpeaker() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_object2 = &R2_GLOBALS._player;
- else if (R2_GLOBALS._player._characterIndex == 2)
- _object2 = &scene->_actor1;
+ else if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
+ _object2 = &scene->_companion1;
else
- _object2 = &scene->_actor2;
+ _object2 = &scene->_companion2;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
if (_object2->_mover)
@@ -1562,12 +1709,12 @@ void SpeakerQuinn3400::proc15() {
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4010, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4012, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -1575,21 +1722,21 @@ void SpeakerQuinn3400::proc15() {
}
}
-void SpeakerQuinn3600::proc15() {
+void SpeakerQuinn3600::animateSpeaker() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 1)
+ if (R2_GLOBALS._player._characterIndex == R2_QUINN)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor10;
+ _object2 = &scene->_quinn;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -1626,28 +1773,28 @@ 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);
+ scene->_miranda.setup(30, 1, 1);
R2_GLOBALS._sound2.play(44);
break;
case 3:
- scene->_actor3.setup(30, 1, 1);
+ scene->_miranda.setup(30, 1, 1);
break;
default:
- scene->_actor3.setup(30, 7, 1);
+ scene->_miranda.setup(30, 7, 1);
break;
}
VisualSpeaker::setText(msg);
}
-void SpeakerQuinn3700::proc15() {
+void SpeakerQuinn3700::animateSpeaker() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_quinn;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1668,24 +1815,24 @@ void SpeakerQuinn3700::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
R2_GLOBALS._sound2.stop();
- scene->_actor1.setup(10, 4, 1);
- scene->_actor3.setup(30, 7, 1);
+ scene->_quinn.setup(10, 4, 1);
+ scene->_miranda.setup(30, 7, 1);
_object1.setup(3701, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor2.setup(20, 1, 1);
- scene->_actor3.setup(30, 1, 1);
- _object1.setup(3701, 2, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ scene->_seeker.setup(20, 1, 1);
+ scene->_miranda.setup(30, 1, 1);
+ _object1.setup(3702, 1, 1);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor1.setup(10, 2, 1);
- scene->_actor3.setup(30, 1, 1);
+ scene->_quinn.setup(10, 2, 1);
+ scene->_miranda.setup(30, 1, 1);
_object1.setup(4011, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -1697,17 +1844,8 @@ void SpeakerQuinn3700::proc15() {
// Classes related to QUINNL
//----------------------------------------------------------------------------
-SpeakerQuinnL::SpeakerQuinnL(): VisualSpeaker() {
+SpeakerQuinnL::SpeakerQuinnL(): SpeakerQuinn() {
_speakerName = "QUINNL";
- _color1 = 35;
- _color2 = 0;
- _fieldF6 = 0;
- _textWidth = 300;
- _hideObjects = false;
- _object2 = NULL;
- _displayMode = 1;
- _numFrames = 0;
- _fontNumber = 10;
}
//----------------------------------------------------------------------------
@@ -1718,7 +1856,7 @@ SpeakerRalf3245::SpeakerRalf3245() {
_speakerName = "Ralf";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1726,12 +1864,12 @@ SpeakerRalf3245::SpeakerRalf3245() {
_numFrames = 0;
}
-void SpeakerRalf3245::proc15() {
- int v = _fieldF6;
+void SpeakerRalf3245::animateSpeaker() {
+ int v = _speakerMode;
Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_ralf;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1770,7 +1908,7 @@ SpeakerRocko::SpeakerRocko() {
_speakerName = "Rocko";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1778,12 +1916,12 @@ SpeakerRocko::SpeakerRocko() {
_numFrames = 0;
}
-void SpeakerRocko3200::proc15() {
- int v = _fieldF6;
+void SpeakerRocko3200::animateSpeaker() {
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_rocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1801,12 +1939,12 @@ void SpeakerRocko3200::proc15() {
}
}
-void SpeakerRocko3220::proc15() {
- int v = _fieldF6;
+void SpeakerRocko3220::animateSpeaker() {
+ int v = _speakerMode;
Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_rocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1824,12 +1962,12 @@ void SpeakerRocko3220::proc15() {
}
}
-void SpeakerRocko3230::proc15() {
- int v = _fieldF6;
+void SpeakerRocko3230::animateSpeaker() {
+ int v = _speakerMode;
Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_rocko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -1855,7 +1993,7 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() {
_speakerName = "SEEKER";
_color1 = 35;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1863,13 +2001,13 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() {
_numFrames = 0;
}
-void SpeakerSeeker300::proc15() {
- int v = _fieldF6;
+void SpeakerSeeker300::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_object2 = &R2_GLOBALS._player;
- } else {
+ } else {assert(R2_GLOBALS._sceneManager._sceneNumber == 300);
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
_object2 = &scene->_seeker;
}
@@ -1899,18 +2037,56 @@ void SpeakerSeeker300::proc15() {
}
}
-void SpeakerSeeker1100::proc15() {
- int v = _fieldF6;
+void SpeakerSeeker500::animateSpeaker() {
+ int v = _speakerMode;
+
+ if (!_object2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
+ _object2 = &R2_GLOBALS._player;
+ } else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 500);
+ Scene500 *scene = (Scene500 *)R2_GLOBALS._sceneManager._scene;
+ _object2 = &scene->_seeker;
+ }
+
+ _object2->hide();
+ _object1.postInit();
+
+ _object1._effect = _object2->_effect;
+ _object1._shade = _object2->_shade;
+ _object1.setPosition(_object2->_position);
+
+ if (_object2->_mover)
+ _object2->addMover(NULL);
+ }
+
+ if (v == 0) {
+ _object1.animate(ANIM_MODE_2, NULL);
+ } else {
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+
+ if (v == 1)
+ _object1.setup(4041, 3, 1);
+ else
+ _object1.setup(4041, 1, 1);
+
+ _object1.animate(ANIM_MODE_5, this);
+ }
+}
+
+void SpeakerSeeker1100::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
if (v == 0)
return;
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 1100);
Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor16;
+ _object2 = &scene->_seeker;
}
_object2->hide();
@@ -1958,15 +2134,16 @@ void SpeakerSeeker1100::proc15() {
}
}
-void SpeakerSeeker1900::proc15() {
- int v = _fieldF6;
+void SpeakerSeeker1900::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 1900);
Scene1900 *scene = (Scene1900 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion;
}
_object2->hide();
@@ -1988,15 +2165,16 @@ void SpeakerSeeker1900::proc15() {
}
}
-void SpeakerSeeker2435::proc15() {
- int v = _fieldF6;
+void SpeakerSeeker2435::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 2435);
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion;
}
_object2->hide();
@@ -2014,15 +2192,16 @@ void SpeakerSeeker2435::proc15() {
}
}
-void SpeakerSeeker2450::proc15() {
- int v = _fieldF6;
+void SpeakerSeeker2450::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2) {
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
_object2 = &R2_GLOBALS._player;
} else {
+ assert(R2_GLOBALS._sceneManager._sceneNumber == 2450);
Scene2450 *scene = (Scene2450 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion;
}
_object2->hide();
@@ -2039,25 +2218,25 @@ void SpeakerSeeker2450::proc15() {
}
}
-void SpeakerSeeker3375::proc15() {
+void SpeakerSeeker3375::animateSpeaker() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion1;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
- if (scene->_actor1._position.y != 163)
+ if (scene->_companion1._position.y != 163)
R2_GLOBALS._player.setStrip(8);
else
R2_GLOBALS._player.setStrip(2);
@@ -2088,22 +2267,22 @@ void SpeakerSeeker3375::proc15() {
}
}
-void SpeakerSeeker3385::proc15() {
+void SpeakerSeeker3385::animateSpeaker() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion1;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3375)
@@ -2137,22 +2316,22 @@ void SpeakerSeeker3385::proc15() {
}
}
-void SpeakerSeeker3395::proc15() {
+void SpeakerSeeker3395::animateSpeaker() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion1;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3385)
@@ -2186,22 +2365,22 @@ void SpeakerSeeker3395::proc15() {
}
}
-void SpeakerSeeker3400::proc15() {
+void SpeakerSeeker3400::animateSpeaker() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor1;
+ _object2 = &scene->_companion1;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -2217,27 +2396,27 @@ void SpeakerSeeker3400::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4031, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4031, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4030, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 4:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4031, 7, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 5:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4033, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -2245,22 +2424,22 @@ void SpeakerSeeker3400::proc15() {
}
}
-void SpeakerSeeker3600::proc15() {
+void SpeakerSeeker3600::animateSpeaker() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 2)
+ if (R2_GLOBALS._player._characterIndex == R2_SEEKER)
_object2 = &R2_GLOBALS._player;
else
- _object2 = &scene->_actor11;
+ _object2 = &scene->_seeker;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -2295,22 +2474,23 @@ 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);
+ scene->_miranda.setup(30, 8, 1);
} else {
- scene->_actor3.setup(30, 2, 1);
+ scene->_miranda.setup(30, 2, 1);
}
+
VisualSpeaker::setText(msg);
}
-void SpeakerSeeker3700::proc15() {
+void SpeakerSeeker3700::animateSpeaker() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_seeker;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2331,19 +2511,19 @@ void SpeakerSeeker3700::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
R2_GLOBALS._sound2.stop();
- scene->_actor1.setup(10, 8, 1);
- scene->_actor2.setup(20, 7, 1);
- scene->_actor3.setup(30, 8, 1);
+ scene->_quinn.setup(10, 8, 1);
+ scene->_seeker.setup(20, 7, 1);
+ scene->_miranda.setup(30, 8, 1);
_object1.setup(3701, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
- scene->_actor1.setup(10, 2, 1);
- scene->_actor2.setup(20, 1, 1);
- scene->_actor3.setup(30, 1, 1);
+ scene->_quinn.setup(10, 2, 1);
+ scene->_seeker.setup(20, 1, 1);
+ scene->_miranda.setup(30, 1, 1);
_object1.setup(4031, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -2355,17 +2535,8 @@ void SpeakerSeeker3700::proc15() {
// Classes related to SEEKERL
//----------------------------------------------------------------------------
-SpeakerSeekerL::SpeakerSeekerL(): VisualSpeaker() {
+SpeakerSeekerL::SpeakerSeekerL(): SpeakerSeeker() {
_speakerName = "SEEKERL";
- _color1 = 35;
- _color2 = 0;
- _fieldF6 = 0;
- _textWidth = 300;
- _hideObjects = false;
- _object2 = NULL;
- _displayMode = 1;
- _numFrames = 0;
- _fontNumber = 10;
}
//----------------------------------------------------------------------------
@@ -2376,7 +2547,7 @@ SpeakerSocko3200::SpeakerSocko3200() {
_speakerName = "Socko";
_color1 = 10;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2384,12 +2555,12 @@ SpeakerSocko3200::SpeakerSocko3200() {
_numFrames = 0;
}
-void SpeakerSocko3200::proc15() {
- int v = _fieldF6;
+void SpeakerSocko3200::animateSpeaker() {
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_socko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2411,11 +2582,11 @@ void SpeakerSocko3200::proc15() {
// Classes related to SOLDIER
//----------------------------------------------------------------------------
-SpeakerSoldier::SpeakerSoldier(int colour) {
+SpeakerSoldier::SpeakerSoldier(int color) {
_speakerName = "SOLDIER";
- _color1 = colour;
+ _color1 = color;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2423,8 +2594,8 @@ SpeakerSoldier::SpeakerSoldier(int colour) {
_numFrames = 0;
}
-void SpeakerSoldier300::proc15() {
- int v = _fieldF6;
+void SpeakerSoldier300::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -2455,7 +2626,7 @@ SpeakerTeal::SpeakerTeal(): VisualSpeaker() {
_speakerName = "TEAL";
_color1 = 22;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2467,8 +2638,43 @@ SpeakerTealMode7::SpeakerTealMode7(): SpeakerTeal() {
_displayMode = 7;
}
-void SpeakerTeal300::proc15() {
- int v = _fieldF6;
+void SpeakerTeal180::animateSpeaker() {
+ int v = _speakerMode;
+
+ if (!_object2) {
+ Scene180 *scene = (Scene180 *)R2_GLOBALS._sceneManager._scene;
+ _object2 = &scene->_teal;
+ _object2->hide();
+
+ _object1.postInit();
+ _object1.setPosition(_object2->_position);
+
+ if (_object2->_mover)
+ _object2->addMover(NULL);
+ }
+
+ switch (v) {
+ case 0:
+ _object1.animate(ANIM_MODE_2, NULL);
+ break;
+ case 1:
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+ _object1.setup(75, 5, 1);
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+ _object1.setup(77, 1, 1);
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ default:
+ signal();
+ break;
+ }
+}
+
+void SpeakerTeal300::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -2491,12 +2697,12 @@ void SpeakerTeal300::proc15() {
}
}
-void SpeakerTeal1625::proc15() {
- int v = _fieldF6;
+void SpeakerTeal1625::animateSpeaker() {
+ int v = _speakerMode;
if (!_object2) {
Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene;
- _object2 = &scene->_actor2;
+ _object2 = &scene->_tealHead;
_object2->hide();
_object1.postInit();
@@ -2515,12 +2721,12 @@ void SpeakerTeal1625::proc15() {
}
}
-void SpeakerTeal3240::proc15() {
- int v = _fieldF6;
+void SpeakerTeal3240::animateSpeaker() {
+ int v = _speakerMode;
Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor1;
+ _object2 = &scene->_teal;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2538,17 +2744,17 @@ void SpeakerTeal3240::proc15() {
}
}
-void SpeakerTeal3400::proc15() {
+void SpeakerTeal3400::animateSpeaker() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor4;
+ _object2 = &scene->_teal;
_object2->hide();
_object1.postInit();
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -2561,8 +2767,8 @@ void SpeakerTeal3400::proc15() {
if (scene ->_sceneMode == 3305) {
R2_GLOBALS._player.setStrip(6);
- scene->_actor1.setStrip(6);
- scene->_actor2.setStrip(6);
+ scene->_companion1.setStrip(6);
+ scene->_companion2.setStrip(6);
}
switch (v) {
@@ -2572,22 +2778,22 @@ void SpeakerTeal3400::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4107, 5, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4107, 1, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4107, 7, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 4:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4107, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -2595,18 +2801,18 @@ void SpeakerTeal3400::proc15() {
}
}
-void SpeakerTeal3600::proc15() {
+void SpeakerTeal3600::animateSpeaker() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor5;
+ _object2 = &scene->_teal;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -2659,7 +2865,7 @@ SpeakerTomko3245::SpeakerTomko3245() {
_speakerName = "Tomko";
_color1 = 10;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2667,12 +2873,12 @@ SpeakerTomko3245::SpeakerTomko3245() {
_numFrames = 0;
}
-void SpeakerTomko3245::proc15() {
- int v = _fieldF6;
+void SpeakerTomko3245::animateSpeaker() {
+ int v = _speakerMode;
Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_tomko;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2707,11 +2913,11 @@ void SpeakerTomko3245::proc15() {
// Classes related to WEBBSTER
//----------------------------------------------------------------------------
-SpeakerWebbster::SpeakerWebbster(int colour) {
+SpeakerWebbster::SpeakerWebbster(int color) {
_speakerName = "WEBBSTER";
- _color1 = colour;
+ _color1 = color;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2719,12 +2925,53 @@ SpeakerWebbster::SpeakerWebbster(int colour) {
_numFrames = 0;
}
-void SpeakerWebbster3240::proc15() {
- int v = _fieldF6;
+void SpeakerWebbster180::animateSpeaker() {
+ Scene180 *scene = (Scene180 *)R2_GLOBALS._sceneManager._scene;
+
+ int v = _speakerMode;
+
+ if (!_object2) {
+ _object2 = &scene->_webbster;
+ _object2->hide();
+ _object1.postInit();
+ _object1.setPosition(_object2->_position);
+ _object1._numFrames = 6;
+
+ if (_object2->_mover)
+ _object2->addMover(NULL);
+ }
+
+ switch (v) {
+ case 0:
+ _object1.animate(ANIM_MODE_2, NULL);
+ break;
+ case 1:
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+ _object1.setup(75, 7, 1);
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+ _object1.setup(76, 4, 1);
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ ((SceneItem *)_action)->_sceneRegionId = 0;
+ _object1.setup(76, 6, 1);
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ default:
+ signal();
+ break;
+ }
+}
+
+void SpeakerWebbster3240::animateSpeaker() {
+ int v = _speakerMode;
Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
- _object2 = &scene->_actor2;
+ _object2 = &scene->_webbster;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2742,21 +2989,21 @@ void SpeakerWebbster3240::proc15() {
}
}
-void SpeakerWebbster3375::proc15() {
+void SpeakerWebbster3375::animateSpeaker() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_webbster;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
- if (scene->_actor1._position.y != 163)
+ if (scene->_companion1._position.y != 163)
R2_GLOBALS._player.setStrip(8);
else
R2_GLOBALS._player.setStrip(2);
@@ -2786,18 +3033,18 @@ void SpeakerWebbster3375::proc15() {
}
}
-void SpeakerWebbster3385::proc15() {
+void SpeakerWebbster3385::animateSpeaker() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_webbster;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3375)
@@ -2830,18 +3077,18 @@ void SpeakerWebbster3385::proc15() {
}
}
-void SpeakerWebbster3395::proc15() {
+void SpeakerWebbster3395::animateSpeaker() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_webbster;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
if (R2_GLOBALS._sceneManager._previousScene == 3385)
@@ -2874,18 +3121,18 @@ void SpeakerWebbster3395::proc15() {
}
}
-void SpeakerWebbster3400::proc15() {
+void SpeakerWebbster3400::animateSpeaker() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_actor3;
+ _object2 = &scene->_webbster;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
_object1._numFrames = 7;
- _object1._effect = 1;
+ _object1._effect = EFFECT_SHADED;
_object1.changeZoom(-1);
R2_GLOBALS._player.disableControl();
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
@@ -2901,17 +3148,17 @@ void SpeakerWebbster3400::proc15() {
case 1:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4110, 5, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 2:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4110, 7, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
case 3:
((SceneItem *)_action)->_sceneRegionId = 0;
_object1.setup(4110, 3, 1);
- _object1.animate(ANIM_MODE_5, NULL);
+ _object1.animate(ANIM_MODE_5, this);
break;
default:
signal();
@@ -2921,11 +3168,11 @@ void SpeakerWebbster3400::proc15() {
//----------------------------------------------------------------------------
-SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() {
+SpeakerDutyOfficer180::SpeakerDutyOfficer180(): VisualSpeaker() {
_speakerName = "DUTYOFFICER";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2933,13 +3180,13 @@ SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() {
_numFrames = 0;
}
-void SpeakerDutyOfficer::proc15() {
+void SpeakerDutyOfficer180::animateSpeaker() {
Scene180 *scene = (Scene180 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- _object2 = &scene->_object2;
+ _object2 = &scene->_dutyOfficer;
_object2->hide();
_object1.postInit();
_object1.setPosition(_object2->_position);
@@ -2953,7 +3200,7 @@ void SpeakerDutyOfficer::proc15() {
_object1.animate(ANIM_MODE_2, NULL);
break;
case 1:
- _action = NULL;
+ _action->_action = NULL;
_object1.setup(76, 2, 1);
_object1.animate(ANIM_MODE_5, this);
break;
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.h b/engines/tsage/ringworld2/ringworld2_speakers.h
index fa2946d56c..d70652ff97 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.h
+++ b/engines/tsage/ringworld2/ringworld2_speakers.h
@@ -41,24 +41,30 @@ 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 _voiceDelayAmount;
+ uint32 _voiceFrameNumber;
private:
void setFrame(int numFrames);
+ void setVoiceFrame(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();
+ virtual void animateSpeaker() {}
+ virtual void stopSpeaking();
void setDelay(int delay);
};
@@ -77,7 +83,7 @@ public:
SpeakerCaptain3210();
virtual Common::String getClassName() { return "SpeakerCaptain3210"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Caretaker
@@ -96,7 +102,7 @@ public:
SpeakerChief1100();
virtual Common::String getClassName() { return "SpeakerChief1100"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Guard
@@ -110,7 +116,7 @@ public:
class SpeakerGuard2800 : public SpeakerGuard {
public:
virtual Common::String getClassName() { return "SpeakerGuard2800"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Jocko
@@ -124,19 +130,19 @@ public:
class SpeakerJocko3200 : public SpeakerJocko {
public:
virtual Common::String getClassName() { return "SpeakerJocko3200"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerJocko3220 : public SpeakerJocko {
public:
virtual Common::String getClassName() { return "SpeakerJocko3220"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerJocko3230 : public SpeakerJocko {
public:
virtual Common::String getClassName() { return "SpeakerJocko3230"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Miranda
@@ -150,55 +156,55 @@ public:
class SpeakerMiranda300 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda300"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda1625 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda1625"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3255 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3255"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3375 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3375"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3385 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3385"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3395 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3395"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3400 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3400"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3600 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3600"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerMiranda3700 : public SpeakerMiranda {
public:
virtual Common::String getClassName() { return "SpeakerMiranda3700"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Nej
@@ -212,19 +218,19 @@ public:
class SpeakerNej2700 : public SpeakerNej {
public:
virtual Common::String getClassName() { return "SpeakerNej2700"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerNej2750 : public SpeakerNej {
public:
virtual Common::String getClassName() { return "SpeakerNej2750"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerNej2800 : public SpeakerNej {
public:
virtual Common::String getClassName() { return "SpeakerNej2800"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Pharisha
@@ -239,7 +245,7 @@ public:
class SpeakerPharisha2435 : public SpeakerPharisha {
public:
virtual Common::String getClassName() { return "SpeakerPharisha2435"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Private
@@ -249,7 +255,7 @@ public:
SpeakerPrivate3210();
virtual Common::String getClassName() { return "SpeakerPrivate3210"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Protector
@@ -259,7 +265,7 @@ public:
SpeakerProtector3600();
virtual Common::String getClassName() { return "SpeakerProtector3600"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Quinn
@@ -273,91 +279,97 @@ public:
class SpeakerQuinn300 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn300"; }
- virtual void proc15();
+ virtual void animateSpeaker();
+};
+
+class SpeakerQuinn500 : public SpeakerQuinn {
+public:
+ virtual Common::String getClassName() { return "SpeakerQuinn500"; }
+ virtual void animateSpeaker();
};
class SpeakerQuinn1100 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn1100"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn2435 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn2435"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn2450 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn2450"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn2700 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn2700"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn2750 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn2750"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn2800 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn2800"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3255 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3255"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3375 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3375"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3385 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3385"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3395 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3395"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3400 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3400"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3600 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3600"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerQuinn3700 : public SpeakerQuinn {
public:
virtual Common::String getClassName() { return "SpeakerQuinn3700"; }
virtual void setText(const Common::String &msg);
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to QuinnL
-class SpeakerQuinnL : public VisualSpeaker {
+class SpeakerQuinnL : public SpeakerQuinn {
public:
SpeakerQuinnL();
@@ -371,7 +383,7 @@ public:
SpeakerRalf3245();
virtual Common::String getClassName() { return "SpeakerRalf3245"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Rocko
@@ -385,19 +397,19 @@ public:
class SpeakerRocko3200 : public SpeakerRocko {
public:
virtual Common::String getClassName() { return "SpeakerRocko3200"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerRocko3220 : public SpeakerRocko {
public:
virtual Common::String getClassName() { return "SpeakerRocko3220"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerRocko3230 : public SpeakerRocko {
public:
virtual Common::String getClassName() { return "SpeakerRocko3230"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Seeker
@@ -411,73 +423,79 @@ public:
class SpeakerSeeker300 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker300"; }
- virtual void proc15();
+ virtual void animateSpeaker();
+};
+
+class SpeakerSeeker500 : public SpeakerSeeker {
+public:
+ virtual Common::String getClassName() { return "SpeakerSeeker500"; }
+ virtual void animateSpeaker();
};
class SpeakerSeeker1100 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker1100"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker1900 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker1900"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker2435 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker2435"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker2450 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker2450"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3375 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3375"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3385 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3385"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3395 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3395"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3400 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3400"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3600 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3600"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSeeker3700 : public SpeakerSeeker {
public:
virtual Common::String getClassName() { return "SpeakerSeeker3700"; }
virtual void setText(const Common::String &msg);
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to SeekerL
-class SpeakerSeekerL : public VisualSpeaker {
+class SpeakerSeekerL : public SpeakerSeeker {
public:
SpeakerSeekerL();
@@ -491,14 +509,14 @@ public:
SpeakerSocko3200();
virtual Common::String getClassName() { return "SpeakerSocko3200"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Soldier
class SpeakerSoldier : public VisualSpeaker {
public:
- SpeakerSoldier(int colour);
+ SpeakerSoldier(int color);
virtual Common::String getClassName() { return "SpeakerSoldier"; }
};
@@ -506,7 +524,7 @@ class SpeakerSoldier300 : public SpeakerSoldier {
public:
SpeakerSoldier300() : SpeakerSoldier(60) {}
virtual Common::String getClassName() { return "SpeakerSoldier300"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerSoldier1625 : public SpeakerSoldier {
@@ -529,34 +547,40 @@ public:
virtual Common::String getClassName() { return "SpeakerTealMode7"; }
};
+class SpeakerTeal180 : public SpeakerTeal {
+public:
+ virtual Common::String getClassName() { return "SpeakerTeal180"; }
+ virtual void animateSpeaker();
+};
+
class SpeakerTeal300 : public SpeakerTeal {
public:
virtual Common::String getClassName() { return "SpeakerTeal300"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerTeal1625 : public SpeakerTeal {
public:
virtual Common::String getClassName() { return "SpeakerTeal1625"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerTeal3240 : public SpeakerTeal {
public:
virtual Common::String getClassName() { return "SpeakerTeal3240"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerTeal3400 : public SpeakerTeal {
public:
virtual Common::String getClassName() { return "SpeakerTeal3400"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerTeal3600 : public SpeakerTealMode7 {
public:
virtual Common::String getClassName() { return "SpeakerTeal3600"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Tomko
@@ -566,17 +590,24 @@ public:
SpeakerTomko3245();
virtual Common::String getClassName() { return "SpeakerTomko3245"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
// Classes related to Webbster
class SpeakerWebbster : public VisualSpeaker {
public:
- SpeakerWebbster(int colour);
+ SpeakerWebbster(int color);
virtual Common::String getClassName() { return "SpeakerWebbster"; }
};
+class SpeakerWebbster180 : public SpeakerWebbster {
+public:
+ SpeakerWebbster180() : SpeakerWebbster(27) {}
+ virtual Common::String getClassName() { return "SpeakerWebbster180"; }
+ virtual void animateSpeaker();
+};
+
class SpeakerWebbster2500 : public SpeakerWebbster {
public:
SpeakerWebbster2500() : SpeakerWebbster(27) {}
@@ -588,7 +619,7 @@ public:
SpeakerWebbster3240() : SpeakerWebbster(10) {}
virtual Common::String getClassName() { return "SpeakerWebbster3240"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerWebbster3375 : public SpeakerWebbster {
@@ -596,7 +627,7 @@ public:
SpeakerWebbster3375() : SpeakerWebbster(60) {}
virtual Common::String getClassName() { return "SpeakerWebbster3375"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerWebbster3385 : public SpeakerWebbster {
@@ -604,7 +635,7 @@ public:
SpeakerWebbster3385() : SpeakerWebbster(60) {}
virtual Common::String getClassName() { return "SpeakerWebbster3385"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerWebbster3395 : public SpeakerWebbster {
@@ -612,7 +643,7 @@ public:
SpeakerWebbster3395() : SpeakerWebbster(60) {}
virtual Common::String getClassName() { return "SpeakerWebbster3395"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
class SpeakerWebbster3400 : public SpeakerWebbster {
@@ -620,15 +651,15 @@ public:
SpeakerWebbster3400() : SpeakerWebbster(27) {}
virtual Common::String getClassName() { return "SpeakerWebbster3400"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
-class SpeakerDutyOfficer: public VisualSpeaker {
+class SpeakerDutyOfficer180: public VisualSpeaker {
public:
- SpeakerDutyOfficer();
+ SpeakerDutyOfficer180();
virtual Common::String getClassName() { return "SpeakerDutyOfficer"; }
- virtual void proc15();
+ virtual void animateSpeaker();
};
} // End of namespace Ringworld2
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
index af2f3566ad..f9e84e8913 100644
--- a/engines/tsage/saveload.cpp
+++ b/engines/tsage/saveload.cpp
@@ -47,6 +47,8 @@ SavedObject::~SavedObject() {
Saver::Saver() {
_macroSaveFlag = false;
_macroRestoreFlag = false;
+
+ _factoryPtr = nullptr;
}
Saver::~Saver() {
@@ -127,7 +129,6 @@ Common::Error Saver::save(int slot, const Common::String &saveName) {
// Set fields
_macroSaveFlag = true;
- _saveSlot = slot;
// Try and create the save file
Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(g_vm->generateSaveName(slot));
@@ -151,8 +152,9 @@ Common::Error Saver::save(int slot, const Common::String &saveName) {
// Save each registered SaveObject descendant object into the savegame file
for (SynchronizedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) {
- serializer.validate((*i)->getClassName());
- (*i)->synchronize(serializer);
+ SavedObject *so = *i;
+ serializer.validate(so->getClassName());
+ so->synchronize(serializer);
}
// Save file complete
@@ -176,7 +178,6 @@ Common::Error Saver::restore(int slot) {
// Set fields
_macroRestoreFlag = true;
- _saveSlot = slot;
_unresolvedPtrs.clear();
// Set up the serializer
@@ -289,7 +290,7 @@ void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &h
// Create a thumbnail and save it
Graphics::Surface *thumb = new Graphics::Surface();
Graphics::Surface s = g_globals->_screenSurface.lockSurface();
- ::createThumbnail(thumb, (const byte *)s.pixels, SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
+ ::createThumbnail(thumb, (const byte *)s.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
Graphics::saveThumbnail(*out, *thumb);
g_globals->_screenSurface.unlockSurface();
thumb->free();
diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h
index 4126e31822..32da6ee7f4 100644
--- a/engines/tsage/saveload.h
+++ b/engines/tsage/saveload.h
@@ -33,7 +33,7 @@ namespace TsAGE {
typedef void (*SaveNotifierFn)(bool postFlag);
-#define TSAGE_SAVEGAME_VERSION 10
+#define TSAGE_SAVEGAME_VERSION 12
class SavedObject;
@@ -48,7 +48,7 @@ struct tSageSavegameHeader {
/*--------------------------------------------------------------------------*/
-// FIXME: workaround to supress spurious strict-alias warnings on older GCC
+// FIXME: workaround to suppress spurious strict-alias warnings on older GCC
// versions. this should be resolved with the savegame rewrite
#define SYNC_POINTER(x) do { \
SavedObject **y = (SavedObject **)((void *)&x); \
@@ -59,7 +59,7 @@ struct tSageSavegameHeader {
if (s.isLoading()) FIELD = (TYPE)v_##FIELD;
/**
- * Derived serializer class with extra synchronisation types
+ * Derived serializer class with extra synchronization types
*/
class Serializer : public Common::Serializer {
public:
@@ -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;
+ }
};
/**
@@ -202,7 +212,6 @@ private:
bool _macroSaveFlag;
bool _macroRestoreFlag;
- int _saveSlot;
void resolveLoadPointers();
public:
diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp
index 774a5277dc..1726d6ad20 100644
--- a/engines/tsage/scenes.cpp
+++ b/engines/tsage/scenes.cpp
@@ -43,6 +43,7 @@ SceneManager::SceneManager() {
g_saver->addListener(this);
_objectCount = 0;
_loadMode = 0;
+ _sceneLoadCount = 0;
}
SceneManager::~SceneManager() {
@@ -56,8 +57,13 @@ void SceneManager::setNewScene(int sceneNumber) {
void SceneManager::checkScene() {
if (_nextSceneNumber != -1) {
+ int nextSceneNumber = _nextSceneNumber;
+
sceneChange();
- _nextSceneNumber = -1;
+
+ // Unless we've already switched to yet another scene, reset
+ if (_nextSceneNumber == nextSceneNumber)
+ _nextSceneNumber = -1;
}
g_globals->dispatchSounds();
@@ -247,6 +253,14 @@ void SceneManager::listenerSynchronize(Serializer &s) {
}
}
+ // Walk regions loading
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ int walkRegionsId = GLOBALS._walkRegions._resNum;
+ s.syncAsSint16LE(walkRegionsId);
+ if (s.isLoading())
+ GLOBALS._walkRegions.load(walkRegionsId);
+ }
+
g_globals->_sceneManager._scrollerRect.synchronize(s);
SYNC_POINTER(g_globals->_scrollFollower);
s.syncAsSint16LE(_loadMode);
@@ -260,6 +274,11 @@ Scene::Scene() : _sceneBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
_activeScreenNumber = 0;
_oldSceneBounds = Rect(4000, 4000, 4100, 4100);
Common::fill(&_zoomPercents[0], &_zoomPercents[256], 0);
+
+ _field12 = 0;
+ _screenNumber = 0;
+ _fieldA = 0;
+ _fieldE = 0;
}
Scene::~Scene() {
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index b9567cece2..6633d15c26 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -22,6 +22,8 @@
#include "audio/decoders/raw.h"
#include "common/config-manager.h"
+#include "audio/decoders/raw.h"
+#include "audio/audiostream.h"
#include "tsage/core.h"
#include "tsage/globals.h"
#include "tsage/debugger.h"
@@ -118,17 +120,31 @@ void SoundManager::syncSounds() {
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
+ bool subtitles = ConfMan.hasKey("subtitles") ? ConfMan.getBool("subtitles") : true;
bool music_mute = mute;
+ bool voice_mute = mute;
if (!mute) {
music_mute = ConfMan.getBool("music_mute");
+ voice_mute = ConfMan.getBool("speech_mute");
}
// Get the new music volume
int musicVolume = music_mute ? 0 : MIN(255, ConfMan.getInt("music_volume"));
this->setMasterVol(musicVolume / 2);
+
+ // Return to Ringworld voice settings
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ // If we don't have voice, then ensure that text is turned on
+ if (voice_mute)
+ subtitles = true;
+
+ R2_GLOBALS._speechSubtitles =
+ (voice_mute ? 0 : SPEECH_VOICE) |
+ (!subtitles ? 0 : SPEECH_TEXT);
+ }
}
void SoundManager::update() {
@@ -953,7 +969,7 @@ void SoundManager::sfRethinkVoiceTypes() {
int entryIndex = -1;
for (uint idx = 0; idx < vtStruct->_entries.size(); ++idx) {
if (vtStruct->_entries[idx]._voiceNum == foundIndex) {
- foundIndex = true;
+ foundMatch = true;
if (!vtStruct->_entries[idx]._type0._sound2) {
entryIndex = idx;
break;
@@ -992,7 +1008,7 @@ void SoundManager::sfRethinkVoiceTypes() {
if (vtStruct->_entries[idx]._type0._priority2 > maxPriority) {
maxPriority = vtStruct->_entries[idx]._type0._priority2;
- entryIndex = -1;
+ entryIndex = idx;
}
}
@@ -1720,7 +1736,7 @@ uint32 Sound::getTimeIndex() const {
}
int Sound::getCueValue() const {
- return _cueValue;
+ return _cueValue == 0xff ? -1 : _cueValue;
}
void Sound::setCueValue(int cueValue) {
@@ -2395,7 +2411,7 @@ int Sound::soFindSound(VoiceTypeStruct *vtStruct, int channelNum) {
/*--------------------------------------------------------------------------*/
ASound::ASound(): EventHandler() {
- _action = NULL;
+ _endAction = NULL;
_cueValue = -1;
if (g_globals)
g_globals->_sounds.push_back(this);
@@ -2422,23 +2438,23 @@ void ASound::dispatch() {
_cueValue = cueValue;
_sound.setCueValue(-1);
- if (_action)
- _action->signal();
+ if (_endAction)
+ _endAction->signal();
}
if (_cueValue != -1) {
if (!_sound.isPrimed()) {
_cueValue = -1;
- if (_action) {
- _action->signal();
- _action = NULL;
+ if (_endAction) {
+ _endAction->signal();
+ _endAction = NULL;
}
}
}
}
-void ASound::play(int soundNum, EventHandler *action, int volume) {
- _action = action;
+void ASound::play(int soundNum, EventHandler *endAction, int volume) {
+ _endAction = endAction;
_cueValue = 0;
setVol(volume);
@@ -2461,9 +2477,9 @@ void ASound::unPrime() {
_action = NULL;
}
-void ASound::fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *action) {
- if (action)
- _action = action;
+void ASound::fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *endAction) {
+ if (endAction)
+ _endAction = endAction;
_sound.fade(fadeDest, fadeSteps, fadeTicks, stopAfterFadeFlag);
}
@@ -2490,8 +2506,8 @@ void ASoundExt::signal() {
}
}
-void ASoundExt::fadeOut2(EventHandler *action) {
- fade(0, 10, 10, true, action);
+void ASoundExt::fadeOut2(EventHandler *endAction) {
+ fade(0, 10, 10, true, endAction);
}
void ASoundExt::changeSound(int soundNum) {
@@ -2505,6 +2521,183 @@ void ASoundExt::changeSound(int soundNum) {
/*--------------------------------------------------------------------------*/
+void PlayStream::ResFileData::load(Common::SeekableReadStream &stream) {
+ // Validate that it's the correct data file
+ char header[4];
+ stream.read(&header[0], 4);
+ if (strncmp(header, "SPAM", 4))
+ error("Invalid voice resource data");
+
+ _fileChunkSize = stream.readUint32LE();
+ stream.skip(2);
+ _indexSize = stream.readUint16LE();
+ _chunkSize = stream.readUint16LE();
+
+ stream.skip(18);
+}
+
+PlayStream::PlayStream(): EventHandler() {
+ _index = NULL;
+ _endAction = NULL;
+ _audioStream = NULL;
+
+ _resData._fileChunkSize = 0;
+ _resData._indexSize = 0;
+ _resData._chunkSize = 0;
+ _voiceNum = 0;
+}
+
+PlayStream::~PlayStream() {
+ remove();
+}
+
+bool PlayStream::setFile(const Common::String &filename) {
+ remove();
+
+ // Open the resource file for access
+ if (!_file.open(filename))
+ return false;
+
+ // Load header
+ _resData.load(_file);
+
+ // Load the index
+ _index = new uint16[_resData._indexSize / 2];
+ for (uint i = 0; i < (_resData._indexSize / 2); ++i)
+ _index[i] = _file.readUint16LE();
+
+ return true;
+}
+
+bool PlayStream::play(int voiceNum, EventHandler *endAction) {
+ uint32 offset = getFileOffset(_index, _resData._fileChunkSize, voiceNum);
+ if (offset) {
+ stop();
+ _voiceNum = 0;
+
+ // Move to the offset for the start of the voice
+ _file.seek(offset);
+
+ // Read in the header and validate it
+ char header[4];
+ _file.read(&header[0], 4);
+ if (strncmp(header, "FEED", 4))
+ error("Invalid stream data");
+
+ // Get basic details of first sound chunk
+ uint chunkSize = _file.readUint16LE() - 16;
+ _file.skip(4);
+ int rate = _file.readUint16LE();
+ _file.skip(4);
+
+ // Create the stream
+ _audioStream = Audio::makeQueuingAudioStream(rate, false);
+
+ // Load in the first chunk
+ byte *data = (byte *)malloc(chunkSize);
+ _file.read(data, chunkSize);
+ _audioStream->queueBuffer(data, chunkSize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
+
+ // If necessary, load further chunks of the voice in
+ while (chunkSize == (_resData._chunkSize - 16)) {
+ // Ensure the next chunk has the 'MORE' header
+ _file.read(&header[0], 4);
+ if (!strncmp(header, "FEED", 4))
+ // Reached start of next voice sample, so stop
+ break;
+ if (strncmp(header, "MORE", 4))
+ // Not more remaining, so break
+ break;
+
+ // Get the size of the chunk
+ chunkSize = _file.readUint16LE() - 16;
+ _file.skip(10);
+
+ // Read in the data for this next chunk and queue it
+ data = (byte *)malloc(chunkSize);
+ _file.read(data, chunkSize);
+ _audioStream->queueBuffer(data, chunkSize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
+ }
+
+ g_vm->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle,
+ _audioStream, DisposeAfterUse::YES);
+ _voiceNum = voiceNum;
+ _endAction = endAction;
+ return true;
+ }
+
+ // If it reaches this point, no valid voice data found
+ return false;
+}
+
+void PlayStream::stop() {
+ if (_audioStream) {
+ g_vm->_mixer->stopHandle(_soundHandle);
+ }
+
+ _audioStream = NULL;
+ _voiceNum = 0;
+ _endAction = NULL;
+}
+
+bool PlayStream::isPlaying() const {
+ return _audioStream != NULL && !_audioStream->endOfData();
+}
+
+void PlayStream::remove() {
+ stop();
+ _file.close();
+
+ // Free index
+ delete[] _index;
+ _index = NULL;
+
+ _endAction = NULL;
+ _voiceNum = 0;
+}
+
+void PlayStream::dispatch() {
+ if (_voiceNum != 0 && !isPlaying()) {
+ // If voice has finished playing, reset fields
+ EventHandler *endAction = _endAction;
+ _endAction = NULL;
+ _voiceNum = 0;
+
+ if (endAction)
+ // Signal given end action
+ endAction->signal();
+ }
+}
+
+uint32 PlayStream::getFileOffset(const uint16 *data, int count, int voiceNum) {
+ if (!data)
+ return 0; // no valid voice data found
+
+ int bitsIndex = voiceNum & 7;
+ int byteIndex = voiceNum >> 3;
+ int shiftAmount = bitsIndex * 2;
+ int bitMask = 3 << shiftAmount;
+ int v = (data[byteIndex] & bitMask) >> shiftAmount;
+ uint32 offset = 0;
+
+ if (!v)
+ return 0;
+
+ // Loop to figure out offsets from index words skipped over
+ for (int i = 0; i < (voiceNum >> 3); ++i) {
+ for (int bit = 0; bit < 16; bit += 2)
+ offset += ((data[i] >> bit) & 3) * count;
+ }
+
+ // Bit index loop
+ for (int i = 0; i < bitsIndex; ++i)
+ offset += ((data[byteIndex] >> (i * 2)) & 3) * count;
+
+ return offset;
+}
+
+/*--------------------------------------------------------------------------*/
+
SoundDriver::SoundDriver() {
_driverResID = 0;
_minVersion = _maxVersion = 0;
@@ -2516,13 +2709,8 @@ SoundDriver::SoundDriver() {
const byte adlib_group_data[] = { 1, 1, 9, 1, 0xff };
-const byte v440B0[9] = { 0, 1, 2, 6, 7, 8, 12, 13, 14 };
-
-const byte v440B9[9] = { 3, 4, 5, 9, 10, 11, 15, 16, 17 };
-
-const byte v440C2[18] = {
- 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
-};
+const byte adlib_operator1_offset[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
+const byte adlib_operator2_offset[] = { 3, 4, 5, 11, 12, 13, 19, 20, 21 };
const byte v44134[64] = {
0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
@@ -2546,8 +2734,6 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_masterVolume = 0;
_groupData._groupMask = 9;
- _groupData._v1 = 0x46;
- _groupData._v2 = 0;
_groupData._pData = &adlib_group_data[0];
_mixer = g_vm->_mixer;
@@ -2653,10 +2839,10 @@ void AdlibSoundDriver::playSound(const byte *channelData, int dataOffset, int pr
_v4409E[channel] = dataP + offset - _patchData;
// Set sustain/release
- int portNum = v440C2[v440B0[channel]] + 0x80;
+ int portNum = adlib_operator1_offset[channel] + 0x80;
write(portNum, (_portContents[portNum] & 0xF0) | 0xF);
- portNum = v440C2[v440B9[channel]] + 0x80;
+ portNum = adlib_operator2_offset[channel] + 0x80;
write(portNum, (_portContents[portNum] & 0xF0) | 0xF);
if (_channelVoiced[channel])
@@ -2713,10 +2899,10 @@ void AdlibSoundDriver::updateChannelVolume(int channelNum) {
int level1 = !_v44082[channelNum] ? 63 - _v44070[channelNum] :
63 - v44134[volume * _v44070[channelNum] / 63];
- int portNum = v440C2[v440B0[channelNum]] + 0x40;
+ int portNum = adlib_operator1_offset[channelNum] + 0x40;
write(portNum, (_portContents[portNum] & 0x80) | level1);
- portNum = v440C2[v440B9[channelNum]] + 0x40;
+ portNum = adlib_operator2_offset[channelNum] + 0x40;
write(portNum, (_portContents[portNum] & 0x80) | level2);
}
@@ -2733,7 +2919,7 @@ void AdlibSoundDriver::clearVoice(int channel) {
void AdlibSoundDriver::updateChannel(int channel) {
const byte *dataP = _patchData + _v4409E[channel];
- int portOffset = v440C2[v440B0[channel]];
+ int portOffset = adlib_operator1_offset[channel];
int portNum = portOffset + 0x20;
int portValue = 0;
@@ -2756,7 +2942,7 @@ void AdlibSoundDriver::updateChannel(int channel) {
write(0x80 + portOffset, *(dataP + 14) | (*(dataP + 13) << 4));
write(0xE0 + portOffset, (_portContents[0xE0 + portOffset] & 0xFC) | *(dataP + 15));
- portOffset = v440C2[v440B9[channel]];
+ portOffset = adlib_operator2_offset[channel];
portNum = portOffset + 0x20;
portValue = 0;
if (*(dataP + 17))
@@ -2865,8 +3051,6 @@ SoundBlasterDriver::SoundBlasterDriver(): SoundDriver() {
_masterVolume = 0;
_groupData._groupMask = 1;
- _groupData._v1 = 0x3E;
- _groupData._v2 = 0;
static byte const group_data[] = { 3, 1, 1, 0, 0xff };
_groupData._pData = group_data;
@@ -2914,10 +3098,12 @@ void SoundBlasterDriver::playSound(const byte *channelData, int dataOffset, int
updateVoice(channel);
// Set the new channel data
- _channelData = channelData + dataOffset;
+ _channelData = channelData + dataOffset + 18;
// Make a copy of the buffer
int dataSize = g_vm->_memoryManager.getSize(channelData);
+ dataSize -= 18;
+
byte *soundData = (byte *)malloc(dataSize - dataOffset);
Common::copy(_channelData, _channelData + (dataSize - dataOffset), soundData);
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 2f59afb49b..fefe8ad101 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -63,8 +63,6 @@ public:
struct GroupData {
uint32 _groupMask;
- byte _v1;
- byte _v2;
const byte *_pData;
};
@@ -98,7 +96,7 @@ public:
virtual const GroupData *getGroupData() { return NULL; } // Method #3
virtual void installPatch(const byte *data, int size) {} // Method #4
virtual void poll() {} // Method #5
- virtual void proc12() {} // Method #6
+ virtual void method6() {} // Method #6
virtual int setMasterVolume(int volume) { return 0; } // Method #7
virtual void proc16() {} // Method #8
virtual void proc18(int al, VoiceType voiceType) {} // Method #9
@@ -259,6 +257,7 @@ public:
class Sound: public EventHandler {
private:
void _prime(int soundResID, bool dontQueue);
+ void _primeBuffer(const byte *soundData);
void _unPrime();
public:
bool _stoppedAsynchronously;
@@ -365,7 +364,7 @@ public:
class ASound: public EventHandler {
public:
Sound _sound;
- EventHandler *_action;
+ EventHandler *_endAction;
int _cueValue;
ASound();
@@ -373,7 +372,7 @@ public:
virtual void synchronize(Serializer &s);
virtual void dispatch();
- void play(int soundNum, EventHandler *action = NULL, int volume = 127);
+ void play(int soundNum, EventHandler *endAction = NULL, int volume = 127);
void stop();
void prime(int soundNum, Action *action = NULL);
void unPrime();
@@ -385,7 +384,7 @@ public:
bool isMuted() const { return _sound.isMuted(); }
void pause(bool flag) { _sound.pause(flag); }
void mute(bool flag) { _sound.mute(flag); }
- void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *action);
+ void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *endAction);
void fadeIn() { fade(127, 5, 10, false, NULL); }
void fadeOut(Action *action) { fade(0, 5, 10, true, action); }
void setTimeIndex(uint32 timeIndex) { _sound.setTimeIndex(timeIndex); }
@@ -406,7 +405,7 @@ public:
int _soundNum;
ASoundExt();
- void fadeOut2(EventHandler *action);
+ void fadeOut2(EventHandler *endAction);
void changeSound(int soundNum);
virtual Common::String getClassName() { return "ASoundExt"; }
@@ -414,15 +413,36 @@ public:
virtual void signal();
};
-class PlayStream {
+class PlayStream: public EventHandler {
+ class ResFileData {
+ public:
+ int _fileChunkSize;
+ uint _indexSize;
+ uint _chunkSize;
+
+ void load(Common::SeekableReadStream &stream);
+ };
+private:
+ Common::File _file;
+ ResFileData _resData;
+ Audio::QueuingAudioStream *_audioStream;
+ Audio::SoundHandle _soundHandle;
+ uint16 *_index;
+ EventHandler *_endAction;
+ int _voiceNum;
+
+ static uint32 getFileOffset(const uint16 *data, int count, int voiceNum);
public:
- Sound _sound;
+ PlayStream();
+ virtual ~PlayStream();
- void setFile(const Common::String &filename) {}
- bool play(int soundNum, EventHandler *endAction) { return false; }
- void stop() {}
- void proc1() {}
- bool isPlaying() const { return false; }
+ bool setFile(const Common::String &filename);
+ bool play(int voiceNum, EventHandler *endAction);
+ void stop();
+ bool isPlaying() const;
+
+ virtual void remove();
+ virtual void dispatch();
};
#define ADLIB_CHANNEL_COUNT 9
diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp
index a273ec2a0b..2749f2ac90 100644
--- a/engines/tsage/staticres.cpp
+++ b/engines/tsage/staticres.cpp
@@ -162,7 +162,7 @@ char const *const BIKINI_HUT = "Bikini Hut";
char const *const RADIO_BTN_LIST[8] = { "10-2 ", "10-4 ", "10-13", "10-15", "10-27", "10-35", "10-97", "10-98" };
// Scene 570 computer messageS
-char const *const SCENE570_PASSWORD = "PASSWORD -> ";
+char const *const SCENE570_PASSWORD = "PASSWORD - }, ";
char const *const SCENE570_C_DRIVE = "C:\\";
char const *const SCENE570_RING = "RING";
char const *const SCENE570_PROTO = "PROTO";
@@ -229,6 +229,7 @@ char const *const RESTORE_GAME = "Restore game";
char const *const SHOW_CREDITS = "Show credits";
char const *const PAUSE_GAME = "Pause game";
char const *const RESUME_PLAY = " Resume play ";
+char const *const R2_RESTART_MSG = "Go to the beginning of game?";
char const *const F2 = "F2";
char const *const F3 = "F3";
char const *const F4 = "F4";
@@ -244,7 +245,7 @@ char const *const USE_INTERCEPTOR = "Do you want to use your interceptor card?";
char const *const USE_DOUBLE_AGENT = "Do you want to use your double agent?";
char const *const NEED_INSTRUCTIONS = "Do you want instructions?";
char const *const WRONG_ANSWER_MSG = "Wrong respond value sent.";
-const byte k562CC[] = {
+const byte scene1550JunkLocationsDefault[] = {
20, 7, 41, 6,
3, 6, 42, 11,
10, 15, 43, 6,
@@ -374,7 +375,7 @@ const byte k562CC[] = {
28, 18, 21, 1
};
-const byte k5A4D6[] = {
+const byte scene1550AreaMap[] = {
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
16, 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, 18,
17, 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, 19,
@@ -397,8 +398,8 @@ const byte k5A4D6[] = {
13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14
};
-const byte k5A72E[] = {0, 98, 135, 183, 229, 81, 133, 185, 235, 75, 131, 187, 241, 70, 129, 190, 247};
-const byte k5A73F[] = {0, 42, 42, 42, 42, 67, 67, 67, 67, 92, 92, 92, 92, 116, 116, 116, 116};
+const byte scene1550JunkX[] = {0, 98, 135, 183, 229, 81, 133, 185, 235, 75, 131, 187, 241, 70, 129, 190, 247};
+const byte scene1550JunkY[] = {0, 42, 42, 42, 42, 67, 67, 67, 67, 92, 92, 92, 92, 116, 116, 116, 116};
const byte k5A750[] = {
9, 10, 7, 13, 7, 8, 9, 7, 9, 10,
2, 3, 3, 2, 2, 2, 4, 3, 3, 4,
@@ -409,8 +410,8 @@ const byte k5A76D[] = {
3, 3, 3, 7, 3, 7, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3
};
-const byte k5A78A[] = {0, 8, 15, 16, 12, 7, 18, 17, 13, 6, 19, 20, 14, 5, 11, 10, 9};
-const byte k5A79B[] = {
+const byte scene1550JunkRegions[] = {0, 8, 15, 16, 12, 7, 18, 17, 13, 6, 19, 20, 14, 5, 11, 10, 9};
+const byte scene1550SpecialAreas[] = {
23, 3, 1,
23, 4, 1,
26, 3, 1,
@@ -448,6 +449,201 @@ const byte k5A7F6[] = {
15, 10, 11
};
+const BalloonRecord balloonData[] = {
+ { 0, -2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 0, 1 },
+ { 0, 0, 1 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 0, 2, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 0, 0, -1 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 0, -1 },
+ { 0, 0, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 0, 0 },
+ { 0, 0, -1 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 2, 0, 0 },
+ { 0, 0, -1 },
+ { -2, 0, 0 },
+ { 0, 0, -1 },
+ { -2, 0, 0 },
+ { 0, 0, -1 },
+ { 2, 0, 0 },
+ { 0, 0, -1 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 2, 0, 0 },
+ { 0, 2, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 0, 1 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, 0, 1 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, 0, -1 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, -2, 0 },
+ { 0, 0, -1 },
+ { -2, 0, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { 0, -2, 0 },
+ { 2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, 0, 0 },
+ { 2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { -2, 0, 0 },
+ { 0, -2, 0 },
+ { 0, 2, 0 },
+ { -2, 0, 0 }
+};
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h
index e3daf73333..587463a918 100644
--- a/engines/tsage/staticres.h
+++ b/engines/tsage/staticres.h
@@ -182,6 +182,7 @@ extern char const *const RESTORE_GAME;
extern char const *const SHOW_CREDITS;
extern char const *const PAUSE_GAME;
extern char const *const RESUME_PLAY;
+extern char const *const R2_RESTART_MSG;
extern char const *const F2;
extern char const *const F3;
extern char const *const F4;
@@ -199,16 +200,24 @@ extern char const *const NEED_INSTRUCTIONS;
extern char const *const WRONG_ANSWER_MSG;
// Scene 1550 arrays of constants
-extern const byte k562CC[];
-extern const byte k5A4D6[];
-extern const byte k5A72E[];
-extern const byte k5A73F[];
+extern const byte scene1550JunkLocationsDefault[];
+extern const byte scene1550AreaMap[];
+extern const byte scene1550JunkX[];
+extern const byte scene1550JunkY[];
extern const byte k5A750[];
extern const byte k5A76D[];
-extern const byte k5A78A[];
-extern const byte k5A79B[];
+extern const byte scene1550JunkRegions[];
+extern const byte scene1550SpecialAreas[];
extern const byte k5A7F6[];
+// Scene 2900 balloon data
+struct BalloonRecord {
+ int8 x;
+ int8 y;
+ int8 v3;
+};
+extern const BalloonRecord balloonData[];
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp
index 87697f950b..37e96c75e0 100644
--- a/engines/tsage/tsage.cpp
+++ b/engines/tsage/tsage.cpp
@@ -38,6 +38,7 @@ TSageEngine::TSageEngine(OSystem *system, const tSageGameDescription *gameDesc)
_gameDescription(gameDesc) {
g_vm = this;
DebugMan.addDebugChannel(kRingDebugScripts, "scripts", "Scripts debugging");
+ _debugger = nullptr;
if (g_vm->getFeatures() & GF_DEMO)
_debugger = new DemoDebugger();
else if (g_vm->getGameID() == GType_Ringworld)
@@ -103,7 +104,7 @@ void TSageEngine::initialize() {
g_globals = new Ringworld2::Ringworld2Globals();
// Setup the user interface
- T2_GLOBALS._uiElements.setup(Common::Point(0, UI_INTERFACE_Y - 2));
+ T2_GLOBALS._uiElements.setup(Common::Point(0, UI_INTERFACE_Y));
// Reset all global variables
R2_GLOBALS.reset();
@@ -124,7 +125,7 @@ void TSageEngine::deinitialize() {
}
Common::Error TSageEngine::run() {
- // Basic initialisation
+ // Basic initialization
initialize();
g_globals->_sceneHandler->registerHandler();
diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp
index 4bd9e49875..ae34ac0574 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->setup2(4, 1, 1, 160, 125);
} else {
// Show object description
SceneItem::display2(3, (int)cursor);
@@ -273,11 +276,29 @@ void UICollection::draw() {
Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT),
Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT));
+ if (g_vm->getGameID() == GType_Ringworld2)
+ r2rDrawFrame();
+
_clearScreen = 1;
g_globals->_sceneManager._scene->_sceneBounds = savedBounds;
}
}
+void UICollection::r2rDrawFrame() {
+ Visage visage;
+ visage.setVisage(2, 1);
+ GfxSurface vertLine = visage.getFrame(1);
+ GfxSurface horizLine = visage.getFrame(2);
+
+ GLOBALS._screenSurface.copyFrom(horizLine, 0, 0);
+ GLOBALS._screenSurface.copyFrom(vertLine, 0, 3);
+ GLOBALS._screenSurface.copyFrom(vertLine, SCREEN_WIDTH - 4, 3);
+
+ // Restrict drawing area to exclude the borders at the edge of the screen
+ R2_GLOBALS._screenSurface._clipRect = Rect(4, 4, SCREEN_WIDTH - 4,
+ SCREEN_HEIGHT - 4);
+}
+
/*--------------------------------------------------------------------------*/
UIElements::UIElements(): UICollection() {
@@ -286,6 +307,10 @@ UIElements::UIElements(): UICollection() {
else
_cursorVisage.setVisage(1, 5);
g_saver->addLoadNotifier(&UIElements::loadNotifierProc);
+
+ _slotStart = 0;
+ _scoreValue = 0;
+ _active = false;
}
void UIElements::synchronize(Serializer &s) {
@@ -399,7 +424,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 +435,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;
@@ -451,7 +476,7 @@ void UIElements::add(UIElement *obj) {
/**
* Handles updating the visual inventory in the user interface
*/
-void UIElements::updateInventory() {
+void UIElements::updateInventory(int objectNumber) {
switch (g_vm->getGameID()) {
case GType_BlueForce:
// Update the score
@@ -480,6 +505,17 @@ void UIElements::updateInventory() {
else if (_slotStart > (lastPage - 1))
_slotStart = 0;
+ // Handle changing the page, if necessary, to ensure an optionally supplied
+ // object number will be on-screen
+ if (objectNumber != 0) {
+ for (uint idx = 0; idx < _itemList.size(); ++idx) {
+ if (_itemList[idx] == objectNumber) {
+ _slotStart = idx / 4;
+ break;
+ }
+ }
+ }
+
// Handle refreshing slot graphics
UIInventorySlot *slotList[4] = { &_slot1, &_slot2, &_slot3, &_slot4 };
diff --git a/engines/tsage/user_interface.h b/engines/tsage/user_interface.h
index 0fbfc5a00f..60cefc0751 100644
--- a/engines/tsage/user_interface.h
+++ b/engines/tsage/user_interface.h
@@ -95,6 +95,8 @@ public:
};
class UICollection: public EventHandler {
+private:
+ void r2rDrawFrame();
protected:
void erase();
public:
@@ -137,7 +139,7 @@ public:
virtual void process(Event &event);
void setup(const Common::Point &pt);
- void updateInventory();
+ void updateInventory(int objectNumber = 0);
void addScore(int amount);
void scrollInventory(bool isLeft);
diff --git a/engines/tucker/configure.engine b/engines/tucker/configure.engine
new file mode 100644
index 0000000000..06676cf0a4
--- /dev/null
+++ b/engines/tucker/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine tucker "Bud Tucker in Double Trouble" yes
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 16c4f4f6f0..bd03eed00b 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -763,7 +763,7 @@ bool AnimationSequencePlayer::decodeNextAnimationFrame(int index, bool copyDirty
if (!copyDirtyRects) {
for (uint16 y = 0; (y < surface->h) && (y < kScreenHeight); y++)
- memcpy(_offscreenBuffer + y * kScreenWidth, (byte *)surface->pixels + y * surface->pitch, surface->w);
+ memcpy(_offscreenBuffer + y * kScreenWidth, (const byte *)surface->getBasePtr(0, y), surface->w);
} else {
_flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth);
}
@@ -811,7 +811,7 @@ void AnimationSequencePlayer::playIntroSeq19_20() {
if (surface)
for (int i = 0; i < kScreenWidth * kScreenHeight; ++i)
if (_offscreenBuffer[i] == 0)
- _offscreenBuffer[i] = *((byte *)surface->pixels + i);
+ _offscreenBuffer[i] = *((const byte *)surface->getPixels() + i);
if (!framesLeft)
_changeToNextSequence = true;
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/voyeur/animation.cpp b/engines/voyeur/animation.cpp
index 3bcc6cf10f..cbd7b0af18 100644
--- a/engines/voyeur/animation.cpp
+++ b/engines/voyeur/animation.cpp
@@ -230,7 +230,7 @@ void RL2Decoder::RL2VideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
for (int y = (*it).top; y < (*it).bottom; ++y) {
const int x = (*it).left;
- memcpy(dst + y * pitch + x, (byte *)_surface->pixels + y * getWidth() + x, (*it).right - x);
+ memcpy(dst + y * pitch + x, (byte *)_surface->getPixels() + y * getWidth() + x, (*it).right - x);
}
}
@@ -238,7 +238,7 @@ void RL2Decoder::RL2VideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
}
void RL2Decoder::RL2VideoTrack::copyFrame(uint8 *data) {
- memcpy((byte *)_surface->pixels, data, getWidth() * getHeight());
+ memcpy((byte *)_surface->getPixels(), data, getWidth() * getHeight());
// Redraw
_dirtyRects.clear();
@@ -248,7 +248,7 @@ void RL2Decoder::RL2VideoTrack::copyFrame(uint8 *data) {
void RL2Decoder::RL2VideoTrack::rl2DecodeFrameWithoutBackground(int screenOffset) {
if (screenOffset == -1)
screenOffset = _videoBase;
- byte *destP = (byte *)_surface->pixels + screenOffset;
+ byte *destP = (byte *)_surface->getPixels() + screenOffset;
int frameSize = _surface->w * _surface->h - screenOffset;
while (frameSize > 0) {
@@ -280,8 +280,8 @@ void RL2Decoder::RL2VideoTrack::rl2DecodeFrameWithoutBackground(int screenOffset
void RL2Decoder::RL2VideoTrack::rl2DecodeFrameWithBackground() {
int screenOffset = _videoBase;
int frameSize = _surface->w * _surface->h - _videoBase;
- byte *src = (byte *)_backSurface->pixels;
- byte *dest = (byte *)_surface->pixels;
+ byte *src = (byte *)_backSurface->getPixels();
+ byte *dest = (byte *)_surface->getPixels();
while (frameSize > 0) {
byte nextByte = _fileStream->readByte();
diff --git a/engines/voyeur/configure.engine b/engines/voyeur/configure.engine
new file mode 100644
index 0000000000..647e20267f
--- /dev/null
+++ b/engines/voyeur/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine voyeur "Voyeur" yes
diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp
index 6bd0012fe7..56b7afd377 100644
--- a/engines/voyeur/events.cpp
+++ b/engines/voyeur/events.cpp
@@ -108,7 +108,7 @@ void EventsManager::checkForNextFrameCounter() {
voyeurTimer();
// Display the frame
- g_system->copyRectToScreen((byte *)_vm->_graphicsManager._screenSurface.pixels,
+ g_system->copyRectToScreen((byte *)_vm->_graphicsManager._screenSurface.getPixels(),
SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g_system->updateScreen();
diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp
index 6e3ed103ce..3a37eb9fb0 100644
--- a/engines/voyeur/graphics.cpp
+++ b/engines/voyeur/graphics.cpp
@@ -308,7 +308,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
// loc_2566F
if (srcFlags & DISPFLAG_2) {
// loc_256FA
- srcP = (byte *)_screenSurface.pixels + srcOffset;
+ srcP = (byte *)_screenSurface.getPixels() + srcOffset;
for (int yp = 0; yp < height1; ++yp) {
for (int xp = 0; xp < width2; ++width2, ++srcP, ++destP) {
@@ -341,7 +341,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
}
} else {
// loc_25829
- destP = (byte *)_screenSurface.pixels + screenOffset;
+ destP = (byte *)_screenSurface.getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::copy(srcP, srcP + width2, destP);
@@ -356,7 +356,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
// loc_25D4A
} else {
// loc_2606D
- destP = (byte *)_screenSurface.pixels + screenOffset;
+ destP = (byte *)_screenSurface.getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::copy(srcP, srcP + width2, destP);
@@ -491,7 +491,7 @@ error("TODO: var22/var24/var2C not initialised before use?");
// loc_27477
if (destFlags & DISPFLAG_8) {
// loc_27481
- destP = (byte *)_screenSurface.pixels + screenOffset;
+ destP = (byte *)_screenSurface.getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::fill(srcP, srcP + width2, onOff);
destP += width2 + widthDiff2;
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index f39d9be9d0..871fc41d25 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -502,8 +502,8 @@ void VoyeurEngine::doOpening() {
if (decoder.needsUpdate()) {
const Graphics::Surface *frame = decoder.decodeNextFrame();
- Common::copy((byte *)frame->pixels, (byte *)frame->pixels + 320 * 200,
- (byte *)_graphicsManager._screenSurface.pixels);
+ Common::copy((byte *)frame->getPixels(), (byte *)frame->getPixels() + 320 * 200,
+ (byte *)_graphicsManager._screenSurface.getPixels());
}
_eventsManager.pollEvents();
@@ -526,8 +526,8 @@ void VoyeurEngine::playRL2Video(const Common::String &filename) {
if (decoder.needsUpdate()) {
const Graphics::Surface *frame = decoder.decodeNextFrame();
- Common::copy((byte *)frame->pixels, (byte *)frame->pixels + 320 * 200,
- (byte *)_graphicsManager._screenSurface.pixels);
+ Common::copy((byte *)frame->getPixels(), (byte *)frame->getPixels() + 320 * 200,
+ (byte *)_graphicsManager._screenSurface.getPixels());
}
_eventsManager.pollEvents();
diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp
index e4c18d6287..33ad39b411 100644
--- a/engines/wintermute/ad/ad_actor.cpp
+++ b/engines/wintermute/ad/ad_actor.cpp
@@ -119,7 +119,7 @@ AdActor::~AdActor() {
//////////////////////////////////////////////////////////////////////////
bool AdActor::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdActor::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -179,7 +179,7 @@ TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF(ANIMATION)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdActor::loadBuffer(byte *buffer, bool complete) {
+bool AdActor::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ACTOR)
TOKEN_TABLE(X)
@@ -219,12 +219,12 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(ANIMATION)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ACTOR) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ACTOR) {
_gameRef->LOG(0, "'ACTOR' keyword expected.");
return STATUS_FAILED;
}
@@ -234,55 +234,55 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
AdGame *adGame = (AdGame *)_gameRef;
AdSpriteSet *spr = nullptr;
int ar = 0, ag = 0, ab = 0, alpha = 0;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_FONT:
- setFont((char *)params);
+ setFont(params);
break;
case TOKEN_SCALABLE:
- parser.scanStr((char *)params, "%b", &_zoomable);
+ parser.scanStr(params, "%b", &_zoomable);
break;
case TOKEN_ROTABLE:
case TOKEN_ROTATABLE:
- parser.scanStr((char *)params, "%b", &_rotatable);
+ parser.scanStr(params, "%b", &_rotatable);
break;
case TOKEN_REGISTRABLE:
case TOKEN_INTERACTIVE:
- parser.scanStr((char *)params, "%b", &_registrable);
+ parser.scanStr(params, "%b", &_registrable);
break;
case TOKEN_SHADOWABLE:
case TOKEN_COLORABLE:
- parser.scanStr((char *)params, "%b", &_shadowable);
+ parser.scanStr(params, "%b", &_shadowable);
break;
case TOKEN_ACTIVE:
- parser.scanStr((char *)params, "%b", &_active);
+ parser.scanStr(params, "%b", &_active);
break;
case TOKEN_WALK:
@@ -348,7 +348,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_CURSOR:
@@ -362,12 +362,12 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SOUND_VOLUME:
- parser.scanStr((char *)params, "%d", &_sFXVolume);
+ parser.scanStr(params, "%d", &_sFXVolume);
break;
case TOKEN_SCALE: {
int s;
- parser.scanStr((char *)params, "%d", &s);
+ parser.scanStr(params, "%d", &s);
_scale = (float)s;
}
@@ -375,14 +375,14 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
case TOKEN_RELATIVE_SCALE: {
int s;
- parser.scanStr((char *)params, "%d", &s);
+ parser.scanStr(params, "%d", &s);
_relativeScale = (float)s;
}
break;
case TOKEN_SOUND_PANNING:
- parser.scanStr((char *)params, "%b", &_autoSoundPanning);
+ parser.scanStr(params, "%b", &_autoSoundPanning);
break;
case TOKEN_PROPERTY:
@@ -432,15 +432,15 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_IGNORE_ITEMS:
- parser.scanStr((char *)params, "%b", &_ignoreItems);
+ parser.scanStr(params, "%b", &_ignoreItems);
break;
case TOKEN_ALPHA_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
break;
case TOKEN_ALPHA:
- parser.scanStr((char *)params, "%d", &alpha);
+ parser.scanStr(params, "%d", &alpha);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -1319,29 +1319,29 @@ BaseSprite *AdActor::getTalkStanceOld(const char *stance) {
bool AdActor::persist(BasePersistenceManager *persistMgr) {
AdTalkHolder::persist(persistMgr);
- persistMgr->transfer(TMEMBER_INT(_dir));
+ persistMgr->transferSint32(TMEMBER_INT(_dir));
persistMgr->transferPtr(TMEMBER_PTR(_path));
- persistMgr->transfer(TMEMBER(_pFCount));
- persistMgr->transfer(TMEMBER(_pFStepX));
- persistMgr->transfer(TMEMBER(_pFStepY));
- persistMgr->transfer(TMEMBER(_pFX));
- persistMgr->transfer(TMEMBER(_pFY));
+ persistMgr->transferSint32(TMEMBER(_pFCount));
+ persistMgr->transferDouble(TMEMBER(_pFStepX));
+ persistMgr->transferDouble(TMEMBER(_pFStepY));
+ persistMgr->transferDouble(TMEMBER(_pFX));
+ persistMgr->transferDouble(TMEMBER(_pFY));
persistMgr->transferPtr(TMEMBER_PTR(_standSprite));
_talkSprites.persist(persistMgr);
_talkSpritesEx.persist(persistMgr);
- persistMgr->transfer(TMEMBER_INT(_targetDir));
- persistMgr->transfer(TMEMBER_INT(_afterWalkDir));
+ persistMgr->transferSint32(TMEMBER_INT(_targetDir));
+ persistMgr->transferSint32(TMEMBER_INT(_afterWalkDir));
persistMgr->transferPtr(TMEMBER_PTR(_targetPoint));
persistMgr->transferPtr(TMEMBER_PTR(_turnLeftSprite));
persistMgr->transferPtr(TMEMBER_PTR(_turnRightSprite));
persistMgr->transferPtr(TMEMBER_PTR(_walkSprite));
persistMgr->transferPtr(TMEMBER_PTR(_animSprite2));
- persistMgr->transfer(TMEMBER(_talkAnimName));
- persistMgr->transfer(TMEMBER(_idleAnimName));
- persistMgr->transfer(TMEMBER(_walkAnimName));
- persistMgr->transfer(TMEMBER(_turnLeftAnimName));
- persistMgr->transfer(TMEMBER(_turnRightAnimName));
+ persistMgr->transferString(TMEMBER(_talkAnimName));
+ persistMgr->transferString(TMEMBER(_idleAnimName));
+ persistMgr->transferString(TMEMBER(_walkAnimName));
+ persistMgr->transferString(TMEMBER(_turnLeftAnimName));
+ persistMgr->transferString(TMEMBER(_turnRightAnimName));
_anims.persist(persistMgr);
@@ -1376,7 +1376,7 @@ TDirection AdActor::angleToDirection(int angle) {
//////////////////////////////////////////////////////////////////////////
-int AdActor::getHeight() {
+int32 AdActor::getHeight() {
// if no current sprite is set, set some
if (_currentSprite == nullptr) {
if (_standSprite) {
@@ -1410,20 +1410,20 @@ bool AdActor::mergeAnims(const char *animsFilename) {
TOKEN_TABLE_END
- byte *fileBuffer = BaseFileManager::getEngineInstance()->readWholeFile(animsFilename);
+ char *fileBuffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(animsFilename);
if (fileBuffer == nullptr) {
_gameRef->LOG(0, "AdActor::MergeAnims failed for file '%s'", animsFilename);
return STATUS_FAILED;
}
- byte *buffer = fileBuffer;
- byte *params;
+ char *buffer = fileBuffer;
+ char *params;
int cmd;
BaseParser parser;
bool ret = STATUS_OK;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_ANIMATION: {
AdSpriteSet *anim = new AdSpriteSet(_gameRef, this);
@@ -1457,4 +1457,4 @@ bool AdActor::playAnim(const char *filename) {
return AdTalkHolder::playAnim(filename);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h
index 3630c6665b..3225eb44ec 100644
--- a/engines/wintermute/ad/ad_actor.h
+++ b/engines/wintermute/ad/ad_actor.h
@@ -47,7 +47,7 @@ class AdActor : public AdTalkHolder {
public:
TDirection angleToDirection(int angle);
DECLARE_PERSISTENT(AdActor, AdTalkHolder)
- virtual int getHeight();
+ virtual int32 getHeight() override;
BaseSprite *getTalkStance(const char *stance);
virtual void goTo(int x, int y, TDirection afterWalkDir = DI_NONE);
BasePoint *_targetPoint;
@@ -57,7 +57,7 @@ public:
AdActor(BaseGame *inGame/*=nullptr*/);
virtual ~AdActor();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
private:
@@ -103,6 +103,6 @@ private:
int32 _pFCount;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp
index c43f74b620..098da49750 100644
--- a/engines/wintermute/ad/ad_entity.cpp
+++ b/engines/wintermute/ad/ad_entity.cpp
@@ -100,7 +100,7 @@ const char *AdEntity::getItemName() const {
//////////////////////////////////////////////////////////////////////////
bool AdEntity::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdEntity::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -166,7 +166,7 @@ TOKEN_DEF(WALK_TO_DIR)
TOKEN_DEF(SAVE_STATE)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdEntity::loadBuffer(byte *buffer, bool complete) {
+bool AdEntity::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ENTITY)
TOKEN_TABLE(SPRITE)
@@ -212,12 +212,12 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(SAVE_STATE)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ENTITY) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ENTITY) {
_gameRef->LOG(0, "'ENTITY' keyword expected.");
return STATUS_FAILED;
}
@@ -227,27 +227,27 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
AdGame *adGame = (AdGame *)_gameRef;
BaseSprite *spr = nullptr;
int ar = 0, ag = 0, ab = 0, alpha = 0;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_SPRITE: {
delete _sprite;
_sprite = nullptr;
spr = new BaseSprite(_gameRef, this);
- if (!spr || DID_FAIL(spr->loadFile((char *)params))) {
+ if (!spr || DID_FAIL(spr->loadFile(params))) {
cmd = PARSERR_GENERIC;
} else {
_sprite = spr;
@@ -257,7 +257,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
case TOKEN_TALK: {
spr = new BaseSprite(_gameRef, this);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, adGame->_texTalkLifeTime))) {
cmd = PARSERR_GENERIC;
} else {
_talkSprites.add(spr);
@@ -267,7 +267,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
case TOKEN_TALK_SPECIAL: {
spr = new BaseSprite(_gameRef, this);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, adGame->_texTalkLifeTime))) {
cmd = PARSERR_GENERIC;
} else {
_talkSpritesEx.add(spr);
@@ -276,28 +276,28 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_ITEM:
- setItem((char *)params);
+ setItem(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_FONT:
- setFont((char *)params);
+ setFont(params);
break;
case TOKEN_SCALABLE:
- parser.scanStr((char *)params, "%b", &_zoomable);
+ parser.scanStr(params, "%b", &_zoomable);
break;
case TOKEN_SCALE: {
int s;
- parser.scanStr((char *)params, "%d", &s);
+ parser.scanStr(params, "%d", &s);
_scale = (float)s;
}
@@ -305,7 +305,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
case TOKEN_RELATIVE_SCALE: {
int s;
- parser.scanStr((char *)params, "%d", &s);
+ parser.scanStr(params, "%d", &s);
_relativeScale = (float)s;
}
@@ -313,27 +313,27 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
case TOKEN_ROTABLE:
case TOKEN_ROTATABLE:
- parser.scanStr((char *)params, "%b", &_rotatable);
+ parser.scanStr(params, "%b", &_rotatable);
break;
case TOKEN_REGISTRABLE:
case TOKEN_INTERACTIVE:
- parser.scanStr((char *)params, "%b", &_registrable);
+ parser.scanStr(params, "%b", &_registrable);
break;
case TOKEN_SHADOWABLE:
case TOKEN_COLORABLE:
- parser.scanStr((char *)params, "%b", &_shadowable);
+ parser.scanStr(params, "%b", &_shadowable);
break;
case TOKEN_ACTIVE:
- parser.scanStr((char *)params, "%b", &_active);
+ parser.scanStr(params, "%b", &_active);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -341,7 +341,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_EDITOR_SELECTED:
- parser.scanStr((char *)params, "%b", &_editorSelected);
+ parser.scanStr(params, "%b", &_editorSelected);
break;
case TOKEN_REGION: {
@@ -402,11 +402,11 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_SUBTYPE: {
- if (scumm_stricmp((char *)params, "sound") == 0) {
+ if (scumm_stricmp(params, "sound") == 0) {
delete _sprite;
_sprite = nullptr;
if (_gameRef->_editorMode) {
@@ -430,23 +430,23 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SOUND:
- playSFX((char *)params, false, false);
+ playSFX(params, false, false);
break;
case TOKEN_SOUND_START_TIME:
- parser.scanStr((char *)params, "%d", &_sFXStart);
+ parser.scanStr(params, "%d", &_sFXStart);
break;
case TOKEN_SOUND_VOLUME:
- parser.scanStr((char *)params, "%d", &_sFXVolume);
+ parser.scanStr(params, "%d", &_sFXVolume);
break;
case TOKEN_SOUND_PANNING:
- parser.scanStr((char *)params, "%b", &_autoSoundPanning);
+ parser.scanStr(params, "%b", &_autoSoundPanning);
break;
case TOKEN_SAVE_STATE:
- parser.scanStr((char *)params, "%b", &_saveState);
+ parser.scanStr(params, "%b", &_saveState);
break;
case TOKEN_PROPERTY:
@@ -454,15 +454,15 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_IGNORE_ITEMS:
- parser.scanStr((char *)params, "%b", &_ignoreItems);
+ parser.scanStr(params, "%b", &_ignoreItems);
break;
case TOKEN_ALPHA_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
break;
case TOKEN_ALPHA:
- parser.scanStr((char *)params, "%d", &alpha);
+ parser.scanStr(params, "%d", &alpha);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -470,16 +470,16 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_WALK_TO_X:
- parser.scanStr((char *)params, "%d", &_walkToX);
+ parser.scanStr(params, "%d", &_walkToX);
break;
case TOKEN_WALK_TO_Y:
- parser.scanStr((char *)params, "%d", &_walkToY);
+ parser.scanStr(params, "%d", &_walkToY);
break;
case TOKEN_WALK_TO_DIR: {
int i;
- parser.scanStr((char *)params, "%d", &i);
+ parser.scanStr(params, "%d", &i);
if (i < 0) {
i = 0;
}
@@ -1067,7 +1067,7 @@ bool AdEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) {
//////////////////////////////////////////////////////////////////////////
-int AdEntity::getHeight() {
+int32 AdEntity::getHeight() {
if (_region && !_sprite) {
return _region->_rect.bottom - _region->_rect.top;
} else {
@@ -1092,16 +1092,16 @@ void AdEntity::updatePosition() {
bool AdEntity::persist(BasePersistenceManager *persistMgr) {
AdTalkHolder::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_item));
+ persistMgr->transferCharPtr(TMEMBER(_item));
persistMgr->transferPtr(TMEMBER_PTR(_region));
//persistMgr->transfer(TMEMBER(_sprite));
- persistMgr->transfer(TMEMBER_INT(_subtype));
+ persistMgr->transferSint32(TMEMBER_INT(_subtype));
_talkSprites.persist(persistMgr);
_talkSpritesEx.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_walkToX));
- persistMgr->transfer(TMEMBER(_walkToY));
- persistMgr->transfer(TMEMBER_INT(_walkToDir));
+ persistMgr->transferSint32(TMEMBER(_walkToX));
+ persistMgr->transferSint32(TMEMBER(_walkToY));
+ persistMgr->transferSint32(TMEMBER_INT(_walkToDir));
persistMgr->transferPtr(TMEMBER_PTR(_theora));
@@ -1134,4 +1134,4 @@ bool AdEntity::setSprite(const char *filename) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h
index c23b37366d..c3ed5622e5 100644
--- a/engines/wintermute/ad/ad_entity.h
+++ b/engines/wintermute/ad/ad_entity.h
@@ -40,7 +40,7 @@ public:
void setItem(const char *itemName);
DECLARE_PERSISTENT(AdEntity, AdTalkHolder)
void updatePosition();
- virtual int getHeight();
+ virtual int32 getHeight() override;
BaseRegion *_region;
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
virtual bool update();
@@ -48,7 +48,7 @@ public:
AdEntity(BaseGame *inGame);
virtual ~AdEntity();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
int32 getWalkToX() const;
int32 getWalkToY() const;
@@ -68,6 +68,6 @@ private:
TEntityType _subtype;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp
index ead68f7729..904b8a541c 100644
--- a/engines/wintermute/ad/ad_game.cpp
+++ b/engines/wintermute/ad/ad_game.cpp
@@ -1245,7 +1245,7 @@ bool AdGame::showCursor() {
//////////////////////////////////////////////////////////////////////////
bool AdGame::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdGame::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -1281,7 +1281,7 @@ TOKEN_DEF(STARTUP_SCENE)
TOKEN_DEF(DEBUG_STARTUP_SCENE)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdGame::loadBuffer(byte *buffer, bool complete) {
+bool AdGame::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(GAME)
TOKEN_TABLE(AD_GAME)
@@ -1295,14 +1295,14 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(DEBUG_STARTUP_SCENE)
TOKEN_TABLE_END
- byte *params;
- byte *params2;
+ char *params;
+ char *params2;
int cmd = 1;
BaseParser parser;
bool itemFound = false, itemsFound = false;
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_GAME:
if (DID_FAIL(BaseGame::loadBuffer(params, false))) {
@@ -1311,12 +1311,12 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_AD_GAME:
- while (cmd > 0 && (cmd = parser.getCommand((char **)&params, commands, (char **)&params2)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&params, commands, &params2)) > 0) {
switch (cmd) {
case TOKEN_RESPONSE_BOX:
delete _responseBox;
_responseBox = new AdResponseBox(_gameRef);
- if (_responseBox && !DID_FAIL(_responseBox->loadFile((char *)params2))) {
+ if (_responseBox && !DID_FAIL(_responseBox->loadFile(params2))) {
registerObject(_responseBox);
} else {
delete _responseBox;
@@ -1328,7 +1328,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
case TOKEN_INVENTORY_BOX:
delete _inventoryBox;
_inventoryBox = new AdInventoryBox(_gameRef);
- if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile((char *)params2))) {
+ if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile(params2))) {
registerObject(_inventoryBox);
} else {
delete _inventoryBox;
@@ -1339,7 +1339,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
case TOKEN_ITEMS:
itemsFound = true;
- BaseUtils::setString(&_itemsFile, (char *)params2);
+ BaseUtils::setString(&_itemsFile, params2);
if (DID_FAIL(loadItemsFile(_itemsFile))) {
delete[] _itemsFile;
_itemsFile = nullptr;
@@ -1348,9 +1348,9 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_TALK_SKIP_BUTTON:
- if (scumm_stricmp((char *)params2, "right") == 0) {
+ if (scumm_stricmp(params2, "right") == 0) {
_talkSkipButton = TALK_SKIP_RIGHT;
- } else if (scumm_stricmp((char *)params2, "both") == 0) {
+ } else if (scumm_stricmp(params2, "both") == 0) {
_talkSkipButton = TALK_SKIP_BOTH;
} else {
_talkSkipButton = TALK_SKIP_LEFT;
@@ -1359,7 +1359,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
case TOKEN_SCENE_VIEWPORT: {
Rect32 rc;
- parser.scanStr((char *)params2, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
+ parser.scanStr(params2, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
if (!_sceneViewport) {
_sceneViewport = new BaseViewport(_gameRef);
}
@@ -1374,11 +1374,11 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_STARTUP_SCENE:
- BaseUtils::setString(&_startupScene, (char *)params2);
+ BaseUtils::setString(&_startupScene, params2);
break;
case TOKEN_DEBUG_STARTUP_SCENE:
- BaseUtils::setString(&_debugStartupScene, (char *)params2);
+ BaseUtils::setString(&_debugStartupScene, params2);
break;
}
}
@@ -1417,41 +1417,41 @@ bool AdGame::persist(BasePersistenceManager *persistMgr) {
_objects.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_prevSceneName));
- persistMgr->transfer(TMEMBER(_prevSceneFilename));
+ persistMgr->transferCharPtr(TMEMBER(_prevSceneName));
+ persistMgr->transferCharPtr(TMEMBER(_prevSceneFilename));
persistMgr->transferPtr(TMEMBER_PTR(_responseBox));
_responsesBranch.persist(persistMgr);
_responsesGame.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_scene));
_sceneStates.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scheduledFadeIn));
- persistMgr->transfer(TMEMBER(_scheduledScene));
+ persistMgr->transferBool(TMEMBER(_scheduledFadeIn));
+ persistMgr->transferCharPtr(TMEMBER(_scheduledScene));
persistMgr->transferPtr(TMEMBER_PTR(_selectedItem));
- persistMgr->transfer(TMEMBER_INT(_talkSkipButton));
+ persistMgr->transferSint32(TMEMBER_INT(_talkSkipButton));
_sentences.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_sceneViewport));
- persistMgr->transfer(TMEMBER_INT(_stateEx));
- persistMgr->transfer(TMEMBER(_initialScene));
- persistMgr->transfer(TMEMBER(_debugStartupScene));
+ persistMgr->transferSint32(TMEMBER_INT(_stateEx));
+ persistMgr->transferBool(TMEMBER(_initialScene));
+ persistMgr->transferCharPtr(TMEMBER(_debugStartupScene));
persistMgr->transferPtr(TMEMBER_PTR(_invObject));
persistMgr->transferPtr(TMEMBER_PTR(_inventoryOwner));
- persistMgr->transfer(TMEMBER(_tempDisableSaveState));
+ persistMgr->transferBool(TMEMBER(_tempDisableSaveState));
_items.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_itemsFile));
+ persistMgr->transferCharPtr(TMEMBER(_itemsFile));
_speechDirs.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_smartItemCursor));
+ persistMgr->transferBool(TMEMBER(_smartItemCursor));
if (!persistMgr->getIsSaving()) {
_initialScene = false;
}
- persistMgr->transfer(TMEMBER(_startupScene));
+ persistMgr->transferCharPtr(TMEMBER(_startupScene));
return STATUS_OK;
@@ -1518,7 +1518,7 @@ bool AdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *ex
//////////////////////////////////////////////////////////////////////////
bool AdGame::loadItemsFile(const char *filename, bool merge) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdGame::LoadItemsFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -1541,12 +1541,12 @@ bool AdGame::loadItemsFile(const char *filename, bool merge) {
//////////////////////////////////////////////////////////////////////////
-bool AdGame::loadItemsBuffer(byte *buffer, bool merge) {
+bool AdGame::loadItemsBuffer(char *buffer, bool merge) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ITEM)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
@@ -1556,7 +1556,7 @@ bool AdGame::loadItemsBuffer(byte *buffer, bool merge) {
}
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_ITEM: {
AdItem *item = new AdItem(_gameRef);
@@ -1637,7 +1637,7 @@ bool AdGame::windowLoadHook(UIWindow *win, char **buffer, char **params) {
switch (cmd) {
case TOKEN_ENTITY_CONTAINER: {
UIEntity *ent = new UIEntity(_gameRef);
- if (!ent || DID_FAIL(ent->loadBuffer((byte *)*params, false))) {
+ if (!ent || DID_FAIL(ent->loadBuffer(*params, false))) {
delete ent;
ent = nullptr;
cmd = PARSERR_GENERIC;
@@ -2160,7 +2160,6 @@ bool AdGame::onMouseLeftDown() {
_gameRef->_capturedObject = _gameRef->_activeObject;
}
_mouseLeftDown = true;
- BasePlatform::setCapture(/*_renderer->_window*/);
return STATUS_OK;
}
@@ -2171,7 +2170,6 @@ bool AdGame::onMouseLeftUp() {
_activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT);
}
- BasePlatform::releaseCapture();
_capturedObject = nullptr;
_mouseLeftDown = false;
@@ -2282,4 +2280,4 @@ bool AdGame::onScriptShutdown(ScScript *script) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_game.h b/engines/wintermute/ad/ad_game.h
index 2032a1723f..019f2e6478 100644
--- a/engines/wintermute/ad/ad_game.h
+++ b/engines/wintermute/ad/ad_game.h
@@ -120,10 +120,10 @@ public:
BaseArray<AdObject *> _objects;
virtual bool loadFile(const char *filename);
- virtual bool loadBuffer(byte *buffer, bool complete = true);
+ virtual bool loadBuffer(char *buffer, bool complete = true);
bool loadItemsFile(const char *filename, bool merge = false);
- bool loadItemsBuffer(byte *buffer, bool merge = false);
+ bool loadItemsBuffer(char *buffer, bool merge = false);
// scripting interface
virtual ScValue *scGetProperty(const Common::String &name) override;
@@ -158,6 +158,6 @@ private:
AdInventoryBox *_inventoryBox;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_inventory.cpp b/engines/wintermute/ad/ad_inventory.cpp
index e9b6e56f16..f9352c77c6 100644
--- a/engines/wintermute/ad/ad_inventory.cpp
+++ b/engines/wintermute/ad/ad_inventory.cpp
@@ -128,9 +128,9 @@ bool AdInventory::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
_takenItems.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scrollOffset));
+ persistMgr->transferSint32(TMEMBER(_scrollOffset));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_inventory.h b/engines/wintermute/ad/ad_inventory.h
index 999200b465..9de831b2a0 100644
--- a/engines/wintermute/ad/ad_inventory.h
+++ b/engines/wintermute/ad/ad_inventory.h
@@ -47,6 +47,6 @@ public:
int32 _scrollOffset;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_inventory_box.cpp b/engines/wintermute/ad/ad_inventory_box.cpp
index 110359917b..5d7f053bb5 100644
--- a/engines/wintermute/ad/ad_inventory_box.cpp
+++ b/engines/wintermute/ad/ad_inventory_box.cpp
@@ -120,8 +120,8 @@ bool AdInventoryBox::display() {
if (_closeButton) {
_closeButton->_posX = _closeButton->_posY = 0;
- _closeButton->_width = _gameRef->_renderer->getWidth();
- _closeButton->_height = _gameRef->_renderer->getHeight();
+ _closeButton->setWidth(_gameRef->_renderer->getWidth());
+ _closeButton->setHeight(_gameRef->_renderer->getHeight());
_closeButton->display();
}
@@ -165,7 +165,7 @@ bool AdInventoryBox::display() {
//////////////////////////////////////////////////////////////////////////
bool AdInventoryBox::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdInventoryBox::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -203,7 +203,7 @@ TOKEN_DEF(HIDE_SELECTED)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) {
+bool AdInventoryBox::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(INVENTORY_BOX)
TOKEN_TABLE(TEMPLATE)
@@ -221,34 +221,34 @@ bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
bool alwaysVisible = false;
_exclusive = false;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_INVENTORY_BOX) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_INVENTORY_BOX) {
_gameRef->LOG(0, "'INVENTORY_BOX' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_WINDOW:
@@ -264,35 +264,35 @@ bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_AREA:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_itemsArea.left, &_itemsArea.top, &_itemsArea.right, &_itemsArea.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_itemsArea.left, &_itemsArea.top, &_itemsArea.right, &_itemsArea.bottom);
break;
case TOKEN_EXCLUSIVE:
- parser.scanStr((char *)params, "%b", &_exclusive);
+ parser.scanStr(params, "%b", &_exclusive);
break;
case TOKEN_HIDE_SELECTED:
- parser.scanStr((char *)params, "%b", &_hideSelected);
+ parser.scanStr(params, "%b", &_hideSelected);
break;
case TOKEN_ALWAYS_VISIBLE:
- parser.scanStr((char *)params, "%b", &alwaysVisible);
+ parser.scanStr(params, "%b", &alwaysVisible);
break;
case TOKEN_SPACING:
- parser.scanStr((char *)params, "%d", &_spacing);
+ parser.scanStr(params, "%d", &_spacing);
break;
case TOKEN_ITEM_WIDTH:
- parser.scanStr((char *)params, "%d", &_itemWidth);
+ parser.scanStr(params, "%d", &_itemWidth);
break;
case TOKEN_ITEM_HEIGHT:
- parser.scanStr((char *)params, "%d", &_itemHeight);
+ parser.scanStr(params, "%d", &_itemHeight);
break;
case TOKEN_SCROLL_BY:
- parser.scanStr((char *)params, "%d", &_scrollBy);
+ parser.scanStr(params, "%d", &_scrollBy);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -323,7 +323,7 @@ bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) {
if (_window) {
for (uint32 i = 0; i < _window->_widgets.size(); i++) {
- if (!_window->_widgets[i]->_listenerObject) {
+ if (!_window->_widgets[i]->getListener()) {
_window->_widgets[i]->setListener(this, _window->_widgets[i], 0);
}
}
@@ -372,18 +372,18 @@ bool AdInventoryBox::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_closeButton));
- persistMgr->transfer(TMEMBER(_hideSelected));
- persistMgr->transfer(TMEMBER(_itemHeight));
- persistMgr->transfer(TMEMBER(_itemsArea));
- persistMgr->transfer(TMEMBER(_itemWidth));
- persistMgr->transfer(TMEMBER(_scrollBy));
- persistMgr->transfer(TMEMBER(_scrollOffset));
- persistMgr->transfer(TMEMBER(_spacing));
- persistMgr->transfer(TMEMBER(_visible));
+ persistMgr->transferBool(TMEMBER(_hideSelected));
+ persistMgr->transferSint32(TMEMBER(_itemHeight));
+ persistMgr->transferRect32(TMEMBER(_itemsArea));
+ persistMgr->transferSint32(TMEMBER(_itemWidth));
+ persistMgr->transferSint32(TMEMBER(_scrollBy));
+ persistMgr->transferSint32(TMEMBER(_scrollOffset));
+ persistMgr->transferSint32(TMEMBER(_spacing));
+ persistMgr->transferBool(TMEMBER(_visible));
persistMgr->transferPtr(TMEMBER_PTR(_window));
- persistMgr->transfer(TMEMBER(_exclusive));
+ persistMgr->transferBool(TMEMBER(_exclusive));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_inventory_box.h b/engines/wintermute/ad/ad_inventory_box.h
index 9792b1ea66..4d576625b2 100644
--- a/engines/wintermute/ad/ad_inventory_box.h
+++ b/engines/wintermute/ad/ad_inventory_box.h
@@ -51,7 +51,7 @@ public:
AdInventoryBox(BaseGame *inGame);
virtual ~AdInventoryBox();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
private:
bool _exclusive;
@@ -60,6 +60,6 @@ private:
int32 _itemWidth;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp
index 1a46eb783b..1f19a3eeae 100644
--- a/engines/wintermute/ad/ad_item.cpp
+++ b/engines/wintermute/ad/ad_item.cpp
@@ -84,7 +84,7 @@ AdItem::~AdItem() {
//////////////////////////////////////////////////////////////////////////
bool AdItem::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdItem::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -134,7 +134,7 @@ TOKEN_DEF(AMOUNT_STRING)
TOKEN_DEF(AMOUNT)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdItem::loadBuffer(byte *buffer, bool complete) {
+bool AdItem::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ITEM)
TOKEN_TABLE(TEMPLATE)
@@ -164,12 +164,12 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(AMOUNT)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ITEM) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ITEM) {
_gameRef->LOG(0, "'ITEM' keyword expected.");
return STATUS_FAILED;
}
@@ -177,31 +177,31 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
}
int ar = 0, ag = 0, ab = 0, alpha = 255;
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_FONT:
- setFont((char *)params);
+ setFont(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_IMAGE:
case TOKEN_SPRITE:
delete _sprite;
_sprite = new BaseSprite(_gameRef, this);
- if (!_sprite || DID_FAIL(_sprite->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
+ if (!_sprite || DID_FAIL(_sprite->loadFile(params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
delete _sprite;
cmd = PARSERR_GENERIC;
}
@@ -211,32 +211,32 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
case TOKEN_SPRITE_HOVER:
delete _spriteHover;
_spriteHover = new BaseSprite(_gameRef, this);
- if (!_spriteHover || DID_FAIL(_spriteHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
+ if (!_spriteHover || DID_FAIL(_spriteHover->loadFile(params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
delete _spriteHover;
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_AMOUNT:
- parser.scanStr((char *)params, "%d", &_amount);
+ parser.scanStr(params, "%d", &_amount);
break;
case TOKEN_DISPLAY_AMOUNT:
- parser.scanStr((char *)params, "%b", &_displayAmount);
+ parser.scanStr(params, "%b", &_displayAmount);
break;
case TOKEN_AMOUNT_OFFSET_X:
- parser.scanStr((char *)params, "%d", &_amountOffsetX);
+ parser.scanStr(params, "%d", &_amountOffsetX);
break;
case TOKEN_AMOUNT_OFFSET_Y:
- parser.scanStr((char *)params, "%d", &_amountOffsetY);
+ parser.scanStr(params, "%d", &_amountOffsetY);
break;
case TOKEN_AMOUNT_ALIGN:
- if (scumm_stricmp((char *)params, "left") == 0) {
+ if (scumm_stricmp(params, "left") == 0) {
_amountAlign = TAL_LEFT;
- } else if (scumm_stricmp((char *)params, "right") == 0) {
+ } else if (scumm_stricmp(params, "right") == 0) {
_amountAlign = TAL_RIGHT;
} else {
_amountAlign = TAL_CENTER;
@@ -244,12 +244,12 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_AMOUNT_STRING:
- BaseUtils::setString(&_amountString, (char *)params);
+ BaseUtils::setString(&_amountString, params);
break;
case TOKEN_TALK: {
BaseSprite *spr = new BaseSprite(_gameRef, this);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, ((AdGame *)_gameRef)->_texTalkLifeTime))) {
cmd = PARSERR_GENERIC;
} else {
_talkSprites.add(spr);
@@ -259,7 +259,7 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
case TOKEN_TALK_SPECIAL: {
BaseSprite *spr = new BaseSprite(_gameRef, this);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, ((AdGame *)_gameRef)->_texTalkLifeTime))) {
cmd = PARSERR_GENERIC;
} else {
_talkSpritesEx.add(spr);
@@ -270,7 +270,7 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
case TOKEN_CURSOR:
delete _cursorNormal;
_cursorNormal = new BaseSprite(_gameRef);
- if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
+ if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile(params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
delete _cursorNormal;
_cursorNormal = nullptr;
cmd = PARSERR_GENERIC;
@@ -280,7 +280,7 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
case TOKEN_CURSOR_HOVER:
delete _cursorHover;
_cursorHover = new BaseSprite(_gameRef);
- if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
+ if (!_cursorHover || DID_FAIL(_cursorHover->loadFile(params, ((AdGame *)_gameRef)->_texItemLifeTime))) {
delete _cursorHover;
_cursorHover = nullptr;
cmd = PARSERR_GENERIC;
@@ -288,11 +288,11 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_CURSOR_COMBINED:
- parser.scanStr((char *)params, "%b", &_cursorCombined);
+ parser.scanStr(params, "%b", &_cursorCombined);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PROPERTY:
@@ -300,11 +300,11 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_ALPHA_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
break;
case TOKEN_ALPHA:
- parser.scanStr((char *)params, "%d", &alpha);
+ parser.scanStr(params, "%d", &alpha);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -783,17 +783,17 @@ bool AdItem::persist(BasePersistenceManager *persistMgr) {
AdTalkHolder::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_cursorCombined));
+ persistMgr->transferBool(TMEMBER(_cursorCombined));
persistMgr->transferPtr(TMEMBER_PTR(_cursorHover));
persistMgr->transferPtr(TMEMBER_PTR(_cursorNormal));
persistMgr->transferPtr(TMEMBER_PTR(_spriteHover));
- persistMgr->transfer(TMEMBER(_inInventory));
- persistMgr->transfer(TMEMBER(_displayAmount));
- persistMgr->transfer(TMEMBER(_amount));
- persistMgr->transfer(TMEMBER(_amountOffsetX));
- persistMgr->transfer(TMEMBER(_amountOffsetY));
- persistMgr->transfer(TMEMBER_INT(_amountAlign));
- persistMgr->transfer(TMEMBER(_amountString));
+ persistMgr->transferBool(TMEMBER(_inInventory));
+ persistMgr->transferBool(TMEMBER(_displayAmount));
+ persistMgr->transferSint32(TMEMBER(_amount));
+ persistMgr->transferSint32(TMEMBER(_amountOffsetX));
+ persistMgr->transferSint32(TMEMBER(_amountOffsetY));
+ persistMgr->transferSint32(TMEMBER_INT(_amountAlign));
+ persistMgr->transferCharPtr(TMEMBER(_amountString));
return STATUS_OK;
}
@@ -810,4 +810,4 @@ bool AdItem::getExtendedFlag(const char *flagName) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_item.h b/engines/wintermute/ad/ad_item.h
index b8351448a7..935ea5d73d 100644
--- a/engines/wintermute/ad/ad_item.h
+++ b/engines/wintermute/ad/ad_item.h
@@ -35,6 +35,8 @@
namespace Wintermute {
class AdItem : public AdTalkHolder {
+ using Wintermute::AdObject::display;
+
public:
bool update();
DECLARE_PERSISTENT(AdItem, AdTalkHolder)
@@ -48,7 +50,7 @@ public:
AdItem(BaseGame *inGame);
virtual ~AdItem();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
// scripting interface
virtual ScValue *scGetProperty(const Common::String &name) override;
@@ -64,6 +66,6 @@ private:
char *_amountString;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp
index 7bf79e4ae5..17dd83a8b7 100644
--- a/engines/wintermute/ad/ad_layer.cpp
+++ b/engines/wintermute/ad/ad_layer.cpp
@@ -62,7 +62,7 @@ AdLayer::~AdLayer() {
//////////////////////////////////////////////////////////////////////////
bool AdLayer::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdLayer::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -100,7 +100,7 @@ TOKEN_DEF(CLOSE_UP)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdLayer::loadBuffer(byte *buffer, bool complete) {
+bool AdLayer::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(LAYER)
TOKEN_TABLE(TEMPLATE)
@@ -119,52 +119,52 @@ bool AdLayer::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_LAYER) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_LAYER) {
_gameRef->LOG(0, "'LAYER' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_MAIN:
- parser.scanStr((char *)params, "%b", &_main);
+ parser.scanStr(params, "%b", &_main);
break;
case TOKEN_CLOSE_UP:
- parser.scanStr((char *)params, "%b", &_closeUp);
+ parser.scanStr(params, "%b", &_closeUp);
break;
case TOKEN_WIDTH:
- parser.scanStr((char *)params, "%d", &_width);
+ parser.scanStr(params, "%d", &_width);
break;
case TOKEN_HEIGHT:
- parser.scanStr((char *)params, "%d", &_height);
+ parser.scanStr(params, "%d", &_height);
break;
case TOKEN_ACTIVE:
- parser.scanStr((char *)params, "%b", &_active);
+ parser.scanStr(params, "%b", &_active);
break;
case TOKEN_REGION: {
@@ -203,11 +203,11 @@ bool AdLayer::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_EDITOR_SELECTED:
- parser.scanStr((char *)params, "%b", &_editorSelected);
+ parser.scanStr(params, "%b", &_editorSelected);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PROPERTY:
@@ -551,14 +551,14 @@ bool AdLayer::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_active));
- persistMgr->transfer(TMEMBER(_closeUp));
- persistMgr->transfer(TMEMBER(_height));
- persistMgr->transfer(TMEMBER(_main));
+ persistMgr->transferBool(TMEMBER(_active));
+ persistMgr->transferBool(TMEMBER(_closeUp));
+ persistMgr->transferSint32(TMEMBER(_height));
+ persistMgr->transferBool(TMEMBER(_main));
_nodes.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_width));
+ persistMgr->transferSint32(TMEMBER(_width));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_layer.h b/engines/wintermute/ad/ad_layer.h
index 8fe4d4f91e..af7c3a364c 100644
--- a/engines/wintermute/ad/ad_layer.h
+++ b/engines/wintermute/ad/ad_layer.h
@@ -43,7 +43,7 @@ public:
virtual ~AdLayer();
BaseArray<AdSceneNode *> _nodes;
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
// scripting interface
@@ -53,6 +53,6 @@ public:
virtual const char *scToString() override;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_node_state.cpp b/engines/wintermute/ad/ad_node_state.cpp
index d52201a08d..dd07f23762 100644
--- a/engines/wintermute/ad/ad_node_state.cpp
+++ b/engines/wintermute/ad/ad_node_state.cpp
@@ -95,13 +95,13 @@ void AdNodeState::setCursor(const char *filename) {
bool AdNodeState::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_active));
- persistMgr->transfer(TMEMBER(_name));
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_cursor));
- persistMgr->transfer(TMEMBER(_alphaColor));
+ persistMgr->transferBool(TMEMBER(_active));
+ persistMgr->transferCharPtr(TMEMBER(_name));
+ persistMgr->transferCharPtr(TMEMBER(_filename));
+ persistMgr->transferCharPtr(TMEMBER(_cursor));
+ persistMgr->transferUint32(TMEMBER(_alphaColor));
for (int i = 0; i < 7; i++) {
- persistMgr->transfer(TMEMBER(_caption[i]));
+ persistMgr->transferCharPtr(TMEMBER(_caption[i]));
}
return STATUS_OK;
@@ -192,4 +192,4 @@ bool AdNodeState::transferEntity(AdEntity *entity, bool includingSprites, bool s
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_node_state.h b/engines/wintermute/ad/ad_node_state.h
index e2050815a7..4b5b46ee60 100644
--- a/engines/wintermute/ad/ad_node_state.h
+++ b/engines/wintermute/ad/ad_node_state.h
@@ -55,6 +55,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_object.cpp b/engines/wintermute/ad/ad_object.cpp
index 741d6e6fc6..3664e0fd8a 100644
--- a/engines/wintermute/ad/ad_object.cpp
+++ b/engines/wintermute/ad/ad_object.cpp
@@ -859,7 +859,7 @@ bool AdObject::setFont(const char *filename) {
//////////////////////////////////////////////////////////////////////////
-int AdObject::getHeight() {
+int32 AdObject::getHeight() {
if (!_currentSprite) {
return 0;
} else {
@@ -1030,30 +1030,30 @@ bool AdObject::reset() {
bool AdObject::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_active));
+ persistMgr->transferBool(TMEMBER(_active));
persistMgr->transferPtr(TMEMBER_PTR(_blockRegion));
persistMgr->transferPtr(TMEMBER_PTR(_currentBlockRegion));
persistMgr->transferPtr(TMEMBER_PTR(_currentWptGroup));
persistMgr->transferPtr(TMEMBER_PTR(_currentSprite));
- persistMgr->transfer(TMEMBER(_drawn));
+ persistMgr->transferBool(TMEMBER(_drawn));
persistMgr->transferPtr(TMEMBER_PTR(_font));
- persistMgr->transfer(TMEMBER(_ignoreItems));
- persistMgr->transfer(TMEMBER_INT(_nextState));
+ persistMgr->transferBool(TMEMBER(_ignoreItems));
+ persistMgr->transferSint32(TMEMBER_INT(_nextState));
persistMgr->transferPtr(TMEMBER_PTR(_sentence));
- persistMgr->transfer(TMEMBER_INT(_state));
+ persistMgr->transferSint32(TMEMBER_INT(_state));
persistMgr->transferPtr(TMEMBER_PTR(_animSprite));
- persistMgr->transfer(TMEMBER(_sceneIndependent));
- persistMgr->transfer(TMEMBER(_forcedTalkAnimName));
- persistMgr->transfer(TMEMBER(_forcedTalkAnimUsed));
+ persistMgr->transferBool(TMEMBER(_sceneIndependent));
+ persistMgr->transferCharPtr(TMEMBER(_forcedTalkAnimName));
+ persistMgr->transferBool(TMEMBER(_forcedTalkAnimUsed));
persistMgr->transferPtr(TMEMBER_PTR(_tempSprite2));
- persistMgr->transfer(TMEMBER_INT(_type));
+ persistMgr->transferSint32(TMEMBER_INT(_type));
persistMgr->transferPtr(TMEMBER_PTR(_wptGroup));
persistMgr->transferPtr(TMEMBER_PTR(_stickRegion));
- persistMgr->transfer(TMEMBER(_subtitlesModRelative));
- persistMgr->transfer(TMEMBER(_subtitlesModX));
- persistMgr->transfer(TMEMBER(_subtitlesModY));
- persistMgr->transfer(TMEMBER(_subtitlesModXCenter));
- persistMgr->transfer(TMEMBER(_subtitlesWidth));
+ persistMgr->transferBool(TMEMBER(_subtitlesModRelative));
+ persistMgr->transferSint32(TMEMBER(_subtitlesModX));
+ persistMgr->transferSint32(TMEMBER(_subtitlesModY));
+ persistMgr->transferBool(TMEMBER(_subtitlesModXCenter));
+ persistMgr->transferSint32(TMEMBER(_subtitlesWidth));
persistMgr->transferPtr(TMEMBER_PTR(_inventory));
persistMgr->transferPtr(TMEMBER_PTR(_partEmitter));
@@ -1065,9 +1065,9 @@ bool AdObject::persist(BasePersistenceManager *persistMgr) {
_attachmentsPost.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_registerAlias));
- persistMgr->transfer(TMEMBER(_partFollowParent));
- persistMgr->transfer(TMEMBER(_partOffsetX));
- persistMgr->transfer(TMEMBER(_partOffsetY));
+ persistMgr->transferBool(TMEMBER(_partFollowParent));
+ persistMgr->transferSint32(TMEMBER(_partOffsetX));
+ persistMgr->transferSint32(TMEMBER(_partOffsetY));
return STATUS_OK;
}
@@ -1299,4 +1299,4 @@ bool AdObject::updatePartEmitter() {
return _partEmitter->update();
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_object.h b/engines/wintermute/ad/ad_object.h
index c6573315da..ba984ef8d1 100644
--- a/engines/wintermute/ad/ad_object.h
+++ b/engines/wintermute/ad/ad_object.h
@@ -61,7 +61,7 @@ public:
bool reset();
DECLARE_PERSISTENT(AdObject, BaseObject)
virtual void talk(const char *text, const char *sound = nullptr, uint32 duration = 0, const char *stances = nullptr, TTextAlign align = TAL_CENTER);
- virtual int getHeight() override;
+ virtual int32 getHeight() override;
bool setFont(const char *filename);
virtual bool update() override;
@@ -123,6 +123,6 @@ private:
AdInventory *_inventory;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_path.cpp b/engines/wintermute/ad/ad_path.cpp
index 5b36ed6471..156fc80958 100644
--- a/engines/wintermute/ad/ad_path.cpp
+++ b/engines/wintermute/ad/ad_path.cpp
@@ -110,11 +110,11 @@ bool AdPath::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_currIndex));
+ persistMgr->transferSint32(TMEMBER(_currIndex));
_points.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_ready));
+ persistMgr->transferBool(TMEMBER(_ready));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_path.h b/engines/wintermute/ad/ad_path.h
index 3f38355b94..9de0bcad2c 100644
--- a/engines/wintermute/ad/ad_path.h
+++ b/engines/wintermute/ad/ad_path.h
@@ -51,6 +51,6 @@ public:
bool _ready;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_path_point.cpp b/engines/wintermute/ad/ad_path_point.cpp
index be4b487466..5ee9568608 100644
--- a/engines/wintermute/ad/ad_path_point.cpp
+++ b/engines/wintermute/ad/ad_path_point.cpp
@@ -65,11 +65,11 @@ bool AdPathPoint::persist(BasePersistenceManager *persistMgr) {
BasePoint::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_distance));
- persistMgr->transfer(TMEMBER(_marked));
+ persistMgr->transferSint32(TMEMBER(_distance));
+ persistMgr->transferBool(TMEMBER(_marked));
persistMgr->transferPtr(TMEMBER_PTR(_origin));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_path_point.h b/engines/wintermute/ad/ad_path_point.h
index 04648b1733..5e6b8c61ea 100644
--- a/engines/wintermute/ad/ad_path_point.h
+++ b/engines/wintermute/ad/ad_path_point.h
@@ -45,6 +45,6 @@ public:
int32 _distance;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp
index acd5f13397..2e8e73a1cf 100644
--- a/engines/wintermute/ad/ad_region.cpp
+++ b/engines/wintermute/ad/ad_region.cpp
@@ -69,7 +69,7 @@ bool AdRegion::hasDecoration() const {
//////////////////////////////////////////////////////////////////////////
bool AdRegion::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdRegion::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -110,7 +110,7 @@ TOKEN_DEF(PROPERTY)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdRegion::loadBuffer(byte *buffer, bool complete) {
+bool AdRegion::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(REGION)
TOKEN_TABLE(TEMPLATE)
@@ -131,12 +131,12 @@ bool AdRegion::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_REGION) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_REGION) {
_gameRef->LOG(0, "'REGION' keyword expected.");
return STATUS_FAILED;
}
@@ -150,67 +150,67 @@ bool AdRegion::loadBuffer(byte *buffer, bool complete) {
int ar = 255, ag = 255, ab = 255, alpha = 255;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_ACTIVE:
- parser.scanStr((char *)params, "%b", &_active);
+ parser.scanStr(params, "%b", &_active);
break;
case TOKEN_BLOCKED:
- parser.scanStr((char *)params, "%b", &_blocked);
+ parser.scanStr(params, "%b", &_blocked);
break;
case TOKEN_DECORATION:
- parser.scanStr((char *)params, "%b", &_decoration);
+ parser.scanStr(params, "%b", &_decoration);
break;
case TOKEN_ZOOM:
case TOKEN_SCALE: {
int j;
- parser.scanStr((char *)params, "%d", &j);
+ parser.scanStr(params, "%d", &j);
_zoom = (float)j;
}
break;
case TOKEN_POINT: {
int x, y;
- parser.scanStr((char *)params, "%d,%d", &x, &y);
+ parser.scanStr(params, "%d,%d", &x, &y);
_points.add(new BasePoint(x, y));
}
break;
case TOKEN_ALPHA_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
break;
case TOKEN_ALPHA:
- parser.scanStr((char *)params, "%d", &alpha);
+ parser.scanStr(params, "%d", &alpha);
break;
case TOKEN_EDITOR_SELECTED:
- parser.scanStr((char *)params, "%b", &_editorSelected);
+ parser.scanStr(params, "%b", &_editorSelected);
break;
case TOKEN_EDITOR_SELECTED_POINT:
- parser.scanStr((char *)params, "%d", &_editorSelectedPoint);
+ parser.scanStr(params, "%d", &_editorSelectedPoint);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PROPERTY:
@@ -401,12 +401,12 @@ bool AdRegion::saveAsText(BaseDynamicBuffer *buffer, int indent) {
bool AdRegion::persist(BasePersistenceManager *persistMgr) {
BaseRegion::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_alpha));
- persistMgr->transfer(TMEMBER(_blocked));
- persistMgr->transfer(TMEMBER(_decoration));
- persistMgr->transfer(TMEMBER(_zoom));
+ persistMgr->transferUint32(TMEMBER(_alpha));
+ persistMgr->transferBool(TMEMBER(_blocked));
+ persistMgr->transferBool(TMEMBER(_decoration));
+ persistMgr->transferFloat(TMEMBER(_zoom));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_region.h b/engines/wintermute/ad/ad_region.h
index bc9eab085e..f3674dcbfb 100644
--- a/engines/wintermute/ad/ad_region.h
+++ b/engines/wintermute/ad/ad_region.h
@@ -40,7 +40,7 @@ public:
AdRegion(BaseGame *inGame);
virtual ~AdRegion();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
bool hasDecoration() const;
@@ -59,6 +59,6 @@ private:
bool _decoration;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp
index 4483bbc667..e7b4188de6 100644
--- a/engines/wintermute/ad/ad_response.cpp
+++ b/engines/wintermute/ad/ad_response.cpp
@@ -134,10 +134,10 @@ bool AdResponse::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_icon));
persistMgr->transferPtr(TMEMBER_PTR(_iconHover));
persistMgr->transferPtr(TMEMBER_PTR(_iconPressed));
- persistMgr->transfer(TMEMBER(_iD));
- persistMgr->transfer(TMEMBER(_text));
- persistMgr->transfer(TMEMBER(_textOrig));
- persistMgr->transfer(TMEMBER_INT(_responseType));
+ persistMgr->transferSint32(TMEMBER(_iD));
+ persistMgr->transferCharPtr(TMEMBER(_text));
+ persistMgr->transferCharPtr(TMEMBER(_textOrig));
+ persistMgr->transferSint32(TMEMBER_INT(_responseType));
persistMgr->transferPtr(TMEMBER_PTR(_font));
return STATUS_OK;
@@ -166,7 +166,7 @@ BaseFont *AdResponse::getFont() const {
int32 AdResponse::getID() const {
return _iD;
}
-
+
const char *AdResponse::getText() const {
return _text;
}
@@ -175,4 +175,4 @@ const char *AdResponse::getTextOrig() const {
return _textOrig;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_response.h b/engines/wintermute/ad/ad_response.h
index 57cd302e9d..00ebafbdb0 100644
--- a/engines/wintermute/ad/ad_response.h
+++ b/engines/wintermute/ad/ad_response.h
@@ -68,6 +68,6 @@ private:
char *_textOrig;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp
index a589bf3a30..f2e986cbdc 100644
--- a/engines/wintermute/ad/ad_response_box.cpp
+++ b/engines/wintermute/ad/ad_response_box.cpp
@@ -58,7 +58,7 @@ AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) {
_shieldWindow = new UIWindow(_gameRef);
_horizontal = false;
- BasePlatform::setRectEmpty(&_responseArea);
+ _responseArea.setEmpty();
_scrollOffset = 0;
_spacing = 0;
@@ -121,12 +121,12 @@ void AdResponseBox::clearButtons() {
//////////////////////////////////////////////////////////////////////////
bool AdResponseBox::invalidateButtons() {
for (uint32 i = 0; i < _respButtons.size(); i++) {
- _respButtons[i]->_image = nullptr;
- _respButtons[i]->_cursor = nullptr;
- _respButtons[i]->_font = nullptr;
- _respButtons[i]->_fontHover = nullptr;
- _respButtons[i]->_fontPress = nullptr;
+ _respButtons[i]->setImage(nullptr);
+ _respButtons[i]->setFont(nullptr);
_respButtons[i]->setText("");
+ _respButtons[i]->_cursor = nullptr;
+ _respButtons[i]->setFontHover(nullptr);
+ _respButtons[i]->setFontPress(nullptr);
}
return STATUS_OK;
}
@@ -141,16 +141,17 @@ bool AdResponseBox::createButtons() {
UIButton *btn = new UIButton(_gameRef);
if (btn) {
btn->_parent = _window;
- btn->_sharedFonts = btn->_sharedImages = true;
+ btn->setSharedFonts(true);
+ btn->setSharedImages(true);
btn->_sharedCursors = true;
// iconic
if (_responses[i]->getIcon()) {
- btn->_image = _responses[i]->getIcon();
+ btn->setImage(_responses[i]->getIcon());
if (_responses[i]->getIconHover()) {
- btn->_imageHover = _responses[i]->getIconHover();
+ btn->setImageHover(_responses[i]->getIconHover());
}
if (_responses[i]->getIconPressed()) {
- btn->_imagePress = _responses[i]->getIconPressed();
+ btn->setImagePress(_responses[i]->getIconPressed());
}
btn->setCaption(_responses[i]->getText());
@@ -163,23 +164,30 @@ bool AdResponseBox::createButtons() {
// textual
else {
btn->setText(_responses[i]->getText());
- btn->_font = (_font == nullptr) ? _gameRef->getSystemFont() : _font;
- btn->_fontHover = (_fontHover == nullptr) ? _gameRef->getSystemFont() : _fontHover;
- btn->_fontPress = btn->_fontHover;
- btn->_align = _align;
+ if (_font == nullptr) {
+ btn->setFont(_gameRef->getSystemFont());
+ } else {
+ btn->setFont(_font);
+ }
+ btn->setFontHover((_fontHover == nullptr) ? _gameRef->getSystemFont() : _fontHover);
+ btn->setFontPress(btn->getFontHover());
+ btn->setTextAlign(_align);
if (_gameRef->_touchInterface) {
- btn->_fontHover = btn->_font;
+ btn->setFontHover(btn->getFont());
}
if (_responses[i]->getFont()) {
- btn->_font = _responses[i]->getFont();
+ btn->setFont(_responses[i]->getFont());
}
- btn->_width = _responseArea.right - _responseArea.left;
- if (btn->_width <= 0) {
- btn->_width = _gameRef->_renderer->getWidth();
+ int width = _responseArea.right - _responseArea.left;
+
+ if (width <= 0) {
+ btn->setWidth(_gameRef->_renderer->getWidth());
+ } else {
+ btn->setWidth(width);
}
}
btn->setName("response");
@@ -187,17 +195,17 @@ bool AdResponseBox::createButtons() {
// make the responses touchable
if (_gameRef->_touchInterface) {
- btn->_height = MAX<int32>(btn->_height, 50);
+ btn->setHeight(MAX<int32>(btn->getHeight(), 50));
}
//btn->SetListener(this, btn, _responses[i]->_iD);
btn->setListener(this, btn, i);
- btn->_visible = false;
+ btn->setVisible(false);
_respButtons.add(btn);
- if (_responseArea.bottom - _responseArea.top < btn->_height) {
+ if (_responseArea.bottom - _responseArea.top < btn->getHeight()) {
_gameRef->LOG(0, "Warning: Response '%s' is too high to be displayed within response box. Correcting.", _responses[i]->getText());
- _responseArea.bottom += (btn->_height - (_responseArea.bottom - _responseArea.top));
+ _responseArea.bottom += (btn->getHeight() - (_responseArea.bottom - _responseArea.top));
}
}
}
@@ -209,7 +217,7 @@ bool AdResponseBox::createButtons() {
//////////////////////////////////////////////////////////////////////////
bool AdResponseBox::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdResponseBox::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -245,7 +253,7 @@ TOKEN_DEF(VERTICAL_ALIGN)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
+bool AdResponseBox::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(RESPONSE_BOX)
TOKEN_TABLE(TEMPLATE)
@@ -262,22 +270,22 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_RESPONSE_BOX) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_RESPONSE_BOX) {
_gameRef->LOG(0, "'RESPONSE_BOX' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
@@ -298,7 +306,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
if (_font) {
_gameRef->_fontStorage->removeFont(_font);
}
- _font = _gameRef->_fontStorage->addFont((char *)params);
+ _font = _gameRef->_fontStorage->addFont(params);
if (!_font) {
cmd = PARSERR_GENERIC;
}
@@ -308,24 +316,24 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
if (_fontHover) {
_gameRef->_fontStorage->removeFont(_fontHover);
}
- _fontHover = _gameRef->_fontStorage->addFont((char *)params);
+ _fontHover = _gameRef->_fontStorage->addFont(params);
if (!_fontHover) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_AREA:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_responseArea.left, &_responseArea.top, &_responseArea.right, &_responseArea.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_responseArea.left, &_responseArea.top, &_responseArea.right, &_responseArea.bottom);
break;
case TOKEN_HORIZONTAL:
- parser.scanStr((char *)params, "%b", &_horizontal);
+ parser.scanStr(params, "%b", &_horizontal);
break;
case TOKEN_TEXT_ALIGN:
- if (scumm_stricmp((char *)params, "center") == 0) {
+ if (scumm_stricmp(params, "center") == 0) {
_align = TAL_CENTER;
- } else if (scumm_stricmp((char *)params, "right") == 0) {
+ } else if (scumm_stricmp(params, "right") == 0) {
_align = TAL_RIGHT;
} else {
_align = TAL_LEFT;
@@ -333,9 +341,9 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_VERTICAL_ALIGN:
- if (scumm_stricmp((char *)params, "top") == 0) {
+ if (scumm_stricmp(params, "top") == 0) {
_verticalAlign = VAL_TOP;
- } else if (scumm_stricmp((char *)params, "center") == 0) {
+ } else if (scumm_stricmp(params, "center") == 0) {
_verticalAlign = VAL_CENTER;
} else {
_verticalAlign = VAL_BOTTOM;
@@ -343,7 +351,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SPACING:
- parser.scanStr((char *)params, "%d", &_spacing);
+ parser.scanStr(params, "%d", &_spacing);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -353,7 +361,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -368,7 +376,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) {
if (_window) {
for (uint32 i = 0; i < _window->_widgets.size(); i++) {
- if (!_window->_widgets[i]->_listenerObject) {
+ if (!_window->_widgets[i]->getListener()) {
_window->_widgets[i]->setListener(this, _window->_widgets[i], 0);
}
}
@@ -461,7 +469,7 @@ bool AdResponseBox::display() {
if (!_horizontal) {
int totalHeight = 0;
for (i = 0; i < _respButtons.size(); i++) {
- totalHeight += (_respButtons[i]->_height + _spacing);
+ totalHeight += (_respButtons[i]->getHeight() + _spacing);
}
totalHeight -= _spacing;
@@ -487,22 +495,22 @@ bool AdResponseBox::display() {
// prepare response buttons
bool scrollNeeded = false;
for (i = _scrollOffset; i < _respButtons.size(); i++) {
- if ((_horizontal && xxx + _respButtons[i]->_width > rect.right)
- || (!_horizontal && yyy + _respButtons[i]->_height > rect.bottom)) {
+ if ((_horizontal && xxx + _respButtons[i]->getWidth() > rect.right)
+ || (!_horizontal && yyy + _respButtons[i]->getHeight() > rect.bottom)) {
scrollNeeded = true;
- _respButtons[i]->_visible = false;
+ _respButtons[i]->setVisible(false);
break;
}
- _respButtons[i]->_visible = true;
+ _respButtons[i]->setVisible(true);
_respButtons[i]->_posX = xxx;
_respButtons[i]->_posY = yyy;
if (_horizontal) {
- xxx += (_respButtons[i]->_width + _spacing);
+ xxx += (_respButtons[i]->getWidth() + _spacing);
} else {
- yyy += (_respButtons[i]->_height + _spacing);
+ yyy += (_respButtons[i]->getHeight() + _spacing);
}
}
@@ -515,8 +523,8 @@ bool AdResponseBox::display() {
// go exclusive
if (_shieldWindow) {
_shieldWindow->_posX = _shieldWindow->_posY = 0;
- _shieldWindow->_width = _gameRef->_renderer->getWidth();
- _shieldWindow->_height = _gameRef->_renderer->getHeight();
+ _shieldWindow->setWidth(_gameRef->_renderer->getWidth());
+ _shieldWindow->setHeight(_gameRef->_renderer->getHeight());
_shieldWindow->display();
}
@@ -575,20 +583,20 @@ bool AdResponseBox::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_font));
persistMgr->transferPtr(TMEMBER_PTR(_fontHover));
- persistMgr->transfer(TMEMBER(_horizontal));
- persistMgr->transfer(TMEMBER(_lastResponseText));
- persistMgr->transfer(TMEMBER(_lastResponseTextOrig));
+ persistMgr->transferBool(TMEMBER(_horizontal));
+ persistMgr->transferCharPtr(TMEMBER(_lastResponseText));
+ persistMgr->transferCharPtr(TMEMBER(_lastResponseTextOrig));
_respButtons.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_responseArea));
+ persistMgr->transferRect32(TMEMBER(_responseArea));
_responses.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scrollOffset));
+ persistMgr->transferSint32(TMEMBER(_scrollOffset));
persistMgr->transferPtr(TMEMBER_PTR(_shieldWindow));
- persistMgr->transfer(TMEMBER(_spacing));
+ persistMgr->transferSint32(TMEMBER(_spacing));
persistMgr->transferPtr(TMEMBER_PTR(_waitingScript));
persistMgr->transferPtr(TMEMBER_PTR(_window));
- persistMgr->transfer(TMEMBER_INT(_verticalAlign));
- persistMgr->transfer(TMEMBER_INT(_align));
+ persistMgr->transferSint32(TMEMBER_INT(_verticalAlign));
+ persistMgr->transferSint32(TMEMBER_INT(_align));
return STATUS_OK;
}
@@ -737,4 +745,4 @@ bool AdResponseBox::getObjects(BaseArray<UIObject *> &objects, bool interactiveO
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_response_box.h b/engines/wintermute/ad/ad_response_box.h
index cb57b98924..9469bfda43 100644
--- a/engines/wintermute/ad/ad_response_box.h
+++ b/engines/wintermute/ad/ad_response_box.h
@@ -72,7 +72,7 @@ public:
virtual ~AdResponseBox();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
UIWindow *getResponseWindow();
@@ -94,6 +94,6 @@ private:
UIWindow *_window;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_response_context.cpp b/engines/wintermute/ad/ad_response_context.cpp
index 663ef49a24..44b43a6077 100644
--- a/engines/wintermute/ad/ad_response_context.cpp
+++ b/engines/wintermute/ad/ad_response_context.cpp
@@ -50,8 +50,8 @@ AdResponseContext::~AdResponseContext() {
//////////////////////////////////////////////////////////////////////////
bool AdResponseContext::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_context));
- persistMgr->transfer(TMEMBER(_id));
+ persistMgr->transferCharPtr(TMEMBER(_context));
+ persistMgr->transferSint32(TMEMBER(_id));
return STATUS_OK;
}
@@ -68,4 +68,4 @@ void AdResponseContext::setContext(const char *context) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_response_context.h b/engines/wintermute/ad/ad_response_context.h
index dd0008a728..bc30b4a1c9 100644
--- a/engines/wintermute/ad/ad_response_context.h
+++ b/engines/wintermute/ad/ad_response_context.h
@@ -47,6 +47,6 @@ private:
char *_context;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp
index 4d7f27aec7..b5bdc8ebe9 100644
--- a/engines/wintermute/ad/ad_rot_level.cpp
+++ b/engines/wintermute/ad/ad_rot_level.cpp
@@ -53,7 +53,7 @@ AdRotLevel::~AdRotLevel() {
//////////////////////////////////////////////////////////////////////////
bool AdRotLevel::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdRotLevel::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -82,7 +82,7 @@ TOKEN_DEF(ROTATION)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdRotLevel::loadBuffer(byte *buffer, bool complete) {
+bool AdRotLevel::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ROTATION_LEVEL)
TOKEN_TABLE(TEMPLATE)
@@ -91,33 +91,33 @@ bool AdRotLevel::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ROTATION_LEVEL) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ROTATION_LEVEL) {
_gameRef->LOG(0, "'ROTATION_LEVEL' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_ROTATION: {
int i;
- parser.scanStr((char *)params, "%d", &i);
+ parser.scanStr(params, "%d", &i);
_rotation = (float)i;
}
break;
@@ -153,9 +153,9 @@ bool AdRotLevel::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_rotation));
+ persistMgr->transferFloat(TMEMBER(_rotation));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_rot_level.h b/engines/wintermute/ad/ad_rot_level.h
index 3466e46ba5..47c621845a 100644
--- a/engines/wintermute/ad/ad_rot_level.h
+++ b/engines/wintermute/ad/ad_rot_level.h
@@ -42,9 +42,9 @@ public:
float getRotation() const { return _rotation; }
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp
index e80f38bd0f..aa7f6f89cf 100644
--- a/engines/wintermute/ad/ad_scale_level.cpp
+++ b/engines/wintermute/ad/ad_scale_level.cpp
@@ -54,7 +54,7 @@ float AdScaleLevel::getScale() const {
//////////////////////////////////////////////////////////////////////////
bool AdScaleLevel::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdScaleLevel::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -83,7 +83,7 @@ TOKEN_DEF(SCALE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdScaleLevel::loadBuffer(byte *buffer, bool complete) {
+bool AdScaleLevel::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(SCALE_LEVEL)
TOKEN_TABLE(TEMPLATE)
@@ -92,33 +92,33 @@ bool AdScaleLevel::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SCALE_LEVEL) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_SCALE_LEVEL) {
_gameRef->LOG(0, "'SCALE_LEVEL' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_SCALE: {
int i;
- parser.scanStr((char *)params, "%d", &i);
+ parser.scanStr(params, "%d", &i);
_scale = (float)i;
}
break;
@@ -154,9 +154,9 @@ bool AdScaleLevel::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transferFloat(TMEMBER(_scale));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_scale_level.h b/engines/wintermute/ad/ad_scale_level.h
index 516f507a5a..768e79bbf7 100644
--- a/engines/wintermute/ad/ad_scale_level.h
+++ b/engines/wintermute/ad/ad_scale_level.h
@@ -41,12 +41,12 @@ public:
virtual ~AdScaleLevel();
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
float getScale() const;
private:
float _scale;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp
index 4d0068fad1..ab7ab51f30 100644
--- a/engines/wintermute/ad/ad_scene.cpp
+++ b/engines/wintermute/ad/ad_scene.cpp
@@ -538,7 +538,7 @@ bool AdScene::initLoop() {
//////////////////////////////////////////////////////////////////////////
bool AdScene::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdScene::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -600,7 +600,7 @@ TOKEN_DEF(PERSISTENT_STATE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdScene::loadBuffer(byte *buffer, bool complete) {
+bool AdScene::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(SCENE)
TOKEN_TABLE(TEMPLATE)
@@ -643,12 +643,12 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
cleanup();
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SCENE) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_SCENE) {
_gameRef->LOG(0, "'SCENE' keyword expected.");
return STATUS_FAILED;
}
@@ -659,20 +659,20 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
char camera[MAX_PATH_LENGTH] = "";
/* float waypointHeight = -1.0f; */
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_LAYER: {
@@ -747,7 +747,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -755,99 +755,99 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_CAMERA:
- Common::strlcpy(camera, (char *)params, MAX_PATH_LENGTH);
+ Common::strlcpy(camera, params, MAX_PATH_LENGTH);
break;
case TOKEN_EDITOR_MARGIN_H:
- parser.scanStr((char *)params, "%d", &_editorMarginH);
+ parser.scanStr(params, "%d", &_editorMarginH);
break;
case TOKEN_EDITOR_MARGIN_V:
- parser.scanStr((char *)params, "%d", &_editorMarginV);
+ parser.scanStr(params, "%d", &_editorMarginV);
break;
case TOKEN_EDITOR_COLOR_FRAME:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColFrame = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_ENTITY:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColEntity = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_ENTITY_SEL:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColEntitySel = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_REGION_SEL:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColRegionSel = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_DECORATION_SEL:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColDecorSel = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_BLOCKED_SEL:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColBlockedSel = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_WAYPOINTS_SEL:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColWaypointsSel = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_REGION:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColRegion = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_DECORATION:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColDecor = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_BLOCKED:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColBlocked = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_WAYPOINTS:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColWaypoints = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_COLOR_SCALE:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
+ parser.scanStr(params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColScale = BYTETORGBA(ar, ag, ab, aa);
break;
case TOKEN_EDITOR_SHOW_REGIONS:
- parser.scanStr((char *)params, "%b", &_editorShowRegions);
+ parser.scanStr(params, "%b", &_editorShowRegions);
break;
case TOKEN_EDITOR_SHOW_BLOCKED:
- parser.scanStr((char *)params, "%b", &_editorShowBlocked);
+ parser.scanStr(params, "%b", &_editorShowBlocked);
break;
case TOKEN_EDITOR_SHOW_DECORATION:
- parser.scanStr((char *)params, "%b", &_editorShowDecor);
+ parser.scanStr(params, "%b", &_editorShowDecor);
break;
case TOKEN_EDITOR_SHOW_ENTITIES:
- parser.scanStr((char *)params, "%b", &_editorShowEntities);
+ parser.scanStr(params, "%b", &_editorShowEntities);
break;
case TOKEN_EDITOR_SHOW_SCALE:
- parser.scanStr((char *)params, "%b", &_editorShowScale);
+ parser.scanStr(params, "%b", &_editorShowScale);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PROPERTY:
@@ -856,7 +856,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
case TOKEN_VIEWPORT: {
Rect32 rc;
- parser.scanStr((char *)params, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
if (!_viewport) {
_viewport = new BaseViewport(_gameRef);
}
@@ -864,13 +864,14 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) {
_viewport->setRect(rc.left, rc.top, rc.right, rc.bottom, true);
}
}
+ break;
case TOKEN_PERSISTENT_STATE:
- parser.scanStr((char *)params, "%b", &_persistentState);
+ parser.scanStr(params, "%b", &_persistentState);
break;
case TOKEN_PERSISTENT_STATE_SPRITES:
- parser.scanStr((char *)params, "%b", &_persistentStateSprites);
+ parser.scanStr(params, "%b", &_persistentStateSprites);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -1014,8 +1015,8 @@ bool AdScene::traverseNodes(bool doUpdate) {
}
if (_shieldWindow) {
_shieldWindow->_posX = _shieldWindow->_posY = 0;
- _shieldWindow->_width = _gameRef->_renderer->getWidth();
- _shieldWindow->_height = _gameRef->_renderer->getHeight();
+ _shieldWindow->setWidth(_gameRef->_renderer->getWidth());
+ _shieldWindow->setHeight(_gameRef->_renderer->getHeight());
_shieldWindow->display();
}
}
@@ -2299,58 +2300,58 @@ float AdScene::getScaleAt(int Y) {
bool AdScene::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_autoScroll));
- persistMgr->transfer(TMEMBER(_editorColBlocked));
- persistMgr->transfer(TMEMBER(_editorColBlockedSel));
- persistMgr->transfer(TMEMBER(_editorColDecor));
- persistMgr->transfer(TMEMBER(_editorColDecorSel));
- persistMgr->transfer(TMEMBER(_editorColEntity));
- persistMgr->transfer(TMEMBER(_editorColEntitySel));
- persistMgr->transfer(TMEMBER(_editorColFrame));
- persistMgr->transfer(TMEMBER(_editorColRegion));
- persistMgr->transfer(TMEMBER(_editorColRegionSel));
- persistMgr->transfer(TMEMBER(_editorColScale));
- persistMgr->transfer(TMEMBER(_editorColWaypoints));
- persistMgr->transfer(TMEMBER(_editorColWaypointsSel));
- persistMgr->transfer(TMEMBER(_editorMarginH));
- persistMgr->transfer(TMEMBER(_editorMarginV));
- persistMgr->transfer(TMEMBER(_editorShowBlocked));
- persistMgr->transfer(TMEMBER(_editorShowDecor));
- persistMgr->transfer(TMEMBER(_editorShowEntities));
- persistMgr->transfer(TMEMBER(_editorShowRegions));
- persistMgr->transfer(TMEMBER(_editorShowScale));
+ persistMgr->transferBool(TMEMBER(_autoScroll));
+ persistMgr->transferUint32(TMEMBER(_editorColBlocked));
+ persistMgr->transferUint32(TMEMBER(_editorColBlockedSel));
+ persistMgr->transferUint32(TMEMBER(_editorColDecor));
+ persistMgr->transferUint32(TMEMBER(_editorColDecorSel));
+ persistMgr->transferUint32(TMEMBER(_editorColEntity));
+ persistMgr->transferUint32(TMEMBER(_editorColEntitySel));
+ persistMgr->transferUint32(TMEMBER(_editorColFrame));
+ persistMgr->transferUint32(TMEMBER(_editorColRegion));
+ persistMgr->transferUint32(TMEMBER(_editorColRegionSel));
+ persistMgr->transferUint32(TMEMBER(_editorColScale));
+ persistMgr->transferUint32(TMEMBER(_editorColWaypoints));
+ persistMgr->transferUint32(TMEMBER(_editorColWaypointsSel));
+ persistMgr->transferSint32(TMEMBER(_editorMarginH));
+ persistMgr->transferSint32(TMEMBER(_editorMarginV));
+ persistMgr->transferBool(TMEMBER(_editorShowBlocked));
+ persistMgr->transferBool(TMEMBER(_editorShowDecor));
+ persistMgr->transferBool(TMEMBER(_editorShowEntities));
+ persistMgr->transferBool(TMEMBER(_editorShowRegions));
+ persistMgr->transferBool(TMEMBER(_editorShowScale));
persistMgr->transferPtr(TMEMBER_PTR(_fader));
- persistMgr->transfer(TMEMBER(_height));
- persistMgr->transfer(TMEMBER(_initialized));
- persistMgr->transfer(TMEMBER(_lastTimeH));
- persistMgr->transfer(TMEMBER(_lastTimeV));
+ persistMgr->transferSint32(TMEMBER(_height));
+ persistMgr->transferBool(TMEMBER(_initialized));
+ persistMgr->transferUint32(TMEMBER(_lastTimeH));
+ persistMgr->transferUint32(TMEMBER(_lastTimeV));
_layers.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_mainLayer));
_objects.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_offsetLeft));
- persistMgr->transfer(TMEMBER(_offsetTop));
- persistMgr->transfer(TMEMBER(_paralaxScrolling));
- persistMgr->transfer(TMEMBER(_persistentState));
- persistMgr->transfer(TMEMBER(_persistentStateSprites));
- persistMgr->transfer(TMEMBER(_pfMaxTime));
+ persistMgr->transferSint32(TMEMBER(_offsetLeft));
+ persistMgr->transferSint32(TMEMBER(_offsetTop));
+ persistMgr->transferBool(TMEMBER(_paralaxScrolling));
+ persistMgr->transferBool(TMEMBER(_persistentState));
+ persistMgr->transferBool(TMEMBER(_persistentStateSprites));
+ persistMgr->transferUint32(TMEMBER(_pfMaxTime));
_pfPath.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_pfPointsNum));
- persistMgr->transfer(TMEMBER(_pfReady));
+ persistMgr->transferSint32(TMEMBER(_pfPointsNum));
+ persistMgr->transferBool(TMEMBER(_pfReady));
persistMgr->transferPtr(TMEMBER_PTR(_pfRequester));
persistMgr->transferPtr(TMEMBER_PTR(_pfTarget));
persistMgr->transferPtr(TMEMBER_PTR(_pfTargetPath));
_rotLevels.persist(persistMgr);
_scaleLevels.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scrollPixelsH));
- persistMgr->transfer(TMEMBER(_scrollPixelsV));
- persistMgr->transfer(TMEMBER(_scrollTimeH));
- persistMgr->transfer(TMEMBER(_scrollTimeV));
+ persistMgr->transferSint32(TMEMBER(_scrollPixelsH));
+ persistMgr->transferSint32(TMEMBER(_scrollPixelsV));
+ persistMgr->transferUint32(TMEMBER(_scrollTimeH));
+ persistMgr->transferUint32(TMEMBER(_scrollTimeV));
persistMgr->transferPtr(TMEMBER_PTR(_shieldWindow));
- persistMgr->transfer(TMEMBER(_targetOffsetLeft));
- persistMgr->transfer(TMEMBER(_targetOffsetTop));
+ persistMgr->transferSint32(TMEMBER(_targetOffsetLeft));
+ persistMgr->transferSint32(TMEMBER(_targetOffsetTop));
_waypointGroups.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_viewport));
- persistMgr->transfer(TMEMBER(_width));
+ persistMgr->transferSint32(TMEMBER(_width));
return STATUS_OK;
}
@@ -2989,4 +2990,4 @@ bool AdScene::getRegionObjects(AdRegion *region, BaseArray<AdObject *> &objects,
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h
index cd144b77ef..1f35a776b5 100644
--- a/engines/wintermute/ad/ad_scene.h
+++ b/engines/wintermute/ad/ad_scene.h
@@ -124,7 +124,7 @@ public:
BaseArray<AdObject *> _objects;
BaseArray<AdWaypointGroup *> _waypointGroups;
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
int32 _width;
int32 _height;
bool addObject(AdObject *Object);
@@ -176,6 +176,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_scene_node.cpp b/engines/wintermute/ad/ad_scene_node.cpp
index e9b80b3cc8..5f6207c23a 100644
--- a/engines/wintermute/ad/ad_scene_node.cpp
+++ b/engines/wintermute/ad/ad_scene_node.cpp
@@ -74,9 +74,9 @@ bool AdSceneNode::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_entity));
persistMgr->transferPtr(TMEMBER_PTR(_region));
- persistMgr->transfer(TMEMBER_INT(_type));
+ persistMgr->transferSint32(TMEMBER_INT(_type));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp
index 8e022ab115..a4218751c3 100644
--- a/engines/wintermute/ad/ad_scene_state.cpp
+++ b/engines/wintermute/ad/ad_scene_state.cpp
@@ -56,7 +56,7 @@ AdSceneState::~AdSceneState() {
//////////////////////////////////////////////////////////////////////////
bool AdSceneState::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_filename));
+ persistMgr->transferCharPtr(TMEMBER(_filename));
_nodeStates.persist(persistMgr);
return STATUS_OK;
@@ -95,4 +95,4 @@ AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_scene_state.h b/engines/wintermute/ad/ad_scene_state.h
index 600aa4b581..067c737b2e 100644
--- a/engines/wintermute/ad/ad_scene_state.h
+++ b/engines/wintermute/ad/ad_scene_state.h
@@ -48,6 +48,6 @@ private:
BaseArray<AdNodeState *> _nodeStates;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp
index 70a57a624d..21ffac5aaf 100644
--- a/engines/wintermute/ad/ad_sentence.cpp
+++ b/engines/wintermute/ad/ad_sentence.cpp
@@ -249,23 +249,23 @@ bool AdSentence::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER_INT(_align));
- persistMgr->transfer(TMEMBER(_currentStance));
+ persistMgr->transferSint32(TMEMBER_INT(_align));
+ persistMgr->transferSint32(TMEMBER(_currentStance));
persistMgr->transferPtr(TMEMBER_PTR(_currentSprite));
- persistMgr->transfer(TMEMBER(_currentSkelAnim));
- persistMgr->transfer(TMEMBER(_duration));
+ persistMgr->transferCharPtr(TMEMBER(_currentSkelAnim));
+ persistMgr->transferUint32(TMEMBER(_duration));
persistMgr->transferPtr(TMEMBER_PTR(_font));
- persistMgr->transfer(TMEMBER(_pos));
+ persistMgr->transferPoint32(TMEMBER(_pos));
persistMgr->transferPtr(TMEMBER_PTR(_sound));
- persistMgr->transfer(TMEMBER(_soundStarted));
- persistMgr->transfer(TMEMBER(_stances));
- persistMgr->transfer(TMEMBER(_startTime));
+ persistMgr->transferBool(TMEMBER(_soundStarted));
+ persistMgr->transferCharPtr(TMEMBER(_stances));
+ persistMgr->transferUint32(TMEMBER(_startTime));
persistMgr->transferPtr(TMEMBER_PTR(_talkDef));
- persistMgr->transfer(TMEMBER(_tempStance));
- persistMgr->transfer(TMEMBER(_text));
- persistMgr->transfer(TMEMBER(_width));
- persistMgr->transfer(TMEMBER(_fixedPos));
- persistMgr->transfer(TMEMBER(_freezable));
+ persistMgr->transferCharPtr(TMEMBER(_tempStance));
+ persistMgr->transferCharPtr(TMEMBER(_text));
+ persistMgr->transferSint32(TMEMBER(_width));
+ persistMgr->transferBool(TMEMBER(_fixedPos));
+ persistMgr->transferBool(TMEMBER(_freezable));
return STATUS_OK;
}
@@ -358,4 +358,4 @@ bool AdSentence::canSkip() {
return (_gameRef->getTimer()->getTime() - _startTime) > 300;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_sentence.h b/engines/wintermute/ad/ad_sentence.h
index 6f255578f7..c491ad99a2 100644
--- a/engines/wintermute/ad/ad_sentence.h
+++ b/engines/wintermute/ad/ad_sentence.h
@@ -80,6 +80,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_sprite_set.cpp b/engines/wintermute/ad/ad_sprite_set.cpp
index 6c802c4863..dd920492de 100644
--- a/engines/wintermute/ad/ad_sprite_set.cpp
+++ b/engines/wintermute/ad/ad_sprite_set.cpp
@@ -60,7 +60,7 @@ AdSpriteSet::~AdSpriteSet() {
//////////////////////////////////////////////////////////////////////////
bool AdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdSpriteSet::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -93,7 +93,7 @@ TOKEN_DEF(TEMPLATE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) {
+bool AdSpriteSet::loadBuffer(char *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(SPRITESET)
TOKEN_TABLE(NAME)
@@ -109,12 +109,12 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SPRITESET) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_SPRITESET) {
_gameRef->LOG(0, "'SPRITESET' keyword expected.");
return STATUS_FAILED;
}
@@ -122,23 +122,23 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
}
BaseSprite *spr = nullptr;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params, lifeTime, cacheType))) {
+ if (DID_FAIL(loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_LEFT:
delete _sprites[DI_LEFT];
_sprites[DI_LEFT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_LEFT] = spr;
@@ -149,7 +149,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_RIGHT];
_sprites[DI_RIGHT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_RIGHT] = spr;
@@ -160,7 +160,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_UP];
_sprites[DI_UP] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_UP] = spr;
@@ -171,7 +171,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_DOWN];
_sprites[DI_DOWN] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_DOWN] = spr;
@@ -182,7 +182,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_UPLEFT];
_sprites[DI_UPLEFT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_UPLEFT] = spr;
@@ -193,7 +193,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_UPRIGHT];
_sprites[DI_UPRIGHT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_UPRIGHT] = spr;
@@ -204,7 +204,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_DOWNLEFT];
_sprites[DI_DOWNLEFT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_DOWNLEFT] = spr;
@@ -215,7 +215,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC
delete _sprites[DI_DOWNRIGHT];
_sprites[DI_DOWNRIGHT] = nullptr;
spr = new BaseSprite(_gameRef, _owner);
- if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) {
+ if (!spr || DID_FAIL(spr->loadFile(params, lifeTime, cacheType))) {
cmd = PARSERR_GENERIC;
} else {
_sprites[DI_DOWNRIGHT] = spr;
@@ -353,4 +353,4 @@ bool AdSpriteSet::containsSprite(BaseSprite *sprite) {
return false;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_sprite_set.h b/engines/wintermute/ad/ad_sprite_set.h
index 61043aa3d6..ece71f7adb 100644
--- a/engines/wintermute/ad/ad_sprite_set.h
+++ b/engines/wintermute/ad/ad_sprite_set.h
@@ -44,10 +44,10 @@ public:
AdSpriteSet(BaseGame *inGame, BaseObject *owner = nullptr);
virtual ~AdSpriteSet();
bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
- bool loadBuffer(byte *buffer, bool complete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
+ bool loadBuffer(char *buffer, bool complete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
BaseSprite *_sprites[NUM_DIRECTIONS];
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_talk_def.cpp b/engines/wintermute/ad/ad_talk_def.cpp
index bf72b2916b..22e3d7b4cc 100644
--- a/engines/wintermute/ad/ad_talk_def.cpp
+++ b/engines/wintermute/ad/ad_talk_def.cpp
@@ -71,7 +71,7 @@ AdTalkDef::~AdTalkDef() {
//////////////////////////////////////////////////////////////////////////
bool AdTalkDef::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdTalkDef::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -101,7 +101,7 @@ TOKEN_DEF(DEFAULT_SPRITE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdTalkDef::loadBuffer(byte *buffer, bool complete) {
+bool AdTalkDef::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(TALK)
TOKEN_TABLE(TEMPLATE)
@@ -112,22 +112,22 @@ bool AdTalkDef::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_TALK) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_TALK) {
_gameRef->LOG(0, "'TALK' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
@@ -145,11 +145,11 @@ bool AdTalkDef::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_DEFAULT_SPRITE:
- BaseUtils::setString(&_defaultSpriteFilename, (char *)params);
+ BaseUtils::setString(&_defaultSpriteFilename, params);
break;
case TOKEN_DEFAULT_SPRITESET_FILE:
- BaseUtils::setString(&_defaultSpriteSetFilename, (char *)params);
+ BaseUtils::setString(&_defaultSpriteSetFilename, params);
break;
case TOKEN_DEFAULT_SPRITESET: {
@@ -209,9 +209,9 @@ bool AdTalkDef::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_defaultSprite));
- persistMgr->transfer(TMEMBER(_defaultSpriteFilename));
+ persistMgr->transferCharPtr(TMEMBER(_defaultSpriteFilename));
persistMgr->transferPtr(TMEMBER_PTR(_defaultSpriteSet));
- persistMgr->transfer(TMEMBER(_defaultSpriteSetFilename));
+ persistMgr->transferCharPtr(TMEMBER(_defaultSpriteSetFilename));
_nodes.persist(persistMgr);
@@ -282,4 +282,4 @@ BaseSprite *AdTalkDef::getDefaultSprite(TDirection dir) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_talk_def.h b/engines/wintermute/ad/ad_talk_def.h
index 2375360d89..5711906b4b 100644
--- a/engines/wintermute/ad/ad_talk_def.h
+++ b/engines/wintermute/ad/ad_talk_def.h
@@ -46,13 +46,13 @@ public:
AdTalkDef(BaseGame *inGame);
virtual ~AdTalkDef();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
BaseArray<AdTalkNode *> _nodes;
char *_defaultSpriteFilename;
BaseSprite *_defaultSprite;
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0) override;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_talk_holder.cpp b/engines/wintermute/ad/ad_talk_holder.cpp
index 33deab7805..6041105b93 100644
--- a/engines/wintermute/ad/ad_talk_holder.cpp
+++ b/engines/wintermute/ad/ad_talk_holder.cpp
@@ -399,4 +399,4 @@ bool AdTalkHolder::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_talk_holder.h b/engines/wintermute/ad/ad_talk_holder.h
index 501acbc885..ab48c3aaf4 100644
--- a/engines/wintermute/ad/ad_talk_holder.h
+++ b/engines/wintermute/ad/ad_talk_holder.h
@@ -52,6 +52,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_talk_node.cpp b/engines/wintermute/ad/ad_talk_node.cpp
index f03c24ea94..6c0d2e1f06 100644
--- a/engines/wintermute/ad/ad_talk_node.cpp
+++ b/engines/wintermute/ad/ad_talk_node.cpp
@@ -79,7 +79,7 @@ TOKEN_DEF(PRECACHE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdTalkNode::loadBuffer(byte *buffer, bool complete) {
+bool AdTalkNode::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ACTION)
TOKEN_TABLE(SPRITESET_FILE)
@@ -92,12 +92,12 @@ bool AdTalkNode::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ACTION) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ACTION) {
_gameRef->LOG(0, "'ACTION' keyword expected.");
return STATUS_FAILED;
}
@@ -108,14 +108,14 @@ bool AdTalkNode::loadBuffer(byte *buffer, bool complete) {
_playToEnd = false;
_preCache = false;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_SPRITE:
- BaseUtils::setString(&_spriteFilename, (char *)params);
+ BaseUtils::setString(&_spriteFilename, params);
break;
case TOKEN_SPRITESET_FILE:
- BaseUtils::setString(&_spriteSetFilename, (char *)params);
+ BaseUtils::setString(&_spriteSetFilename, params);
break;
case TOKEN_SPRITESET: {
@@ -130,20 +130,20 @@ bool AdTalkNode::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_START_TIME:
- parser.scanStr((char *)params, "%d", &_startTime);
+ parser.scanStr(params, "%d", &_startTime);
break;
case TOKEN_END_TIME:
- parser.scanStr((char *)params, "%d", &_endTime);
+ parser.scanStr(params, "%d", &_endTime);
break;
case TOKEN_PRECACHE:
- parser.scanStr((char *)params, "%b", &_preCache);
+ parser.scanStr(params, "%b", &_preCache);
break;
case TOKEN_COMMENT:
if (_gameRef->_editorMode) {
- BaseUtils::setString(&_comment, (char *)params);
+ BaseUtils::setString(&_comment, params);
}
break;
@@ -191,14 +191,14 @@ bool AdTalkNode::loadBuffer(byte *buffer, bool complete) {
//////////////////////////////////////////////////////////////////////////
bool AdTalkNode::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_comment));
- persistMgr->transfer(TMEMBER(_startTime));
- persistMgr->transfer(TMEMBER(_endTime));
- persistMgr->transfer(TMEMBER(_playToEnd));
+ persistMgr->transferCharPtr(TMEMBER(_comment));
+ persistMgr->transferUint32(TMEMBER(_startTime));
+ persistMgr->transferUint32(TMEMBER(_endTime));
+ persistMgr->transferBool(TMEMBER(_playToEnd));
persistMgr->transferPtr(TMEMBER_PTR(_sprite));
- persistMgr->transfer(TMEMBER(_spriteFilename));
+ persistMgr->transferCharPtr(TMEMBER(_spriteFilename));
persistMgr->transferPtr(TMEMBER_PTR(_spriteSet));
- persistMgr->transfer(TMEMBER(_spriteSetFilename));
+ persistMgr->transferCharPtr(TMEMBER(_spriteSetFilename));
return STATUS_OK;
}
@@ -292,4 +292,4 @@ BaseSprite *AdTalkNode::getSprite(TDirection dir) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_talk_node.h b/engines/wintermute/ad/ad_talk_node.h
index 012fa2133e..7a014b2d9f 100644
--- a/engines/wintermute/ad/ad_talk_node.h
+++ b/engines/wintermute/ad/ad_talk_node.h
@@ -46,7 +46,7 @@ public:
AdTalkNode(BaseGame *inGame);
virtual ~AdTalkNode();
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0) override;
char *_spriteFilename;
BaseSprite *_sprite;
@@ -58,6 +58,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_types.h b/engines/wintermute/ad/ad_types.h
index ae5882f4ee..dc1a54b91d 100644
--- a/engines/wintermute/ad/ad_types.h
+++ b/engines/wintermute/ad/ad_types.h
@@ -102,6 +102,6 @@ typedef enum {
GEOM_GENERIC
} TGeomNodeType;
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp
index 96dece34b8..ae6b18e266 100644
--- a/engines/wintermute/ad/ad_waypoint_group.cpp
+++ b/engines/wintermute/ad/ad_waypoint_group.cpp
@@ -66,7 +66,7 @@ void AdWaypointGroup::cleanup() {
//////////////////////////////////////////////////////////////////////////
bool AdWaypointGroup::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "AdWaypointGroup::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -98,7 +98,7 @@ TOKEN_DEF(PROPERTY)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool AdWaypointGroup::loadBuffer(byte *buffer, bool complete) {
+bool AdWaypointGroup::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(WAYPOINTS)
TOKEN_TABLE(TEMPLATE)
@@ -110,43 +110,43 @@ bool AdWaypointGroup::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_WAYPOINTS) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_WAYPOINTS) {
_gameRef->LOG(0, "'WAYPOINTS' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_POINT: {
int x, y;
- parser.scanStr((char *)params, "%d,%d", &x, &y);
+ parser.scanStr(params, "%d,%d", &x, &y);
_points.add(new BasePoint(x, y));
}
break;
case TOKEN_EDITOR_SELECTED:
- parser.scanStr((char *)params, "%b", &_editorSelected);
+ parser.scanStr(params, "%b", &_editorSelected);
break;
case TOKEN_EDITOR_SELECTED_POINT:
- parser.scanStr((char *)params, "%d", &_editorSelectedPoint);
+ parser.scanStr(params, "%d", &_editorSelectedPoint);
break;
case TOKEN_PROPERTY:
@@ -194,11 +194,11 @@ bool AdWaypointGroup::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_active));
- persistMgr->transfer(TMEMBER(_editorSelectedPoint));
- persistMgr->transfer(TMEMBER(_lastMimicScale));
- persistMgr->transfer(TMEMBER(_lastMimicX));
- persistMgr->transfer(TMEMBER(_lastMimicY));
+ persistMgr->transferBool(TMEMBER(_active));
+ persistMgr->transferSint32(TMEMBER(_editorSelectedPoint));
+ persistMgr->transferFloat(TMEMBER(_lastMimicScale));
+ persistMgr->transferSint32(TMEMBER(_lastMimicX));
+ persistMgr->transferSint32(TMEMBER(_lastMimicY));
_points.persist(persistMgr);
return STATUS_OK;
@@ -267,4 +267,4 @@ bool AdWaypointGroup::mimic(AdWaypointGroup *wpt, float scale, int argX, int arg
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ad/ad_waypoint_group.h b/engines/wintermute/ad/ad_waypoint_group.h
index 79b28e0d22..47fd611be6 100644
--- a/engines/wintermute/ad/ad_waypoint_group.h
+++ b/engines/wintermute/ad/ad_waypoint_group.h
@@ -41,7 +41,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
AdWaypointGroup(BaseGame *inGame);
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual ~AdWaypointGroup();
bool _active;
@@ -56,6 +56,6 @@ private:
int32 _lastMimicY;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp
index d01972b82f..6a0666b36e 100644
--- a/engines/wintermute/base/base.cpp
+++ b/engines/wintermute/base/base.cpp
@@ -60,7 +60,7 @@ Common::String BaseClass::getEditorProp(const Common::String &propName, const Co
if (_editorPropsIter != _editorProps.end()) {
return _editorPropsIter->_value.c_str();
} else {
- return initVal;
+ return initVal; // Used to be NULL
}
}
@@ -87,7 +87,7 @@ TOKEN_DEF(NAME)
TOKEN_DEF(VALUE)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool BaseClass::parseEditorProperty(byte *buffer, bool complete) {
+bool BaseClass::parseEditorProperty(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE(NAME)
@@ -100,12 +100,12 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) {
}
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_EDITOR_PROPERTY) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_EDITOR_PROPERTY) {
BaseEngine::LOG(0, "'EDITOR_PROPERTY' keyword expected.");
return STATUS_FAILED;
}
@@ -115,13 +115,13 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) {
char *propName = nullptr;
char *propValue = nullptr;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_NAME:
delete[] propName;
- propName = new char[strlen((char *)params) + 1];
+ propName = new char[strlen(params) + 1];
if (propName) {
- strcpy(propName, (char *)params);
+ strcpy(propName, params);
} else {
cmd = PARSERR_GENERIC;
}
@@ -129,9 +129,9 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) {
case TOKEN_VALUE:
delete[] propValue;
- propValue = new char[strlen((char *)params) + 1];
+ propValue = new char[strlen(params) + 1];
if (propValue) {
- strcpy(propValue, (char *)params);
+ strcpy(propValue, params);
} else {
cmd = PARSERR_GENERIC;
}
@@ -183,4 +183,4 @@ bool BaseClass::saveAsText(BaseDynamicBuffer *buffer, int indent) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base.h b/engines/wintermute/base/base.h
index 7f2796c6e0..8767cc9bdd 100644
--- a/engines/wintermute/base/base.h
+++ b/engines/wintermute/base/base.h
@@ -44,9 +44,9 @@ class BaseClass {
public:
bool _persistable;
bool setEditorProp(const Common::String &propName, const Common::String &propValue);
- Common::String getEditorProp(const Common::String &propName, const Common::String &initVal = nullptr);
+ Common::String getEditorProp(const Common::String &propName, const Common::String &initVal = Common::String());
BaseClass(TDynamicConstructor, TDynamicConstructor) {}
- bool parseEditorProperty(byte *buffer, bool complete = true);
+ bool parseEditorProperty(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0);
BaseClass();
BaseClass(BaseGame *GameOwner);
@@ -57,6 +57,6 @@ protected:
Common::HashMap<Common::String, Common::String>::iterator _editorPropsIter;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp
index 7a91854c57..69cc7b02b6 100644
--- a/engines/wintermute/base/base_active_rect.cpp
+++ b/engines/wintermute/base/base_active_rect.cpp
@@ -37,7 +37,7 @@ namespace Wintermute {
//////////////////////////////////////////////////////////////////////
BaseActiveRect::BaseActiveRect(BaseGame *inGame) : BaseClass(inGame) {
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
_owner = nullptr;
_frame = nullptr;
_region = nullptr;
@@ -52,7 +52,7 @@ BaseActiveRect::BaseActiveRect(BaseGame *inGame) : BaseClass(inGame) {
BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseSubFrame *frame, int x, int y, int width, int height, float zoomX, float zoomY, bool precise) : BaseClass(inGame) {
_owner = owner;
_frame = frame;
- BasePlatform::setRect(&_rect, x, y, x + width, y + height);
+ _rect.setRect(x, y, x + width, y + height);
_zoomX = zoomX;
_zoomY = zoomY;
_precise = precise;
@@ -109,4 +109,4 @@ void BaseActiveRect::clipRect() {
BasePlatform::intersectRect(&_rect, &_rect, &rc);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_active_rect.h b/engines/wintermute/base/base_active_rect.h
index 982a0902d0..a3c0746618 100644
--- a/engines/wintermute/base/base_active_rect.h
+++ b/engines/wintermute/base/base_active_rect.h
@@ -55,6 +55,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_dynamic_buffer.cpp b/engines/wintermute/base/base_dynamic_buffer.cpp
index f684420b1e..5334ae46c4 100644
--- a/engines/wintermute/base/base_dynamic_buffer.cpp
+++ b/engines/wintermute/base/base_dynamic_buffer.cpp
@@ -201,4 +201,4 @@ void BaseDynamicBuffer::putTextForm(const char *format, va_list argptr) {
putBytes((byte *)buff, strlen(buff));
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h
index ad78ebad00..2804d78895 100644
--- a/engines/wintermute/base/base_dynamic_buffer.h
+++ b/engines/wintermute/base/base_dynamic_buffer.h
@@ -60,6 +60,6 @@ private:
void putTextForm(const char *format, va_list argptr);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp
index d4b17a0a64..acb12bbe5f 100644
--- a/engines/wintermute/base/base_engine.cpp
+++ b/engines/wintermute/base/base_engine.cpp
@@ -44,10 +44,11 @@ BaseEngine::BaseEngine() {
_classReg = nullptr;
_rnd = nullptr;
_gameId = "";
+ _language = Common::UNK_LANG;
}
-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 +61,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, ...) {
@@ -122,4 +125,4 @@ const Timer *BaseEngine::getLiveTimer() {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index d972e6ebbc..a5eafd3597 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,9 +70,11 @@ 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
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_fader.cpp b/engines/wintermute/base/base_fader.cpp
index 0d17b07a9d..c7dac8be27 100644
--- a/engines/wintermute/base/base_fader.cpp
+++ b/engines/wintermute/base/base_fader.cpp
@@ -175,16 +175,16 @@ uint32 BaseFader::getCurrentColor() const {
bool BaseFader::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_active));
- persistMgr->transfer(TMEMBER(_blue));
- persistMgr->transfer(TMEMBER(_currentAlpha));
- persistMgr->transfer(TMEMBER(_duration));
- persistMgr->transfer(TMEMBER(_green));
- persistMgr->transfer(TMEMBER(_red));
- persistMgr->transfer(TMEMBER(_sourceAlpha));
- persistMgr->transfer(TMEMBER(_startTime));
- persistMgr->transfer(TMEMBER(_targetAlpha));
- persistMgr->transfer(TMEMBER(_system));
+ persistMgr->transferBool(TMEMBER(_active));
+ persistMgr->transferByte(TMEMBER(_blue));
+ persistMgr->transferByte(TMEMBER(_currentAlpha));
+ persistMgr->transferUint32(TMEMBER(_duration));
+ persistMgr->transferByte(TMEMBER(_green));
+ persistMgr->transferByte(TMEMBER(_red));
+ persistMgr->transferByte(TMEMBER(_sourceAlpha));
+ persistMgr->transferUint32(TMEMBER(_startTime));
+ persistMgr->transferByte(TMEMBER(_targetAlpha));
+ persistMgr->transferBool(TMEMBER(_system));
if (_system && !persistMgr->getIsSaving()) {
_startTime = 0;
@@ -193,4 +193,4 @@ bool BaseFader::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h
index 845ce2f244..087b19bc44 100644
--- a/engines/wintermute/base/base_fader.h
+++ b/engines/wintermute/base/base_fader.h
@@ -58,6 +58,6 @@ private:
uint32 _startTime;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
index 4c7c31562d..286f83defe 100644
--- a/engines/wintermute/base/base_file_manager.cpp
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -168,15 +168,20 @@ bool BaseFileManager::initPaths() {
if (languageSubFolder.exists()) {
addPath(PATH_PACKAGE, languageSubFolder);
}
+ // Also add languages/ for Reversion1.
+ languageSubFolder = gameData.getChild("languages");
+ if (languageSubFolder.exists()) {
+ addPath(PATH_PACKAGE, languageSubFolder);
+ }
return STATUS_OK;
}
bool BaseFileManager::registerPackages(const Common::FSList &fslist) {
for (Common::FSList::const_iterator it = fslist.begin(); it != fslist.end(); ++it) {
- debugC(kWintermuteDebugFileAccess, "Adding %s", (*it).getName().c_str());
- if ((*it).getName().contains(".dcp")) {
- if (registerPackage((*it))) {
- addPath(PATH_PACKAGE, (*it));
+ debugC(kWintermuteDebugFileAccess, "Adding %s", it->getName().c_str());
+ if (it->getName().contains(".dcp")) {
+ if (registerPackage(*it)) {
+ addPath(PATH_PACKAGE, *it);
}
}
}
@@ -187,36 +192,72 @@ bool BaseFileManager::registerPackages(const Common::FSList &fslist) {
bool BaseFileManager::registerPackages() {
debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Scanning packages");
+ // We need the target name as a Common::String to perform some game-specific hacks.
+ Common::String targetName = BaseEngine::instance().getGameTargetName();
+
// Register without using SearchMan, as otherwise the FSNode-based lookup in openPackage will fail
// and that has to be like that to support the detection-scheme.
Common::FSList files;
- for (Common::FSList::iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
- debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", (*it).getPath().c_str(), (*it).getName().c_str());
- if ((*it).getChildren(files, Common::FSNode::kListFilesOnly)) {
- warning("getChildren() failed for path: %s", (*it).getDisplayName().c_str());
+ for (Common::FSList::const_iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
+ debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", it->getPath().c_str(), it->getName().c_str());
+ if (!it->getChildren(files, Common::FSNode::kListFilesOnly)) {
+ warning("getChildren() failed for path: %s", it->getDisplayName().c_str());
}
- for (Common::FSList::iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
- if (!fileIt->getName().hasSuffix(".dcp")) {
+ for (Common::FSList::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
+ // To prevent any case sensitivity issues we make the filename
+ // all lowercase here. This makes the code slightly prettier
+ // than the equivalent of using equalsIgnoreCase.
+ Common::String fileName = fileIt->getName();
+ fileName.toLowercase();
+
+ if (!fileName.hasSuffix(".dcp")) {
continue;
}
+ // HACK: for Reversion1, avoid loading xlanguage_pt.dcp from the main folder:
+ if (_language != Common::PT_BRA && targetName.hasPrefix("reversion1")) {
+ if (fileName == "xlanguage_pt.dcp") {
+ continue;
+ }
+ }
+
+ // Again, make the parent's name all lowercase to avoid any case
+ // issues.
+ Common::String parentName = fileIt->getParent().getName();
+ parentName.toLowercase();
+
// Avoid registering all the language files
// TODO: Select based on the gameDesc.
- if (_language != Common::UNK_LANG && fileIt->getParent().getName() == "language") {
- Common::String parentName = fileIt->getParent().getName();
- Common::String dcpName = fileIt->getName();
- if (_language == Common::EN_ANY && fileIt->getName() != "english.dcp") {
+ if (_language != Common::UNK_LANG && (parentName == "language" || parentName == "languages")) {
+ // English
+ if (_language == Common::EN_ANY && (fileName != "english.dcp" && fileName != "xlanguage_en.dcp")) {
+ continue;
+ // Chinese
+ } else if (_language == Common::ZH_CNA && (fileName != "chinese.dcp" && fileName != "xlanguage_nz.dcp")) {
+ continue;
+ // Czech
+ } else if (_language == Common::CZ_CZE && (fileName != "czech.dcp" && fileName != "xlanguage_cz.dcp")) {
+ continue;
+ // French
+ } else if (_language == Common::FR_FRA && (fileName != "french.dcp" && fileName != "xlanguage_fr.dcp")) {
+ continue;
+ // German
+ } else if (_language == Common::DE_DEU && (fileName != "german.dcp" && fileName != "xlanguage_de.dcp")) {
continue;
- } else if (_language == Common::CZ_CZE && fileIt->getName() != "czech.dcp") {
+ // Italian
+ } else if (_language == Common::IT_ITA && (fileName != "italian.dcp" && fileName != "xlanguage_it.dcp")) {
continue;
- } else if (_language == Common::IT_ITA && fileIt->getName() != "italian.dcp") {
+ // Polish
+ } else if (_language == Common::PL_POL && (fileName != "polish.dcp" && fileName != "xlanguage_po.dcp")) {
continue;
- } else if (_language == Common::PL_POL && fileIt->getName() != "polish.dcp") {
+ // Portuguese
+ } else if (_language == Common::PT_BRA && (fileName != "portuguese.dcp" && fileName != "xlanguage_pt.dcp")) {
continue;
- } else if (_language == Common::RU_RUS && fileIt->getName() != "russian.dcp") {
+ // Russian
+ } else if (_language == Common::RU_RUS && (fileName != "russian.dcp" && fileName != "xlanguage_ru.dcp")) {
continue;
}
}
- debugC(kWintermuteDebugFileAccess, "Registering %s %s", (*fileIt).getPath().c_str(), (*fileIt).getName().c_str());
+ debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().c_str(), fileIt->getName().c_str());
registerPackage((*fileIt));
}
}
@@ -250,8 +291,6 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f
Common::String upcName = filename;
upcName.toUppercase();
Common::SeekableReadStream *file = nullptr;
- char fileName[MAX_PATH_LENGTH];
- Common::strlcpy(fileName, upcName.c_str(), MAX_PATH_LENGTH);
// correct slashes
for (uint32 i = 0; i < upcName.size(); i++) {
@@ -269,7 +308,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;
}
@@ -360,4 +399,4 @@ BaseFileManager *BaseFileManager::getEngineInstance() {
return nullptr;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h
index 7ed3a6c7cb..8c2876f681 100644
--- a/engines/wintermute/base/base_file_manager.h
+++ b/engines/wintermute/base/base_file_manager.h
@@ -74,6 +74,6 @@ private:
// the detector too, without launching the entire engine:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp
index 9fb5770f79..1455733461 100644
--- a/engines/wintermute/base/base_frame.cpp
+++ b/engines/wintermute/base/base_frame.cpp
@@ -142,7 +142,7 @@ TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF(KILL_SOUND)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////
-bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
+bool BaseFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(DELAY)
TOKEN_TABLE(IMAGE)
@@ -181,10 +181,10 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
bool decoration = false;
bool mirrorX = false;
bool mirrorY = false;
- BasePlatform::setRectEmpty(&rect);
+ rect.setEmpty();
char *surface_file = nullptr;
- while ((cmd = parser.getCommand((char **)&buffer, commands, &params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_DELAY:
parser.scanStr(params, "%d", &_delay);
@@ -249,7 +249,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
case TOKEN_SUBFRAME: {
BaseSubFrame *subframe = new BaseSubFrame(_gameRef);
- if (!subframe || DID_FAIL(subframe->loadBuffer((byte *)params, lifeTime, keepLoaded))) {
+ if (!subframe || DID_FAIL(subframe->loadBuffer(params, lifeTime, keepLoaded))) {
delete subframe;
cmd = PARSERR_GENERIC;
} else {
@@ -290,7 +290,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
break;
case TOKEN_EDITOR_PROPERTY:
- parseEditorProperty((byte *)params, false);
+ parseEditorProperty(params, false);
break;
}
}
@@ -325,7 +325,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
}
}
- if (BasePlatform::isRectEmpty(&rect)) {
+ if (rect.isRectEmpty()) {
sub->setDefaultRect();
} else {
sub->setRect(rect);
@@ -352,7 +352,7 @@ bool BaseFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float
if (!rect) {
return false;
}
- BasePlatform::setRectEmpty(rect);
+ rect->setEmpty();
Rect32 subRect;
@@ -414,12 +414,12 @@ bool BaseFrame::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
_applyEvent.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_delay));
- persistMgr->transfer(TMEMBER(_editorExpanded));
- persistMgr->transfer(TMEMBER(_keyframe));
- persistMgr->transfer(TMEMBER(_killSound));
- persistMgr->transfer(TMEMBER(_moveX));
- persistMgr->transfer(TMEMBER(_moveY));
+ persistMgr->transferUint32(TMEMBER(_delay));
+ persistMgr->transferBool(TMEMBER(_editorExpanded));
+ persistMgr->transferBool(TMEMBER(_keyframe));
+ persistMgr->transferBool(TMEMBER(_killSound));
+ persistMgr->transferSint32(TMEMBER(_moveX));
+ persistMgr->transferSint32(TMEMBER(_moveY));
persistMgr->transferPtr(TMEMBER_PTR(_sound));
_subframes.persist(persistMgr);
@@ -764,4 +764,4 @@ const char *BaseFrame::scToString() {
return "[frame]";
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h
index 954851c77f..c4cfc443fa 100644
--- a/engines/wintermute/base/base_frame.h
+++ b/engines/wintermute/base/base_frame.h
@@ -52,7 +52,7 @@ public:
uint32 _delay;
BaseArray<BaseSubFrame *> _subframes;
bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
- bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded);
+ bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded);
BaseFrame(BaseGame *inGame);
virtual ~BaseFrame();
@@ -70,6 +70,6 @@ private:
BaseSound *_sound;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index e97e342149..6b7e1cf803 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;
@@ -185,7 +185,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
_lastCursor = nullptr;
- BasePlatform::setRectEmpty(&_mouseLockRect);
+ _mouseLockRect.setEmpty();
_suppressScriptErrors = false;
_lastMiniUpdate = 0;
@@ -212,7 +212,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
#else*/
_touchInterface = false;
_constrainedMemory = false;
-
+
_settings = new BaseGameSettings(this);
//#endif
@@ -573,7 +573,7 @@ bool BaseGame::initLoop() {
_focusedWindow = nullptr;
for (int i = _windows.size() - 1; i >= 0; i--) {
- if (_windows[i]->_visible) {
+ if (_windows[i]->isVisible()) {
_focusedWindow = _windows[i];
break;
}
@@ -620,7 +620,7 @@ void BaseGame::getOffset(int *offsetX, int *offsetY) const {
//////////////////////////////////////////////////////////////////////////
bool BaseGame::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "BaseGame::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -690,7 +690,7 @@ TOKEN_DEF(GUID)
TOKEN_DEF(COMPAT_KILL_METHOD_THREADS)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool BaseGame::loadBuffer(byte *buffer, bool complete) {
+bool BaseGame::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(GAME)
TOKEN_TABLE(TEMPLATE)
@@ -740,32 +740,32 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
Common::String loadImageName = "";
Common::String saveImageName = "";
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_GAME) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_GAME) {
_gameRef->LOG(0, "'GAME' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_SYSTEM_FONT:
@@ -774,7 +774,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
}
_systemFont = nullptr;
- _systemFont = _gameRef->_fontStorage->addFont((char *)params);
+ _systemFont = _gameRef->_fontStorage->addFont(params);
break;
case TOKEN_VIDEO_FONT:
@@ -783,14 +783,14 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
}
_videoFont = nullptr;
- _videoFont = _gameRef->_fontStorage->addFont((char *)params);
+ _videoFont = _gameRef->_fontStorage->addFont(params);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -801,7 +801,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
delete _activeCursor;
_activeCursor = nullptr;
_activeCursor = new BaseSprite(_gameRef);
- if (!_activeCursor || DID_FAIL(_activeCursor->loadFile((char *)params))) {
+ if (!_activeCursor || DID_FAIL(_activeCursor->loadFile(params))) {
delete _activeCursor;
_activeCursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -811,7 +811,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
case TOKEN_NONINTERACTIVE_CURSOR:
delete _cursorNoninteractive;
_cursorNoninteractive = new BaseSprite(_gameRef);
- if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile((char *)params))) {
+ if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile(params))) {
delete _cursorNoninteractive;
_cursorNoninteractive = nullptr;
cmd = PARSERR_GENERIC;
@@ -819,23 +819,23 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PERSONAL_SAVEGAMES:
- parser.scanStr((char *)params, "%b", &_personalizedSave);
+ parser.scanStr(params, "%b", &_personalizedSave);
break;
case TOKEN_SUBTITLES:
- parser.scanStr((char *)params, "%b", &_subtitles);
+ parser.scanStr(params, "%b", &_subtitles);
break;
case TOKEN_SUBTITLES_SPEED:
- parser.scanStr((char *)params, "%d", &_subtitlesSpeed);
+ parser.scanStr(params, "%d", &_subtitlesSpeed);
break;
case TOKEN_VIDEO_SUBTITLES:
- parser.scanStr((char *)params, "%b", &_videoSubtitles);
+ parser.scanStr(params, "%b", &_videoSubtitles);
break;
case TOKEN_PROPERTY:
@@ -847,66 +847,66 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_THUMBNAIL_WIDTH:
- parser.scanStr((char *)params, "%d", &_thumbnailWidth);
+ parser.scanStr(params, "%d", &_thumbnailWidth);
break;
case TOKEN_THUMBNAIL_HEIGHT:
- parser.scanStr((char *)params, "%d", &_thumbnailHeight);
+ parser.scanStr(params, "%d", &_thumbnailHeight);
break;
case TOKEN_INDICATOR_X:
- parser.scanStr((char *)params, "%d", &indicatorX);
+ parser.scanStr(params, "%d", &indicatorX);
break;
case TOKEN_INDICATOR_Y:
- parser.scanStr((char *)params, "%d", &indicatorY);
+ parser.scanStr(params, "%d", &indicatorY);
break;
case TOKEN_INDICATOR_COLOR: {
int r, g, b, a;
- parser.scanStr((char *)params, "%d,%d,%d,%d", &r, &g, &b, &a);
+ parser.scanStr(params, "%d,%d,%d,%d", &r, &g, &b, &a);
indicatorColor = BYTETORGBA(r, g, b, a);
}
break;
case TOKEN_INDICATOR_WIDTH:
- parser.scanStr((char *)params, "%d", &indicatorWidth);
+ parser.scanStr(params, "%d", &indicatorWidth);
break;
case TOKEN_INDICATOR_HEIGHT:
- parser.scanStr((char *)params, "%d", &indicatorHeight);
+ parser.scanStr(params, "%d", &indicatorHeight);
break;
case TOKEN_SAVE_IMAGE:
- saveImageName = (char *) params;
+ saveImageName = params;
break;
case TOKEN_SAVE_IMAGE_X:
- parser.scanStr((char *)params, "%d", &saveImageX);
+ parser.scanStr(params, "%d", &saveImageX);
break;
case TOKEN_SAVE_IMAGE_Y:
- parser.scanStr((char *)params, "%d", &saveImageY);
+ parser.scanStr(params, "%d", &saveImageY);
break;
case TOKEN_LOAD_IMAGE:
- loadImageName = (char *) params;
+ loadImageName = params;
break;
case TOKEN_LOAD_IMAGE_X:
- parser.scanStr((char *)params, "%d", &loadImageX);
+ parser.scanStr(params, "%d", &loadImageX);
break;
case TOKEN_LOAD_IMAGE_Y:
- parser.scanStr((char *)params, "%d", &loadImageY);
+ parser.scanStr(params, "%d", &loadImageY);
break;
case TOKEN_LOCAL_SAVE_DIR:
- _localSaveDir = (char *)params;
+ _localSaveDir = params;
break;
case TOKEN_COMPAT_KILL_METHOD_THREADS:
- parser.scanStr((char *)params, "%b", &_compatKillMethodThreads);
+ parser.scanStr(params, "%b", &_compatKillMethodThreads);
break;
}
}
@@ -1123,7 +1123,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
BaseUtils::swap(&top, &bottom);
}
- BasePlatform::setRect(&_mouseLockRect, left, top, right, bottom);
+ _mouseLockRect.setRect(left, top, right, bottom);
stack->pushNULL();
return STATUS_OK;
@@ -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;
}
@@ -2558,7 +2554,7 @@ bool BaseGame::displayQuickMsg() {
// update
for (uint32 i = 0; i < _quickMessages.size(); i++) {
- if (_currentTime - _quickMessages[i]->_startTime >= QUICK_MSG_DURATION) {
+ if (_currentTime - _quickMessages[i]->getStartTime() >= QUICK_MSG_DURATION) {
delete _quickMessages[i];
_quickMessages.remove_at(i);
i--;
@@ -2583,7 +2579,7 @@ void BaseGame::quickMessage(const char *text) {
delete _quickMessages[0];
_quickMessages.remove_at(0);
}
- _quickMessages.add(new BaseQuickMsg(_gameRef, text));
+ _quickMessages.add(new BaseQuickMsg(_currentTime, text));
}
@@ -3023,10 +3019,10 @@ bool BaseGame::displayWindows(bool inGame) {
bool res;
// did we lose focus? focus topmost window
- if (_focusedWindow == nullptr || !_focusedWindow->_visible || _focusedWindow->_disable) {
+ if (_focusedWindow == nullptr || !_focusedWindow->isVisible() || _focusedWindow->isDisabled()) {
_focusedWindow = nullptr;
for (int i = _windows.size() - 1; i >= 0; i--) {
- if (_windows[i]->_visible && !_windows[i]->_disable) {
+ if (_windows[i]->isVisible() && !_windows[i]->isDisabled()) {
_focusedWindow = _windows[i];
break;
}
@@ -3035,7 +3031,7 @@ bool BaseGame::displayWindows(bool inGame) {
// display all windows
for (uint32 i = 0; i < _windows.size(); i++) {
- if (_windows[i]->_visible && _windows[i]->_inGame == inGame) {
+ if (_windows[i]->isVisible() && _windows[i]->getInGame() == inGame) {
res = _windows[i]->display();
if (DID_FAIL(res)) {
@@ -3058,61 +3054,61 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_activeObject));
persistMgr->transferPtr(TMEMBER_PTR(_capturedObject));
persistMgr->transferPtr(TMEMBER_PTR(_cursorNoninteractive));
- persistMgr->transfer(TMEMBER(_editorMode));
+ persistMgr->transferBool(TMEMBER(_editorMode));
persistMgr->transferPtr(TMEMBER_PTR(_fader));
- persistMgr->transfer(TMEMBER(_freezeLevel));
+ persistMgr->transferSint32(TMEMBER(_freezeLevel));
persistMgr->transferPtr(TMEMBER_PTR(_focusedWindow));
persistMgr->transferPtr(TMEMBER_PTR(_fontStorage));
- persistMgr->transfer(TMEMBER(_interactive));
+ persistMgr->transferBool(TMEMBER(_interactive));
persistMgr->transferPtr(TMEMBER_PTR(_keyboardState));
- persistMgr->transfer(TMEMBER(_lastTime));
+ persistMgr->transferUint32(TMEMBER(_lastTime));
persistMgr->transferPtr(TMEMBER_PTR(_mainObject));
_musicSystem->persistChannels(persistMgr);
_musicSystem->persistCrossfadeSettings(persistMgr);
- persistMgr->transfer(TMEMBER(_offsetX));
- persistMgr->transfer(TMEMBER(_offsetY));
- persistMgr->transfer(TMEMBER(_offsetPercentX));
- persistMgr->transfer(TMEMBER(_offsetPercentY));
+ persistMgr->transferSint32(TMEMBER(_offsetX));
+ persistMgr->transferSint32(TMEMBER(_offsetY));
+ persistMgr->transferFloat(TMEMBER(_offsetPercentX));
+ persistMgr->transferFloat(TMEMBER(_offsetPercentY));
- persistMgr->transfer(TMEMBER(_origInteractive));
- persistMgr->transfer(TMEMBER_INT(_origState));
- persistMgr->transfer(TMEMBER(_personalizedSave));
- persistMgr->transfer(TMEMBER(_quitting));
+ persistMgr->transferBool(TMEMBER(_origInteractive));
+ persistMgr->transferSint32(TMEMBER_INT(_origState));
+ persistMgr->transferBool(TMEMBER(_personalizedSave));
+ persistMgr->transferBool(TMEMBER(_quitting));
_regObjects.persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_scEngine));
//persistMgr->transfer(TMEMBER(_soundMgr));
- persistMgr->transfer(TMEMBER_INT(_state));
+ persistMgr->transferSint32(TMEMBER_INT(_state));
//persistMgr->transfer(TMEMBER(_surfaceStorage));
- persistMgr->transfer(TMEMBER(_subtitles));
- persistMgr->transfer(TMEMBER(_subtitlesSpeed));
+ persistMgr->transferBool(TMEMBER(_subtitles));
+ persistMgr->transferSint32(TMEMBER(_subtitlesSpeed));
persistMgr->transferPtr(TMEMBER_PTR(_systemFont));
persistMgr->transferPtr(TMEMBER_PTR(_videoFont));
- persistMgr->transfer(TMEMBER(_videoSubtitles));
+ persistMgr->transferBool(TMEMBER(_videoSubtitles));
_timerNormal.persist(persistMgr);
_timerLive.persist(persistMgr);
_renderer->persistSaveLoadImages(persistMgr);
- persistMgr->transfer(TMEMBER_INT(_textEncoding));
- persistMgr->transfer(TMEMBER(_textRTL));
+ persistMgr->transferSint32(TMEMBER_INT(_textEncoding));
+ persistMgr->transferBool(TMEMBER(_textRTL));
- persistMgr->transfer(TMEMBER(_soundBufferSizeSec));
- persistMgr->transfer(TMEMBER(_suspendedRendering));
+ persistMgr->transferSint32(TMEMBER(_soundBufferSizeSec));
+ persistMgr->transferBool(TMEMBER(_suspendedRendering));
- persistMgr->transfer(TMEMBER(_mouseLockRect));
+ persistMgr->transferRect32(TMEMBER(_mouseLockRect));
_windows.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_suppressScriptErrors));
- persistMgr->transfer(TMEMBER(_autorunDisabled));
+ persistMgr->transferBool(TMEMBER(_suppressScriptErrors));
+ persistMgr->transferBool(TMEMBER(_autorunDisabled));
- persistMgr->transfer(TMEMBER(_autoSaveOnExit));
- persistMgr->transfer(TMEMBER(_autoSaveSlot));
- persistMgr->transfer(TMEMBER(_cursorHidden));
+ persistMgr->transferBool(TMEMBER(_autoSaveOnExit));
+ persistMgr->transferUint32(TMEMBER(_autoSaveSlot));
+ persistMgr->transferBool(TMEMBER(_cursorHidden));
if (!persistMgr->getIsSaving()) {
_quitting = false;
@@ -3135,7 +3131,7 @@ bool BaseGame::focusWindow(UIWindow *window) {
_gameRef->_focusedWindow = window;
}
- if (window->_mode == WINDOW_NORMAL && prev != window && _gameRef->validObject(prev) && (prev->_mode == WINDOW_EXCLUSIVE || prev->_mode == WINDOW_SYSTEM_EXCLUSIVE)) {
+ if (window->getMode() == WINDOW_NORMAL && prev != window && _gameRef->validObject(prev) && (prev->getMode() == WINDOW_EXCLUSIVE || prev->getMode() == WINDOW_SYSTEM_EXCLUSIVE)) {
return focusWindow(prev);
} else {
return STATUS_OK;
@@ -3365,10 +3361,10 @@ bool BaseGame::getCurrentViewportRect(Rect32 *rect, bool *custom) const {
*custom = true;
}
} else {
- BasePlatform::setRect(rect, _renderer->_drawOffsetX,
- _renderer->_drawOffsetY,
- _renderer->getWidth() + _renderer->_drawOffsetX,
- _renderer->getHeight() + _renderer->_drawOffsetY);
+ rect->setRect(_renderer->_drawOffsetX,
+ _renderer->_drawOffsetY,
+ _renderer->getWidth() + _renderer->_drawOffsetX,
+ _renderer->getHeight() + _renderer->_drawOffsetY);
if (custom) {
*custom = false;
}
@@ -3581,7 +3577,6 @@ bool BaseGame::onMouseLeftDown() {
_capturedObject = _activeObject;
}
_mouseLeftDown = true;
- BasePlatform::setCapture(/*_renderer->_window*/);
return STATUS_OK;
}
@@ -3592,7 +3587,6 @@ bool BaseGame::onMouseLeftUp() {
_activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT);
}
- BasePlatform::releaseCapture();
_capturedObject = nullptr;
_mouseLeftDown = false;
@@ -3734,7 +3728,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 +3896,26 @@ char *BaseGame::getKeyFromStringTable(const char *str) const {
return _settings->getKeyFromStringTable(str);
}
-} // end of namespace Wintermute
+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..742d6f548d 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,14 +150,14 @@ public:
BaseScriptable *_mathClass;
BaseSurfaceStorage *_surfaceStorage;
BaseFontStorage *_fontStorage;
- BaseGame(const Common::String &gameId);
+ BaseGame(const Common::String &targetName);
virtual ~BaseGame();
bool _debugDebugMode;
int32 _sequence;
virtual bool loadFile(const char *filename);
- virtual bool loadBuffer(byte *buffer, bool complete = true);
+ virtual bool loadBuffer(char *buffer, bool complete = true);
int32 _viewportSP;
@@ -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:
@@ -356,6 +358,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp
index ac23801e4c..8894fb843f 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,28 +205,28 @@ 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;
}
bool BaseGameMusic::persistChannels(BasePersistenceManager *persistMgr) {
for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
persistMgr->transferPtr(TMEMBER_PTR(_music[i]));
- persistMgr->transfer(TMEMBER(_musicStartTime[i]));
+ persistMgr->transferUint32(TMEMBER(_musicStartTime[i]));
}
return true;
}
bool BaseGameMusic::persistCrossfadeSettings(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_musicCrossfadeRunning));
- persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime));
- persistMgr->transfer(TMEMBER(_musicCrossfadeLength));
- persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1));
- persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2));
- persistMgr->transfer(TMEMBER(_musicCrossfadeSwap));
+ persistMgr->transferBool(TMEMBER(_musicCrossfadeRunning));
+ persistMgr->transferUint32(TMEMBER(_musicCrossfadeStartTime));
+ persistMgr->transferUint32(TMEMBER(_musicCrossfadeLength));
+ persistMgr->transferSint32(TMEMBER(_musicCrossfadeChannel1));
+ persistMgr->transferSint32(TMEMBER(_musicCrossfadeChannel2));
+ persistMgr->transferBool(TMEMBER(_musicCrossfadeSwap));
return true;
}
@@ -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();
@@ -503,4 +503,4 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h
index 0ac904b8c1..72c7a171a6 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:
@@ -68,6 +68,6 @@ private:
int32 _musicCrossfadeChannel2;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_game_settings.cpp b/engines/wintermute/base/base_game_settings.cpp
index 55fbe39fd2..43809b5d1e 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,90 +101,90 @@ bool BaseGameSettings::loadSettings(const char *filename) {
TOKEN_TABLE(SAVED_GAME_EXT)
TOKEN_TABLE(GUID)
TOKEN_TABLE_END
-
-
- byte *origBuffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+
+
+ char *origBuffer = (char *)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;
+
+ char *buffer = origBuffer;
+ char *params;
int cmd;
BaseParser parser;
-
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SETTINGS) {
+
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_SETTINGS) {
BaseEngine::LOG(0, "'SETTINGS' keyword expected in game settings file.");
return STATUS_FAILED;
}
buffer = params;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_GAME:
delete[] _gameFile;
- _gameFile = new char[strlen((char *)params) + 1];
+ _gameFile = new char[strlen(params) + 1];
if (_gameFile) {
- strcpy(_gameFile, (char *)params);
+ strcpy(_gameFile, params);
}
break;
-
+
case TOKEN_STRING_TABLE:
- if (DID_FAIL(_stringTable->loadFile((char *)params))) {
+ if (DID_FAIL(_stringTable->loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
-
+
case TOKEN_RESOLUTION:
- parser.scanStr((char *)params, "%d,%d", &_resWidth, &_resHeight);
+ parser.scanStr(params, "%d,%d", &_resWidth, &_resHeight);
break;
-
+
case TOKEN_REQUIRE_3D_ACCELERATION:
- parser.scanStr((char *)params, "%b", &_requireAcceleration);
+ parser.scanStr(params, "%b", &_requireAcceleration);
break;
-
+
case TOKEN_REQUIRE_SOUND:
- parser.scanStr((char *)params, "%b", &_requireSound);
+ parser.scanStr(params, "%b", &_requireSound);
break;
-
+
case TOKEN_HWTL_MODE:
- parser.scanStr((char *)params, "%d", &_TLMode);
+ parser.scanStr(params, "%d", &_TLMode);
break;
-
+
case TOKEN_ALLOW_WINDOWED_MODE:
- parser.scanStr((char *)params, "%b", &_allowWindowed);
+ parser.scanStr(params, "%b", &_allowWindowed);
break;
-
+
case TOKEN_ALLOW_DESKTOP_RES:
- parser.scanStr((char *)params, "%b", &_allowDesktopRes);
+ parser.scanStr(params, "%b", &_allowDesktopRes);
break;
-
+
case TOKEN_ALLOW_ADVANCED:
- parser.scanStr((char *)params, "%b", &_allowAdvanced);
+ parser.scanStr(params, "%b", &_allowAdvanced);
break;
-
+
case TOKEN_ALLOW_ACCESSIBILITY_TAB:
- parser.scanStr((char *)params, "%b", &_allowAccessTab);
+ parser.scanStr(params, "%b", &_allowAccessTab);
break;
-
+
case TOKEN_ALLOW_ABOUT_TAB:
- parser.scanStr((char *)params, "%b", &_allowAboutTab);
+ parser.scanStr(params, "%b", &_allowAboutTab);
break;
-
+
case TOKEN_REGISTRY_PATH:
- //BaseEngine::instance().getRegistry()->setBasePath((char *)params);
+ //BaseEngine::instance().getRegistry()->setBasePath(params);
break;
-
+
case TOKEN_RICH_SAVED_GAMES:
- parser.scanStr((char *)params, "%b", &_richSavedGames);
+ parser.scanStr(params, "%b", &_richSavedGames);
break;
-
+
case TOKEN_SAVED_GAME_EXT:
- _savedGameExt = (char *)params;
+ _savedGameExt = 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;
}
@@ -219,4 +219,4 @@ char *BaseGameSettings::getKeyFromStringTable(const char *str) const {
return _stringTable->getKey(str);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_game_settings.h b/engines/wintermute/base/base_game_settings.h
index 1dfb0b50cc..38a2fd1042 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.
@@ -66,6 +66,6 @@ private:
bool _richSavedGames;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp
index 072a1bb71b..77469e07a5 100644
--- a/engines/wintermute/base/base_keyboard_state.cpp
+++ b/engines/wintermute/base/base_keyboard_state.cpp
@@ -221,12 +221,12 @@ bool BaseKeyboardState::persist(BasePersistenceManager *persistMgr) {
//if (!persistMgr->getIsSaving()) cleanup();
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_currentAlt));
- persistMgr->transfer(TMEMBER(_currentCharCode));
- persistMgr->transfer(TMEMBER(_currentControl));
- persistMgr->transfer(TMEMBER(_currentKeyData));
- persistMgr->transfer(TMEMBER(_currentPrintable));
- persistMgr->transfer(TMEMBER(_currentShift));
+ persistMgr->transferBool(TMEMBER(_currentAlt));
+ persistMgr->transferUint32(TMEMBER(_currentCharCode));
+ persistMgr->transferBool(TMEMBER(_currentControl));
+ persistMgr->transferUint32(TMEMBER(_currentKeyData));
+ persistMgr->transferBool(TMEMBER(_currentPrintable));
+ persistMgr->transferBool(TMEMBER(_currentShift));
if (!persistMgr->getIsSaving()) {
_keyStates = new uint8[323]; // Hardcoded size for the common/keyboard.h enum
@@ -276,17 +276,21 @@ uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) {
}
enum VKeyCodes {
- kVkSpace = 32,
- kVkLeft = 37,
- kVkUp = 38,
- kVkRight = 39,
- kVkDown = 40
+ kVkEscape = 27,
+ kVkSpace = 32,
+ kVkLeft = 37,
+ kVkUp = 38,
+ kVkRight = 39,
+ kVkDown = 40
};
//////////////////////////////////////////////////////////////////////////
Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) {
// todo
switch (vkey) {
+ case kVkEscape:
+ return Common::KEYCODE_ESCAPE;
+ break;
case kVkSpace:
return Common::KEYCODE_SPACE;
break;
@@ -310,4 +314,4 @@ Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) {
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h
index b62ece02b7..14a57ee7b8 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;
@@ -71,6 +71,6 @@ private:
Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_named_object.cpp b/engines/wintermute/base/base_named_object.cpp
index f99ec2f5db..3d1df5ab84 100644
--- a/engines/wintermute/base/base_named_object.cpp
+++ b/engines/wintermute/base/base_named_object.cpp
@@ -68,4 +68,4 @@ void BaseNamedObject::setName(const char *name) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_named_object.h b/engines/wintermute/base/base_named_object.h
index d25fec4a82..ee4a3bba6a 100644
--- a/engines/wintermute/base/base_named_object.h
+++ b/engines/wintermute/base/base_named_object.h
@@ -46,6 +46,6 @@ public:
void setName(const char *name);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
index ad181b922e..540c7dd164 100644
--- a/engines/wintermute/base/base_object.cpp
+++ b/engines/wintermute/base/base_object.cpp
@@ -63,7 +63,7 @@ BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) {
_iD = _gameRef->getSequence();
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
_rectSet = false;
_cursor = nullptr;
@@ -953,53 +953,53 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) {
BaseScriptHolder::persist(persistMgr);
for (int i = 0; i < 7; i++) {
- persistMgr->transfer(TMEMBER(_caption[i]));
+ persistMgr->transferCharPtr(TMEMBER(_caption[i]));
}
persistMgr->transferPtr(TMEMBER_PTR(_activeCursor));
- persistMgr->transfer(TMEMBER(_alphaColor));
- persistMgr->transfer(TMEMBER(_autoSoundPanning));
+ persistMgr->transferUint32(TMEMBER(_alphaColor));
+ persistMgr->transferBool(TMEMBER(_autoSoundPanning));
persistMgr->transferPtr(TMEMBER_PTR(_cursor));
- persistMgr->transfer(TMEMBER(_sharedCursors));
- persistMgr->transfer(TMEMBER(_editorAlwaysRegister));
- persistMgr->transfer(TMEMBER(_editorOnly));
- persistMgr->transfer(TMEMBER(_editorSelected));
- persistMgr->transfer(TMEMBER(_iD));
- persistMgr->transfer(TMEMBER(_is3D));
- persistMgr->transfer(TMEMBER(_movable));
- persistMgr->transfer(TMEMBER(_posX));
- persistMgr->transfer(TMEMBER(_posY));
- persistMgr->transfer(TMEMBER(_relativeScale));
- persistMgr->transfer(TMEMBER(_rotatable));
- persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transferBool(TMEMBER(_sharedCursors));
+ persistMgr->transferBool(TMEMBER(_editorAlwaysRegister));
+ persistMgr->transferBool(TMEMBER(_editorOnly));
+ persistMgr->transferBool(TMEMBER(_editorSelected));
+ persistMgr->transferSint32(TMEMBER(_iD));
+ persistMgr->transferBool(TMEMBER(_is3D));
+ persistMgr->transferBool(TMEMBER(_movable));
+ persistMgr->transferSint32(TMEMBER(_posX));
+ persistMgr->transferSint32(TMEMBER(_posY));
+ persistMgr->transferFloat(TMEMBER(_relativeScale));
+ persistMgr->transferBool(TMEMBER(_rotatable));
+ persistMgr->transferFloat(TMEMBER(_scale));
persistMgr->transferPtr(TMEMBER_PTR(_sFX));
- persistMgr->transfer(TMEMBER(_sFXStart));
- persistMgr->transfer(TMEMBER(_sFXVolume));
- persistMgr->transfer(TMEMBER(_ready));
- persistMgr->transfer(TMEMBER(_rect));
- persistMgr->transfer(TMEMBER(_rectSet));
- persistMgr->transfer(TMEMBER(_registrable));
- persistMgr->transfer(TMEMBER(_shadowable));
- persistMgr->transfer(TMEMBER(_soundEvent));
- persistMgr->transfer(TMEMBER(_zoomable));
+ persistMgr->transferUint32(TMEMBER(_sFXStart));
+ persistMgr->transferSint32(TMEMBER(_sFXVolume));
+ persistMgr->transferBool(TMEMBER(_ready));
+ persistMgr->transferRect32(TMEMBER(_rect));
+ persistMgr->transferBool(TMEMBER(_rectSet));
+ persistMgr->transferBool(TMEMBER(_registrable));
+ persistMgr->transferBool(TMEMBER(_shadowable));
+ persistMgr->transferCharPtr(TMEMBER(_soundEvent));
+ persistMgr->transferBool(TMEMBER(_zoomable));
- persistMgr->transfer(TMEMBER(_scaleX));
- persistMgr->transfer(TMEMBER(_scaleY));
+ persistMgr->transferFloat(TMEMBER(_scaleX));
+ persistMgr->transferFloat(TMEMBER(_scaleY));
- persistMgr->transfer(TMEMBER(_rotate));
- persistMgr->transfer(TMEMBER(_rotateValid));
- persistMgr->transfer(TMEMBER(_relativeRotate));
+ persistMgr->transferFloat(TMEMBER(_rotate));
+ persistMgr->transferBool(TMEMBER(_rotateValid));
+ persistMgr->transferFloat(TMEMBER(_relativeRotate));
- persistMgr->transfer(TMEMBER(_saveState));
- persistMgr->transfer(TMEMBER(_nonIntMouseEvents));
+ persistMgr->transferBool(TMEMBER(_saveState));
+ persistMgr->transferBool(TMEMBER(_nonIntMouseEvents));
- persistMgr->transfer(TMEMBER_INT(_sFXType));
- persistMgr->transfer(TMEMBER(_sFXParam1));
- persistMgr->transfer(TMEMBER(_sFXParam2));
- persistMgr->transfer(TMEMBER(_sFXParam3));
- persistMgr->transfer(TMEMBER(_sFXParam4));
+ persistMgr->transferSint32(TMEMBER_INT(_sFXType));
+ persistMgr->transferFloat(TMEMBER(_sFXParam1));
+ persistMgr->transferFloat(TMEMBER(_sFXParam2));
+ persistMgr->transferFloat(TMEMBER(_sFXParam3));
+ persistMgr->transferFloat(TMEMBER(_sFXParam4));
- persistMgr->transfer(TMEMBER_INT(_blendMode));
+ persistMgr->transferSint32(TMEMBER_INT(_blendMode));
return STATUS_OK;
}
@@ -1039,7 +1039,7 @@ bool BaseObject::setActiveCursor(const char *filename) {
//////////////////////////////////////////////////////////////////////////
-int BaseObject::getHeight() {
+int32 BaseObject::getHeight() {
return 0;
}
@@ -1242,4 +1242,4 @@ bool BaseObject::afterMove() {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h
index 7afe9cf94c..a190b1bcb4 100644
--- a/engines/wintermute/base/base_object.h
+++ b/engines/wintermute/base/base_object.h
@@ -89,7 +89,7 @@ public:
virtual bool handleMouseWheel(int delta);
virtual bool handleMouse(TMouseEvent event, TMouseButton button);
virtual bool handleKeypress(Common::Event *event, bool printable = false);
- virtual int getHeight();
+ virtual int32 getHeight();
bool setCursor(const char *filename);
bool setActiveCursor(const char *filename);
bool cleanup();
@@ -142,6 +142,6 @@ public:
virtual const char *scToString() override;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp
index a7e3bd5efb..ff9c6c81b0 100644
--- a/engines/wintermute/base/base_parser.cpp
+++ b/engines/wintermute/base/base_parser.cpp
@@ -250,10 +250,10 @@ Common::String BaseParser::getToken(char **buf) {
*t++ = 0;
} else if (*b == 0) {
*buf = b;
- return nullptr;
+ return Common::String();
} else {
// Error.
- return nullptr;
+ return Common::String();
}
*buf = b;
@@ -464,4 +464,4 @@ int32 BaseParser::scanStr(const char *in, const char *format, ...) {
return num;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_parser.h b/engines/wintermute/base/base_parser.h
index 4953ac3c0b..4bf48cc016 100644
--- a/engines/wintermute/base/base_parser.h
+++ b/engines/wintermute/base/base_parser.h
@@ -83,6 +83,6 @@ private:
char *_whiteSpace;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index 5dbacb157b..3d0fc0e925 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;
}
}
@@ -465,44 +465,53 @@ uint32 BasePersistenceManager::getDWORD() {
//////////////////////////////////////////////////////////////////////////
-void BasePersistenceManager::putString(const Common::String &val) {
- if (!val.size()) {
- putString("(null)");
- } else {
- _saveStream->writeUint32LE(val.size());
- _saveStream->writeString(val);
+void BasePersistenceManager::putString(const char *val) {
+ if (!val) {
+ _saveStream->writeUint32LE(0);
+ return;
}
-}
-Common::String BasePersistenceManager::getStringObj() {
- uint32 len = _loadStream->readUint32LE();
- char *ret = new char[len + 1];
- _loadStream->read(ret, len);
- ret[len] = '\0';
-
- Common::String retString = ret;
- delete[] ret;
+ uint32 len = strlen(val);
- if (retString == "(null)") {
- retString = "";
- }
+ _saveStream->writeUint32LE(len + 1);
+ _saveStream->write(val, len);
+}
- return retString;
+Common::String BasePersistenceManager::getStringObj() {
+ return getString();
}
//////////////////////////////////////////////////////////////////////////
char *BasePersistenceManager::getString() {
uint32 len = _loadStream->readUint32LE();
- char *ret = new char[len + 1];
- _loadStream->read(ret, len);
- ret[len] = '\0';
- if (!strcmp(ret, "(null)")) {
- delete[] ret;
- return nullptr;
+ if (checkVersion(1,2,2)) {
+ // Version 1.2.2 and above: len == strlen() + 1, NULL has len == 0
+
+ if (len == 0)
+ return nullptr;
+
+ char *ret = new char[len];
+ _loadStream->read(ret, len - 1);
+ ret[len - 1] = '\0';
+
+ return ret;
+
} else {
+
+ // Version 1.2.1 and older: NULL strings are represented as "(null)"
+ char *ret = new char[len + 1];
+ _loadStream->read(ret, len);
+ ret[len] = '\0';
+
+ if (!strcmp(ret, "(null)")) {
+ delete[] ret;
+ return nullptr;
+ }
+
return ret;
}
+
}
bool BasePersistenceManager::putTimeDate(const TimeDate &t) {
@@ -536,8 +545,7 @@ void BasePersistenceManager::putFloat(float val) {
int exponent = 0;
float significand = frexp(val, &exponent);
Common::String str = Common::String::format("FS%f", significand);
- _saveStream->writeUint32LE(str.size());
- _saveStream->writeString(str);
+ putString(str.c_str());
_saveStream->writeSint32LE(exponent);
}
@@ -559,8 +567,7 @@ void BasePersistenceManager::putDouble(double val) {
int exponent = 0;
double significand = frexp(val, &exponent);
Common::String str = Common::String::format("DS%f", significand);
- _saveStream->writeUint32LE(str.size());
- _saveStream->writeString(str);
+ putString(str.c_str());
_saveStream->writeSint32LE(exponent);
}
@@ -580,7 +587,7 @@ double BasePersistenceManager::getDouble() {
//////////////////////////////////////////////////////////////////////////
// bool
-bool BasePersistenceManager::transfer(const char *name, bool *val) {
+bool BasePersistenceManager::transferBool(const char *name, bool *val) {
if (_saving) {
_saveStream->writeByte(*val);
if (_saveStream->err()) {
@@ -599,7 +606,7 @@ bool BasePersistenceManager::transfer(const char *name, bool *val) {
//////////////////////////////////////////////////////////////////////////
// int
-bool BasePersistenceManager::transfer(const char *name, int32 *val) {
+bool BasePersistenceManager::transferSint32(const char *name, int32 *val) {
if (_saving) {
_saveStream->writeSint32LE(*val);
if (_saveStream->err()) {
@@ -618,7 +625,7 @@ bool BasePersistenceManager::transfer(const char *name, int32 *val) {
//////////////////////////////////////////////////////////////////////////
// DWORD
-bool BasePersistenceManager::transfer(const char *name, uint32 *val) {
+bool BasePersistenceManager::transferUint32(const char *name, uint32 *val) {
if (_saving) {
_saveStream->writeUint32LE(*val);
if (_saveStream->err()) {
@@ -637,7 +644,7 @@ bool BasePersistenceManager::transfer(const char *name, uint32 *val) {
//////////////////////////////////////////////////////////////////////////
// float
-bool BasePersistenceManager::transfer(const char *name, float *val) {
+bool BasePersistenceManager::transferFloat(const char *name, float *val) {
if (_saving) {
putFloat(*val);
if (_saveStream->err()) {
@@ -656,7 +663,7 @@ bool BasePersistenceManager::transfer(const char *name, float *val) {
//////////////////////////////////////////////////////////////////////////
// double
-bool BasePersistenceManager::transfer(const char *name, double *val) {
+bool BasePersistenceManager::transferDouble(const char *name, double *val) {
if (_saving) {
putDouble(*val);
if (_saveStream->err()) {
@@ -675,7 +682,7 @@ bool BasePersistenceManager::transfer(const char *name, double *val) {
//////////////////////////////////////////////////////////////////////////
// char*
-bool BasePersistenceManager::transfer(const char *name, char **val) {
+bool BasePersistenceManager::transferCharPtr(const char *name, char **val) {
if (_saving) {
putString(*val);
return STATUS_OK;
@@ -692,7 +699,7 @@ bool BasePersistenceManager::transfer(const char *name, char **val) {
//////////////////////////////////////////////////////////////////////////
// const char*
-bool BasePersistenceManager::transfer(const char *name, const char **val) {
+bool BasePersistenceManager::transferConstChar(const char *name, const char **val) {
if (_saving) {
putString(*val);
return STATUS_OK;
@@ -709,9 +716,9 @@ bool BasePersistenceManager::transfer(const char *name, const char **val) {
//////////////////////////////////////////////////////////////////////////
// Common::String
-bool BasePersistenceManager::transfer(const char *name, Common::String *val) {
+bool BasePersistenceManager::transferString(const char *name, Common::String *val) {
if (_saving) {
- putString(*val);
+ putString(val->c_str());
return STATUS_OK;
} else {
char *str = getString();
@@ -730,39 +737,8 @@ bool BasePersistenceManager::transfer(const char *name, Common::String *val) {
}
//////////////////////////////////////////////////////////////////////////
-bool BasePersistenceManager::transfer(const char *name, AnsiStringArray &val) {
- size_t size;
-
- if (_saving) {
- size = val.size();
- _saveStream->writeUint32LE(size);
-
- for (AnsiStringArray::iterator it = val.begin(); it != val.end(); ++it) {
- putString((*it).c_str());
- }
- } else {
- val.clear();
- size = _loadStream->readUint32LE();
-
- for (size_t i = 0; i < size; i++) {
- char *str = getString();
- if (_loadStream->err()) {
- delete[] str;
- return STATUS_FAILED;
- }
- if (str) {
- val.push_back(str);
- }
- delete[] str;
- }
- }
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
// BYTE
-bool BasePersistenceManager::transfer(const char *name, byte *val) {
+bool BasePersistenceManager::transferByte(const char *name, byte *val) {
if (_saving) {
_saveStream->writeByte(*val);
if (_saveStream->err()) {
@@ -781,7 +757,7 @@ bool BasePersistenceManager::transfer(const char *name, byte *val) {
//////////////////////////////////////////////////////////////////////////
// RECT
-bool BasePersistenceManager::transfer(const char *name, Rect32 *val) {
+bool BasePersistenceManager::transferRect32(const char *name, Rect32 *val) {
if (_saving) {
_saveStream->writeSint32LE(val->left);
_saveStream->writeSint32LE(val->top);
@@ -806,7 +782,7 @@ bool BasePersistenceManager::transfer(const char *name, Rect32 *val) {
//////////////////////////////////////////////////////////////////////////
// POINT
-bool BasePersistenceManager::transfer(const char *name, Point32 *val) {
+bool BasePersistenceManager::transferPoint32(const char *name, Point32 *val) {
if (_saving) {
_saveStream->writeSint32LE(val->x);
_saveStream->writeSint32LE(val->y);
@@ -827,7 +803,7 @@ bool BasePersistenceManager::transfer(const char *name, Point32 *val) {
//////////////////////////////////////////////////////////////////////////
// Vector2
-bool BasePersistenceManager::transfer(const char *name, Vector2 *val) {
+bool BasePersistenceManager::transferVector2(const char *name, Vector2 *val) {
if (_saving) {
putFloat(val->x);
putFloat(val->y);
@@ -887,4 +863,4 @@ bool BasePersistenceManager::checkVersion(byte verMajor, byte verMinor, byte ver
return true;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h
index 7b578085ba..43259b26ff 100644
--- a/engines/wintermute/base/base_persistence_manager.h
+++ b/engines/wintermute/base/base_persistence_manager.h
@@ -52,7 +52,7 @@ public:
void putDWORD(uint32 val);
char *getString();
Common::String getStringObj();
- void putString(const Common::String &val);
+ void putString(const char *val);
float getFloat();
void putFloat(float val);
double getDouble();
@@ -74,19 +74,18 @@ public:
byte *_richBuffer;
bool transferPtr(const char *name, void *val);
- bool transfer(const char *name, int32 *val);
- bool transfer(const char *name, uint32 *val);
- bool transfer(const char *name, float *val);
- bool transfer(const char *name, double *val);
- bool transfer(const char *name, bool *val);
- bool transfer(const char *name, byte *val);
- bool transfer(const char *name, Rect32 *val);
- bool transfer(const char *name, Point32 *val);
- bool transfer(const char *name, const char **val);
- bool transfer(const char *name, char **val);
- bool transfer(const char *name, Common::String *val);
- bool transfer(const char *name, Vector2 *val);
- bool transfer(const char *name, AnsiStringArray &Val);
+ bool transferSint32(const char *name, int32 *val);
+ bool transferUint32(const char *name, uint32 *val);
+ bool transferFloat(const char *name, float *val);
+ bool transferDouble(const char *name, double *val);
+ bool transferBool(const char *name, bool *val);
+ bool transferByte(const char *name, byte *val);
+ bool transferRect32(const char *name, Rect32 *val);
+ bool transferPoint32(const char *name, Point32 *val);
+ bool transferConstChar(const char *name, const char **val);
+ bool transferCharPtr(const char *name, char **val);
+ bool transferString(const char *name, Common::String *val);
+ bool transferVector2(const char *name, Vector2 *val);
BasePersistenceManager(const char *savePrefix = nullptr, bool deleteSingleton = false);
virtual ~BasePersistenceManager();
bool checkVersion(byte verMajor, byte verMinor, byte verBuild);
@@ -115,6 +114,6 @@ private:
BaseGame *_gameRef;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_point.cpp b/engines/wintermute/base/base_point.cpp
index fbd8960894..84b6a629c7 100644
--- a/engines/wintermute/base/base_point.cpp
+++ b/engines/wintermute/base/base_point.cpp
@@ -54,10 +54,10 @@ BasePoint::BasePoint(int initX, int initY) {
//////////////////////////////////////////////////////////////////////////
bool BasePoint::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(x));
- persistMgr->transfer(TMEMBER(y));
+ persistMgr->transferSint32(TMEMBER(x));
+ persistMgr->transferSint32(TMEMBER(y));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_point.h b/engines/wintermute/base/base_point.h
index 26568d5d0b..cf8a5be336 100644
--- a/engines/wintermute/base/base_point.h
+++ b/engines/wintermute/base/base_point.h
@@ -45,6 +45,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_quick_msg.cpp b/engines/wintermute/base/base_quick_msg.cpp
index 50a9031eee..ac0c107d3b 100644
--- a/engines/wintermute/base/base_quick_msg.cpp
+++ b/engines/wintermute/base/base_quick_msg.cpp
@@ -27,14 +27,13 @@
*/
#include "engines/wintermute/base/base_quick_msg.h"
-#include "engines/wintermute/base/base_game.h"
namespace Wintermute {
//////////////////////////////////////////////////////////////////////////
-BaseQuickMsg::BaseQuickMsg(BaseGame *inGame, const char *text) {
+BaseQuickMsg::BaseQuickMsg(uint32 startTime, const char *text) {
_text = text;
- _startTime = _gameRef->_currentTime;
+ _startTime = startTime;
}
@@ -48,4 +47,9 @@ const char *BaseQuickMsg::getText() const {
return _text.c_str();
}
-} // end of namespace Wintermute
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseQuickMsg::getStartTime() const {
+ return _startTime;
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_quick_msg.h b/engines/wintermute/base/base_quick_msg.h
index 0d342b3b12..b706424c18 100644
--- a/engines/wintermute/base/base_quick_msg.h
+++ b/engines/wintermute/base/base_quick_msg.h
@@ -32,18 +32,18 @@
#include "common/str.h"
namespace Wintermute {
-class BaseGame;
+
class BaseQuickMsg {
public:
const char *getText() const;
- uint32 _startTime;
- BaseQuickMsg(BaseGame *inGame, const char *text);
+ uint32 getStartTime() const;
+ BaseQuickMsg(uint32 startTime, const char *text);
virtual ~BaseQuickMsg();
private:
- BaseGame *_gameRef;
Common::String _text;
+ uint32 _startTime;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp
index 2dabe6ae44..dc17b18ea2 100644
--- a/engines/wintermute/base/base_region.cpp
+++ b/engines/wintermute/base/base_region.cpp
@@ -48,7 +48,7 @@ BaseRegion::BaseRegion(BaseGame *inGame) : BaseObject(inGame) {
_lastMimicScale = -1;
_lastMimicX = _lastMimicY = INT_MIN;
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
}
@@ -65,7 +65,7 @@ void BaseRegion::cleanup() {
}
_points.clear();
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
_editorSelectedPoint = -1;
}
@@ -102,7 +102,7 @@ bool BaseRegion::pointInRegion(int x, int y) {
//////////////////////////////////////////////////////////////////////////
bool BaseRegion::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
BaseEngine::LOG(0, "BaseRegion::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -135,7 +135,7 @@ TOKEN_DEF(EDITOR_SELECTED_POINT)
TOKEN_DEF(PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool BaseRegion::loadBuffer(byte *buffer, bool complete) {
+bool BaseRegion::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(REGION)
TOKEN_TABLE(TEMPLATE)
@@ -148,12 +148,12 @@ bool BaseRegion::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_REGION) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_REGION) {
BaseEngine::LOG(0, "'REGION' keyword expected.");
return STATUS_FAILED;
}
@@ -165,39 +165,39 @@ bool BaseRegion::loadBuffer(byte *buffer, bool complete) {
}
_points.clear();
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_ACTIVE:
- parser.scanStr((char *)params, "%b", &_active);
+ parser.scanStr(params, "%b", &_active);
break;
case TOKEN_POINT: {
int x, y;
- parser.scanStr((char *)params, "%d,%d", &x, &y);
+ parser.scanStr(params, "%d,%d", &x, &y);
_points.add(new BasePoint(x, y));
}
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_EDITOR_SELECTED_POINT:
- parser.scanStr((char *)params, "%d", &_editorSelectedPoint);
+ parser.scanStr(params, "%d", &_editorSelectedPoint);
break;
case TOKEN_PROPERTY:
@@ -430,11 +430,11 @@ bool BaseRegion::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_active));
- persistMgr->transfer(TMEMBER(_editorSelectedPoint));
- persistMgr->transfer(TMEMBER(_lastMimicScale));
- persistMgr->transfer(TMEMBER(_lastMimicX));
- persistMgr->transfer(TMEMBER(_lastMimicY));
+ persistMgr->transferBool(TMEMBER(_active));
+ persistMgr->transferSint32(TMEMBER(_editorSelectedPoint));
+ persistMgr->transferFloat(TMEMBER(_lastMimicScale));
+ persistMgr->transferSint32(TMEMBER(_lastMimicX));
+ persistMgr->transferSint32(TMEMBER(_lastMimicY));
_points.persist(persistMgr);
return STATUS_OK;
@@ -491,7 +491,7 @@ bool BaseRegion::ptInPolygon(int32 x, int32 y) {
//////////////////////////////////////////////////////////////////////////
bool BaseRegion::getBoundingRect(Rect32 *rect) {
if (_points.size() == 0) {
- BasePlatform::setRectEmpty(rect);
+ rect->setEmpty();
} else {
int32 minX = INT_MAX, minY = INT_MAX, maxX = INT_MIN, maxY = INT_MIN;
@@ -502,7 +502,7 @@ bool BaseRegion::getBoundingRect(Rect32 *rect) {
maxX = MAX(maxX, _points[i]->x);
maxY = MAX(maxY, _points[i]->y);
}
- BasePlatform::setRect(rect, minX, minY, maxX, maxY);
+ rect->setRect(minX, minY, maxX, maxY);
}
return STATUS_OK;
}
@@ -532,4 +532,4 @@ bool BaseRegion::mimic(BaseRegion *region, float scale, int x, int y) {
return createRegion() ? STATUS_OK : STATUS_FAILED;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h
index 67ca158897..846dcfc341 100644
--- a/engines/wintermute/base/base_region.h
+++ b/engines/wintermute/base/base_region.h
@@ -48,7 +48,7 @@ public:
bool pointInRegion(int x, int y);
bool createRegion();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
Rect32 _rect;
BaseArray<BasePoint *> _points;
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) { return saveAsText(buffer, indent, nullptr); }
@@ -65,6 +65,6 @@ private:
int32 _lastMimicY;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp
index 036bac1dd8..5fb0b62713 100644
--- a/engines/wintermute/base/base_script_holder.cpp
+++ b/engines/wintermute/base/base_script_holder.cpp
@@ -280,14 +280,14 @@ bool BaseScriptHolder::saveAsText(BaseDynamicBuffer *buffer, int indent) {
bool BaseScriptHolder::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_freezable));
+ persistMgr->transferCharPtr(TMEMBER(_filename));
+ persistMgr->transferBool(TMEMBER(_freezable));
if (persistMgr->getIsSaving()) {
const char *name = getName();
- persistMgr->transfer(TMEMBER(name));
+ persistMgr->transferConstChar(TMEMBER(name));
} else {
char *name;
- persistMgr->transfer(TMEMBER(name));
+ persistMgr->transferCharPtr(TMEMBER(name));
setName(name);
delete[] name;
}
@@ -370,19 +370,19 @@ TOKEN_DEF(NAME)
TOKEN_DEF(VALUE)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) {
+bool BaseScriptHolder::parseProperty(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(PROPERTY)
TOKEN_TABLE(NAME)
TOKEN_TABLE(VALUE)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_PROPERTY) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_PROPERTY) {
BaseEngine::LOG(0, "'PROPERTY' keyword expected.");
return STATUS_FAILED;
}
@@ -392,13 +392,13 @@ bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) {
char *propName = nullptr;
char *propValue = nullptr;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_NAME:
delete[] propName;
- propName = new char[strlen((char *)params) + 1];
+ propName = new char[strlen(params) + 1];
if (propName) {
- strcpy(propName, (char *)params);
+ strcpy(propName, params);
} else {
cmd = PARSERR_GENERIC;
}
@@ -406,9 +406,9 @@ bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) {
case TOKEN_VALUE:
delete[] propValue;
- propValue = new char[strlen((char *)params) + 1];
+ propValue = new char[strlen(params) + 1];
if (propValue) {
- strcpy(propValue, (char *)params);
+ strcpy(propValue, params);
} else {
cmd = PARSERR_GENERIC;
}
@@ -500,4 +500,4 @@ bool BaseScriptHolder::sendEvent(const char *eventName) {
return DID_SUCCEED(applyEvent(eventName));
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h
index 38a3f935d3..b4e22a59ee 100644
--- a/engines/wintermute/base/base_script_holder.h
+++ b/engines/wintermute/base/base_script_holder.h
@@ -53,7 +53,7 @@ public:
bool applyEvent(const char *eventName, bool unbreakable = false);
void setFilename(const char *filename);
const char *getFilename() { return _filename; }
- bool parseProperty(byte *buffer, bool complete = true);
+ bool parseProperty(char *buffer, bool complete = true);
bool _freezable;
bool _ready;
@@ -71,6 +71,6 @@ public:
virtual bool sendEvent(const char *eventName);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp
index 5753b0482b..d2ff627f0a 100644
--- a/engines/wintermute/base/base_scriptable.cpp
+++ b/engines/wintermute/base/base_scriptable.cpp
@@ -153,7 +153,7 @@ void BaseScriptable::scSetBool(bool val) {
//////////////////////////////////////////////////////////////////////////
bool BaseScriptable::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_refCount));
+ persistMgr->transferSint32(TMEMBER(_refCount));
persistMgr->transferPtr(TMEMBER_PTR(_scProp));
persistMgr->transferPtr(TMEMBER_PTR(_scValue));
@@ -188,4 +188,4 @@ ScScript *BaseScriptable::invokeMethodThread(const char *methodName) {
return nullptr;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h
index f23d7faa5b..08fd32081a 100644
--- a/engines/wintermute/base/base_scriptable.h
+++ b/engines/wintermute/base/base_scriptable.h
@@ -78,6 +78,6 @@ BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack);
BaseScriptable *makeSXStore(BaseGame *inGame);
BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack);
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp
index c920da9ee9..b1fcb42dcc 100644
--- a/engines/wintermute/base/base_sprite.cpp
+++ b/engines/wintermute/base/base_sprite.cpp
@@ -168,7 +168,7 @@ bool BaseSprite::loadFile(const Common::String &filename, int lifeTime, TSpriteC
ret = STATUS_OK;
}
} else {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer) {
if (DID_FAIL(ret = loadBuffer(buffer, true, lifeTime, cacheType))) {
BaseEngine::LOG(0, "Error parsing SPRITE file '%s'", filename.c_str());
@@ -204,7 +204,7 @@ TOKEN_DEF(EDITOR_BG_ALPHA)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////
-bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) {
+bool BaseSprite::loadBuffer(char *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(CONTINUOUS)
TOKEN_TABLE(SPRITE)
@@ -223,7 +223,7 @@ bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCa
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
@@ -231,7 +231,7 @@ bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCa
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SPRITE) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_SPRITE) {
BaseEngine::LOG(0, "'SPRITE' keyword expected.");
return STATUS_FAILED;
}
@@ -240,30 +240,30 @@ bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCa
int frameCount = 1;
BaseFrame *frame;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_CONTINUOUS:
- parser.scanStr((char *)params, "%b", &_continuous);
+ parser.scanStr(params, "%b", &_continuous);
break;
case TOKEN_EDITOR_MUTED:
- parser.scanStr((char *)params, "%b", &_editorMuted);
+ parser.scanStr(params, "%b", &_editorMuted);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_LOOPING:
- parser.scanStr((char *)params, "%b", &_looping);
+ parser.scanStr(params, "%b", &_looping);
break;
case TOKEN_PRECISE:
- parser.scanStr((char *)params, "%b", &_precise);
+ parser.scanStr(params, "%b", &_precise);
break;
case TOKEN_STREAMED:
- parser.scanStr((char *)params, "%b", &_streamed);
+ parser.scanStr(params, "%b", &_streamed);
if (_streamed && lifeTime == -1) {
lifeTime = 500;
cacheType = CACHE_ALL;
@@ -271,33 +271,33 @@ bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCa
break;
case TOKEN_STREAMED_KEEP_LOADED:
- parser.scanStr((char *)params, "%b", &_streamedKeepLoaded);
+ parser.scanStr(params, "%b", &_streamedKeepLoaded);
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_EDITOR_BG_FILE:
if (_gameRef->_editorMode) {
delete[] _editorBgFile;
- _editorBgFile = new char[strlen((char *)params) + 1];
+ _editorBgFile = new char[strlen(params) + 1];
if (_editorBgFile) {
- strcpy(_editorBgFile, (char *)params);
+ strcpy(_editorBgFile, params);
}
}
break;
case TOKEN_EDITOR_BG_OFFSET_X:
- parser.scanStr((char *)params, "%d", &_editorBgOffsetX);
+ parser.scanStr(params, "%d", &_editorBgOffsetX);
break;
case TOKEN_EDITOR_BG_OFFSET_Y:
- parser.scanStr((char *)params, "%d", &_editorBgOffsetY);
+ parser.scanStr(params, "%d", &_editorBgOffsetY);
break;
case TOKEN_EDITOR_BG_ALPHA:
- parser.scanStr((char *)params, "%d", &_editorBgAlpha);
+ parser.scanStr(params, "%d", &_editorBgAlpha);
_editorBgAlpha = MIN<int32>(_editorBgAlpha, 255);
_editorBgAlpha = MAX<int32>(_editorBgAlpha, 0);
break;
@@ -462,7 +462,7 @@ bool BaseSprite::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float
return false;
}
- BasePlatform::setRectEmpty(rect);
+ rect->setEmpty();
for (uint32 i = 0; i < _frames.size(); i++) {
Rect32 frame;
Rect32 temp;
@@ -520,29 +520,29 @@ bool BaseSprite::saveAsText(BaseDynamicBuffer *buffer, int indent) {
bool BaseSprite::persist(BasePersistenceManager *persistMgr) {
BaseScriptHolder::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_canBreak));
- persistMgr->transfer(TMEMBER(_changed));
- persistMgr->transfer(TMEMBER(_paused));
- persistMgr->transfer(TMEMBER(_continuous));
- persistMgr->transfer(TMEMBER(_currentFrame));
- persistMgr->transfer(TMEMBER(_editorAllFrames));
- persistMgr->transfer(TMEMBER(_editorBgAlpha));
- persistMgr->transfer(TMEMBER(_editorBgFile));
- persistMgr->transfer(TMEMBER(_editorBgOffsetX));
- persistMgr->transfer(TMEMBER(_editorBgOffsetY));
- persistMgr->transfer(TMEMBER(_editorMuted));
- persistMgr->transfer(TMEMBER(_finished));
+ persistMgr->transferBool(TMEMBER(_canBreak));
+ persistMgr->transferBool(TMEMBER(_changed));
+ persistMgr->transferBool(TMEMBER(_paused));
+ persistMgr->transferBool(TMEMBER(_continuous));
+ persistMgr->transferSint32(TMEMBER(_currentFrame));
+ persistMgr->transferBool(TMEMBER(_editorAllFrames));
+ persistMgr->transferSint32(TMEMBER(_editorBgAlpha));
+ persistMgr->transferCharPtr(TMEMBER(_editorBgFile));
+ persistMgr->transferSint32(TMEMBER(_editorBgOffsetX));
+ persistMgr->transferSint32(TMEMBER(_editorBgOffsetY));
+ persistMgr->transferBool(TMEMBER(_editorMuted));
+ persistMgr->transferBool(TMEMBER(_finished));
_frames.persist(persistMgr);
- persistMgr->transfer(TMEMBER(_lastFrameTime));
- persistMgr->transfer(TMEMBER(_looping));
- persistMgr->transfer(TMEMBER(_moveX));
- persistMgr->transfer(TMEMBER(_moveY));
+ persistMgr->transferUint32(TMEMBER(_lastFrameTime));
+ persistMgr->transferBool(TMEMBER(_looping));
+ persistMgr->transferSint32(TMEMBER(_moveX));
+ persistMgr->transferSint32(TMEMBER(_moveY));
persistMgr->transferPtr(TMEMBER_PTR(_owner));
- persistMgr->transfer(TMEMBER(_precise));
- persistMgr->transfer(TMEMBER(_streamed));
- persistMgr->transfer(TMEMBER(_streamedKeepLoaded));
+ persistMgr->transferBool(TMEMBER(_precise));
+ persistMgr->transferBool(TMEMBER(_streamed));
+ persistMgr->transferBool(TMEMBER(_streamedKeepLoaded));
return STATUS_OK;
@@ -817,4 +817,4 @@ bool BaseSprite::killAllSounds() {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h
index 05cb9fc936..54d595f655 100644
--- a/engines/wintermute/base/base_sprite.h
+++ b/engines/wintermute/base/base_sprite.h
@@ -32,6 +32,7 @@
#include "engines/wintermute/coll_templ.h"
#include "engines/wintermute/base/base_script_holder.h"
+#include "engines/wintermute/graphics/transform_tools.h"
namespace Wintermute {
class BaseFrame;
@@ -44,17 +45,17 @@ public:
void setDefaults();
DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder)
- bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
+ bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = kDefaultZoomX, float scaleY = kDefaultZoomY);
int32 _moveY;
int32 _moveX;
- bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
- bool getCurrentFrame(float zoomX = 100, float zoomY = 100);
+ bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod, float rotate = kDefaultAngle, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool getCurrentFrame(float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY);
void reset();
bool isChanged();
bool isFinished();
- bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
+ bool loadBuffer(char *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
- bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF);
+ bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod);
bool _looping;
int32 _currentFrame;
bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = nullptr);
@@ -88,6 +89,6 @@ private:
bool killAllSounds();
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp
index 8207c32244..3d9cc4f8b3 100644
--- a/engines/wintermute/base/base_string_table.cpp
+++ b/engines/wintermute/base/base_string_table.cpp
@@ -253,4 +253,4 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h
index 128807bd1a..f8808f5b27 100644
--- a/engines/wintermute/base/base_string_table.h
+++ b/engines/wintermute/base/base_string_table.h
@@ -50,6 +50,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp
index d93cf667f1..38eebb067b 100644
--- a/engines/wintermute/base/base_sub_frame.cpp
+++ b/engines/wintermute/base/base_sub_frame.cpp
@@ -34,10 +34,11 @@
#include "engines/wintermute/base/base_surface_storage.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_engine.h"
-#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/graphics/transform_tools.h"
+#include "engines/wintermute/graphics/transform_struct.h"
namespace Wintermute {
@@ -46,12 +47,13 @@ IMPLEMENT_PERSISTENT(BaseSubFrame, false)
//////////////////////////////////////////////////////////////////////////
BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) {
_surface = nullptr;
- _hotspotX = _hotspotY = 0;
- _alpha = 0xFFFFFFFF;
+ _hotspotX = kDefaultHotspotX;
+ _hotspotY = kDefaultHotspotY;
+ _alpha = kDefaultRgbaMod;
_transparent = 0xFFFF00FF;
_wantsDefaultRect = false;
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
_editorSelected = false;
@@ -94,7 +96,7 @@ TOKEN_DEF(EDITOR_SELECTED)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////
-bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
+bool BaseSubFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(IMAGE)
TOKEN_TABLE(TRANSPARENT)
@@ -118,13 +120,13 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
int r = 255, g = 255, b = 255;
int ar = 255, ag = 255, ab = 255, alpha = 255;
bool custoTrans = false;
- BasePlatform::setRectEmpty(&rect);
+ rect.setEmpty();
char *surfaceFile = nullptr;
delete _surface;
_surface = nullptr;
- while ((cmd = parser.getCommand((char **)&buffer, commands, &params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_IMAGE:
surfaceFile = params;
@@ -176,7 +178,7 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
break;
case TOKEN_EDITOR_PROPERTY:
- parseEditorProperty((byte *)params, false);
+ parseEditorProperty(params, false);
break;
}
}
@@ -205,7 +207,7 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
return STATUS_FAILED;
}
*/
- if (BasePlatform::isRectEmpty(&rect)) {
+ if (rect.isRectEmpty()) {
setDefaultRect();
} else {
setRect(rect);
@@ -216,7 +218,7 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
Rect32 BaseSubFrame::getRect() {
if (_wantsDefaultRect && _surface) {
- BasePlatform::setRect(&_rect, 0, 0, _surface->getWidth(), _surface->getHeight());
+ _rect.setRect(0, 0, _surface->getWidth(), _surface->getHeight());
_wantsDefaultRect = false;
}
return _rect;
@@ -233,12 +235,18 @@ const char* BaseSubFrame::getSurfaceFilename() {
//////////////////////////////////////////////////////////////////////
bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
+
+ rotate = fmod(rotate, 360.0f);
+ if (rotate < 0) {
+ rotate += 360.0f;
+ }
+
if (!_surface) {
return STATUS_OK;
}
if (registerOwner != nullptr && !_decoration) {
- if (zoomX == 100 && zoomY == 100) {
+ if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) {
BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise));
} else {
BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + getRect().left) * (zoomX / 100)), (int)(y - (_hotspotY + getRect().top) * (zoomY / 100)), (int)((getRect().right - getRect().left) * (zoomX / 100)), (int)((getRect().bottom - getRect().top) * (zoomY / 100)), zoomX, zoomY, precise));
@@ -251,17 +259,24 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl
bool res;
//if (Alpha==0xFFFFFFFF) Alpha = _alpha; // TODO: better (combine owner's and self alpha)
- if (_alpha != 0xFFFFFFFF) {
+ if (_alpha != kDefaultRgbaMod) {
alpha = _alpha;
}
- if (rotate != 0.0f) {
- res = _surface->displayTransform((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), _hotspotX, _hotspotY, getRect(), zoomX, zoomY, alpha, rotate, blendMode, _mirrorX, _mirrorY);
+ if (rotate != kDefaultAngle) {
+ Point32 boxOffset, rotatedHotspot, hotspotOffset, newOrigin;
+ Point32 origin(x, y);
+ Rect32 oldRect = getRect();
+ Point32 newHotspot;
+ TransformStruct transform = TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0);
+ Rect32 newRect = TransformTools::newRect (oldRect, transform, &newHotspot);
+ newOrigin = origin - newHotspot;
+ res = _surface->displayTransform(newOrigin.x, newOrigin.y, oldRect, newRect, transform);
} else {
- if (zoomX == 100 && zoomY == 100) {
+ if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) {
res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, getRect(), alpha, blendMode, _mirrorX, _mirrorY);
} else {
- res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY);
+ res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY);
}
}
@@ -278,11 +293,10 @@ bool BaseSubFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, flo
float ratioX = scaleX / 100.0f;
float ratioY = scaleY / 100.0f;
- BasePlatform::setRect(rect,
- (int)(x - _hotspotX * ratioX),
- (int)(y - _hotspotY * ratioY),
- (int)(x - _hotspotX * ratioX + (getRect().right - getRect().left) * ratioX),
- (int)(y - _hotspotY * ratioY + (getRect().bottom - getRect().top) * ratioY));
+ rect->setRect((int)(x - _hotspotX * ratioX),
+ (int)(y - _hotspotY * ratioY),
+ (int)(x - _hotspotX * ratioX + (getRect().right - getRect().left) * ratioX),
+ (int)(y - _hotspotY * ratioY + (getRect().bottom - getRect().top) * ratioY));
return true;
}
@@ -302,9 +316,9 @@ bool BaseSubFrame::saveAsText(BaseDynamicBuffer *buffer, int indent, bool comple
}
Rect32 rect;
- BasePlatform::setRectEmpty(&rect);
+ rect.setEmpty();
if (_surface) {
- BasePlatform::setRect(&rect, 0, 0, _surface->getWidth(), _surface->getHeight());
+ rect.setRect(0, 0, _surface->getWidth(), _surface->getHeight());
}
if (!(rect == getRect())) {
buffer->putTextIndent(indent + 2, "RECT { %d,%d,%d,%d }\n", getRect().left, getRect().top, getRect().right, getRect().bottom);
@@ -360,7 +374,7 @@ void BaseSubFrame::setDefaultRect() {
_wantsDefaultRect = true;
} else {
_wantsDefaultRect = false;
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
}
}
@@ -370,27 +384,27 @@ bool BaseSubFrame::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_2DOnly));
- persistMgr->transfer(TMEMBER(_3DOnly));
- persistMgr->transfer(TMEMBER(_alpha));
- persistMgr->transfer(TMEMBER(_decoration));
- persistMgr->transfer(TMEMBER(_editorSelected));
- persistMgr->transfer(TMEMBER(_hotspotX));
- persistMgr->transfer(TMEMBER(_hotspotY));
- persistMgr->transfer(TMEMBER(_rect));
- persistMgr->transfer(TMEMBER(_wantsDefaultRect));
-
- persistMgr->transfer(TMEMBER(_surfaceFilename));
- persistMgr->transfer(TMEMBER(_cKDefault));
- persistMgr->transfer(TMEMBER(_cKRed));
- persistMgr->transfer(TMEMBER(_cKGreen));
- persistMgr->transfer(TMEMBER(_cKBlue));
- persistMgr->transfer(TMEMBER(_lifeTime));
-
- persistMgr->transfer(TMEMBER(_keepLoaded));
- persistMgr->transfer(TMEMBER(_mirrorX));
- persistMgr->transfer(TMEMBER(_mirrorY));
- persistMgr->transfer(TMEMBER(_transparent));
+ persistMgr->transferBool(TMEMBER(_2DOnly));
+ persistMgr->transferBool(TMEMBER(_3DOnly));
+ persistMgr->transferUint32(TMEMBER(_alpha));
+ persistMgr->transferBool(TMEMBER(_decoration));
+ persistMgr->transferBool(TMEMBER(_editorSelected));
+ persistMgr->transferSint32(TMEMBER(_hotspotX));
+ persistMgr->transferSint32(TMEMBER(_hotspotY));
+ persistMgr->transferRect32(TMEMBER(_rect));
+ persistMgr->transferBool(TMEMBER(_wantsDefaultRect));
+
+ persistMgr->transferCharPtr(TMEMBER(_surfaceFilename));
+ persistMgr->transferBool(TMEMBER(_cKDefault));
+ persistMgr->transferByte(TMEMBER(_cKRed));
+ persistMgr->transferByte(TMEMBER(_cKGreen));
+ persistMgr->transferByte(TMEMBER(_cKBlue));
+ persistMgr->transferSint32(TMEMBER(_lifeTime));
+
+ persistMgr->transferBool(TMEMBER(_keepLoaded));
+ persistMgr->transferBool(TMEMBER(_mirrorX));
+ persistMgr->transferBool(TMEMBER(_mirrorY));
+ persistMgr->transferUint32(TMEMBER(_transparent));
return STATUS_OK;
}
@@ -657,4 +671,4 @@ bool BaseSubFrame::setSurfaceSimple() {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h
index 37ba34b748..4e164467e2 100644
--- a/engines/wintermute/base/base_sub_frame.h
+++ b/engines/wintermute/base/base_sub_frame.h
@@ -51,7 +51,7 @@ public:
bool _editorSelected;
BaseSubFrame(BaseGame *inGame);
virtual ~BaseSubFrame();
- bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded);
+ bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded);
bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
const char* getSurfaceFilename();
@@ -88,6 +88,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp
index 8dbd6a6d2a..f1d068674b 100644
--- a/engines/wintermute/base/base_surface_storage.cpp
+++ b/engines/wintermute/base/base_surface_storage.cpp
@@ -203,4 +203,4 @@ bool BaseSurfaceStorage::surfaceSortCB(const BaseSurface *s1, const BaseSurface
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_surface_storage.h b/engines/wintermute/base/base_surface_storage.h
index 61738e69a2..c0049d676c 100644
--- a/engines/wintermute/base/base_surface_storage.h
+++ b/engines/wintermute/base/base_surface_storage.h
@@ -52,6 +52,6 @@ public:
Common::Array<BaseSurface *> _surfaces;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp
index 1c869e6a2b..eee5f1aae7 100644
--- a/engines/wintermute/base/base_transition_manager.cpp
+++ b/engines/wintermute/base/base_transition_manager.cpp
@@ -135,4 +135,4 @@ bool BaseTransitionMgr::update() {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_transition_manager.h b/engines/wintermute/base/base_transition_manager.h
index edb3045a58..82edb9ff88 100644
--- a/engines/wintermute/base/base_transition_manager.h
+++ b/engines/wintermute/base/base_transition_manager.h
@@ -49,6 +49,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp
index f79e5c9f13..a6e8b17927 100644
--- a/engines/wintermute/base/base_viewport.cpp
+++ b/engines/wintermute/base/base_viewport.cpp
@@ -29,7 +29,6 @@
#include "engines/wintermute/base/base_viewport.h"
#include "engines/wintermute/base/base_engine.h"
#include "engines/wintermute/base/base_persistence_manager.h"
-#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/gfx/base_renderer.h"
namespace Wintermute {
@@ -38,7 +37,7 @@ IMPLEMENT_PERSISTENT(BaseViewport, false)
//////////////////////////////////////////////////////////////////////////
BaseViewport::BaseViewport(BaseGame *inGame) : BaseClass(inGame) {
- BasePlatform::setRectEmpty(&_rect);
+ _rect.setEmpty();
_mainObject = nullptr;
_offsetX = _offsetY = 0;
}
@@ -56,9 +55,9 @@ bool BaseViewport::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
persistMgr->transferPtr(TMEMBER_PTR(_mainObject));
- persistMgr->transfer(TMEMBER(_offsetX));
- persistMgr->transfer(TMEMBER(_offsetY));
- persistMgr->transfer(TMEMBER(_rect));
+ persistMgr->transferSint32(TMEMBER(_offsetX));
+ persistMgr->transferSint32(TMEMBER(_offsetY));
+ persistMgr->transferRect32(TMEMBER(_rect));
return STATUS_OK;
}
@@ -73,7 +72,7 @@ bool BaseViewport::setRect(int32 left, int32 top, int32 right, int32 bottom, boo
bottom = MIN(bottom, BaseEngine::instance().getRenderer()->getHeight());
}
- BasePlatform::setRect(&_rect, left, top, right, bottom);
+ _rect.setRect(left, top, right, bottom);
_offsetX = left;
_offsetY = top;
return STATUS_OK;
@@ -97,4 +96,4 @@ int BaseViewport::getHeight() const {
return _rect.bottom - _rect.top;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_viewport.h b/engines/wintermute/base/base_viewport.h
index 584e5a78f9..0225c02c7c 100644
--- a/engines/wintermute/base/base_viewport.h
+++ b/engines/wintermute/base/base_viewport.h
@@ -52,6 +52,6 @@ private:
Rect32 _rect;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
index 3c1ecc7a73..808dc9e00d 100644
--- a/engines/wintermute/base/file/base_disk_file.cpp
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -66,12 +66,6 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
const Common::FSNode gameDataDir(ConfMan.get("path"));
Common::FSNode curNode = gameDataDir;
- Common::String fixedPath = "";
- while (!path.empty()) {
- fixedPath += path.nextToken() + "/";
- }
- fixedPath.deleteLastChar();
-
// Parse all path-elements
while (!path.empty()) {
// Get the next path-component by slicing on '\\'
@@ -123,6 +117,8 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
if (fixedFilename.contains(':')) {
if (fixedFilename.hasPrefix("c:/windows/fonts/")) { // East Side Story refers to "c:\windows\fonts\framd.ttf"
fixedFilename = filename.c_str() + 14;
+ } else if (fixedFilename.hasPrefix("c:/carol6/svn/data/")) { // Carol Reed 6: Black Circle refers to "c:\carol6\svn\data\sprites\system\help.png"
+ fixedFilename = fixedFilename.c_str() + 19;
} else {
error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str());
}
@@ -155,7 +151,8 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
}
if (compressed) {
- uint32 dataOffset, compSize, uncompSize;
+ uint32 dataOffset, compSize;
+ unsigned long uncompSize;
dataOffset = file->readUint32LE();
compSize = file->readUint32LE();
uncompSize = file->readUint32LE();
@@ -177,7 +174,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
file->seek(dataOffset + prefixSize, SEEK_SET);
file->read(compBuffer, compSize);
- if (Common::uncompress(data, (unsigned long *)&uncompSize, compBuffer, compSize) != true) {
+ if (Common::uncompress(data, &uncompSize, compBuffer, compSize) != true) {
error("Error uncompressing file '%s'", filename.c_str());
delete[] compBuffer;
delete file;
@@ -198,4 +195,4 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
return nullptr;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_disk_file.h b/engines/wintermute/base/file/base_disk_file.h
index c9f93b80d9..81cc22b86d 100644
--- a/engines/wintermute/base/file/base_disk_file.h
+++ b/engines/wintermute/base/file/base_disk_file.h
@@ -36,6 +36,6 @@ namespace Wintermute {
Common::SeekableReadStream *openDiskFile(const Common::String &filename);
bool diskFileExists(const Common::String &filename);
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/base_file.cpp b/engines/wintermute/base/file/base_file.cpp
index f52a13211e..42eea69824 100644
--- a/engines/wintermute/base/file/base_file.cpp
+++ b/engines/wintermute/base/file/base_file.cpp
@@ -65,4 +65,4 @@ Common::SeekableReadStream *BaseFile::getMemStream() {
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_file.h b/engines/wintermute/base/file/base_file.h
index 8eda6d51d9..9acda7ffce 100644
--- a/engines/wintermute/base/file/base_file.h
+++ b/engines/wintermute/base/file/base_file.h
@@ -62,6 +62,6 @@ public:
virtual Common::SeekableReadStream *getMemStream();
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp
index 1968da6f47..846f56b55c 100644
--- a/engines/wintermute/base/file/base_file_entry.cpp
+++ b/engines/wintermute/base/file/base_file_entry.cpp
@@ -70,4 +70,4 @@ BaseFileEntry::~BaseFileEntry() {
_package = nullptr; // ref only
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h
index 6e4823d994..9d738c8c11 100644
--- a/engines/wintermute/base/file/base_file_entry.h
+++ b/engines/wintermute/base/file/base_file_entry.h
@@ -55,6 +55,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp
index 73f767c3ef..512279b72c 100644
--- a/engines/wintermute/base/file/base_package.cpp
+++ b/engines/wintermute/base/file/base_package.cpp
@@ -273,4 +273,4 @@ Common::SeekableReadStream *PackageSet::createReadStreamForMember(const Common::
return nullptr;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_package.h b/engines/wintermute/base/file/base_package.h
index bcf088aaea..18156c4f65 100644
--- a/engines/wintermute/base/file/base_package.h
+++ b/engines/wintermute/base/file/base_package.h
@@ -85,6 +85,6 @@ private:
Common::HashMap<Common::String, Common::ArchiveMemberPtr>::iterator _filesIter;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp
index 2c4ddf4875..bb172ca66a 100644
--- a/engines/wintermute/base/file/base_save_thumb_file.cpp
+++ b/engines/wintermute/base/file/base_save_thumb_file.cpp
@@ -150,4 +150,4 @@ bool BaseSaveThumbFile::seek(uint32 pos, int whence) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_save_thumb_file.h b/engines/wintermute/base/file/base_save_thumb_file.h
index 3b217525fd..faf1af9255 100644
--- a/engines/wintermute/base/file/base_save_thumb_file.h
+++ b/engines/wintermute/base/file/base_save_thumb_file.h
@@ -47,6 +47,6 @@ private:
byte *_data;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/file/dcpackage.h b/engines/wintermute/base/file/dcpackage.h
index 2234139408..a2ec5d28d5 100644
--- a/engines/wintermute/base/file/dcpackage.h
+++ b/engines/wintermute/base/file/dcpackage.h
@@ -75,6 +75,6 @@ v2: uint32 TimeDate1
*/
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/font/base_font.cpp b/engines/wintermute/base/font/base_font.cpp
index 596f9fb5c6..2a394616d1 100644
--- a/engines/wintermute/base/font/base_font.cpp
+++ b/engines/wintermute/base/font/base_font.cpp
@@ -118,18 +118,18 @@ bool BaseFont::isTrueType(BaseGame *gameRef, const Common::String &filename) {
TOKEN_TABLE_END
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
return false;
}
- byte *workBuffer = buffer;
+ char *workBuffer = buffer;
char *params;
BaseParser parser;
bool ret = false;
- if (parser.getCommand((char **)&workBuffer, commands, (char **)&params) == TOKEN_TTFONT) {
+ if (parser.getCommand(&workBuffer, commands, &params) == TOKEN_TTFONT) {
ret = true;
}
@@ -137,4 +137,4 @@ bool BaseFont::isTrueType(BaseGame *gameRef, const Common::String &filename) {
return ret;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font.h b/engines/wintermute/base/font/base_font.h
index 50587fa7eb..d75d3f4fb5 100644
--- a/engines/wintermute/base/font/base_font.h
+++ b/engines/wintermute/base/font/base_font.h
@@ -56,6 +56,6 @@ private:
static bool isTrueType(BaseGame *game, const Common::String &filename);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp
index 03bd471636..95f9a83a6a 100644
--- a/engines/wintermute/base/font/base_font_bitmap.cpp
+++ b/engines/wintermute/base/font/base_font_bitmap.cpp
@@ -37,7 +37,6 @@
#include "engines/wintermute/base/base_frame.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/platform_osystem.h"
namespace Wintermute {
@@ -253,7 +252,7 @@ void BaseFontBitmap::drawChar(byte c, int x, int y) {
tileWidth = _widths[c];
}
- BasePlatform::setRect(&rect, col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1)*_tileHeight);
+ rect.setRect(col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1) * _tileHeight);
bool handled = false;
if (_sprite) {
_sprite->getCurrentFrame();
@@ -272,7 +271,7 @@ void BaseFontBitmap::drawChar(byte c, int x, int y) {
//////////////////////////////////////////////////////////////////////
bool BaseFontBitmap::loadFile(const Common::String &filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "BaseFontBitmap::LoadFile failed for file '%s'", filename.c_str());
return STATUS_FAILED;
@@ -311,7 +310,7 @@ TOKEN_DEF(WIDTHS_FRAME)
TOKEN_DEF(PAINT_WHOLE_CELL)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////
-bool BaseFontBitmap::loadBuffer(byte *buffer) {
+bool BaseFontBitmap::loadBuffer(char *buffer) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(FONTEXT_FIX)
TOKEN_TABLE(FONT)
@@ -335,11 +334,11 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) {
int cmd;
BaseParser parser;
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_FONT) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_FONT) {
_gameRef->LOG(0, "'FONT' keyword expected.");
return STATUS_FAILED;
}
- buffer = (byte *)params;
+ buffer = params;
int widths[300];
int num = 0, defaultWidth = 8;
@@ -354,15 +353,15 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) {
int spaceWidth = 0;
int expandWidth = 0;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_IMAGE:
- surfaceFile = (char *)params;
+ surfaceFile = params;
break;
case TOKEN_SPRITE:
- spriteFile = (char *)params;
+ spriteFile = params;
break;
case TOKEN_TRANSPARENT:
@@ -418,7 +417,7 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) {
break;
case TOKEN_EDITOR_PROPERTY:
- parseEditorProperty((byte *)params, false);
+ parseEditorProperty(params, false);
break;
}
@@ -496,13 +495,13 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) {
bool BaseFontBitmap::persist(BasePersistenceManager *persistMgr) {
BaseFont::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_numColumns));
+ persistMgr->transferSint32(TMEMBER(_numColumns));
persistMgr->transferPtr(TMEMBER_PTR(_subframe));
- persistMgr->transfer(TMEMBER(_tileHeight));
- persistMgr->transfer(TMEMBER(_tileWidth));
+ persistMgr->transferSint32(TMEMBER(_tileHeight));
+ persistMgr->transferSint32(TMEMBER(_tileWidth));
persistMgr->transferPtr(TMEMBER_PTR(_sprite));
- persistMgr->transfer(TMEMBER(_widthsFrame));
+ persistMgr->transferSint32(TMEMBER(_widthsFrame));
if (persistMgr->getIsSaving()) {
persistMgr->putBytes(_widths, sizeof(_widths));
@@ -511,8 +510,8 @@ bool BaseFontBitmap::persist(BasePersistenceManager *persistMgr) {
}
- persistMgr->transfer(TMEMBER(_fontextFix));
- persistMgr->transfer(TMEMBER(_wholeCell));
+ persistMgr->transferBool(TMEMBER(_fontextFix));
+ persistMgr->transferBool(TMEMBER(_wholeCell));
return STATUS_OK;
@@ -587,4 +586,4 @@ int BaseFontBitmap::getLetterHeight() {
return _tileHeight;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_bitmap.h b/engines/wintermute/base/font/base_font_bitmap.h
index 0bdac64026..77620d8b88 100644
--- a/engines/wintermute/base/font/base_font_bitmap.h
+++ b/engines/wintermute/base/font/base_font_bitmap.h
@@ -37,7 +37,7 @@ class BaseSubFrame;
class BaseFontBitmap : public BaseFont {
public:
DECLARE_PERSISTENT(BaseFontBitmap, BaseFont)
- bool loadBuffer(byte *Buffer);
+ bool loadBuffer(char *buffer);
bool loadFile(const Common::String &filename);
virtual int getTextWidth(const byte *text, int maxLength = -1) override;
virtual int getTextHeight(const byte *text, int width) override;
@@ -66,6 +66,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp
index 3286742478..8abd368b70 100644
--- a/engines/wintermute/base/font/base_font_storage.cpp
+++ b/engines/wintermute/base/font/base_font_storage.cpp
@@ -138,4 +138,4 @@ bool BaseFontStorage::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_storage.h b/engines/wintermute/base/font/base_font_storage.h
index 60874167e7..f4ac490324 100644
--- a/engines/wintermute/base/font/base_font_storage.h
+++ b/engines/wintermute/base/font/base_font_storage.h
@@ -50,6 +50,6 @@ public:
bool initLoop();
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 2fcdebc117..b879e789e3 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -34,7 +34,6 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/wintermute.h"
#include "graphics/fonts/ttf.h"
#include "graphics/fontman.h"
@@ -122,7 +121,7 @@ int BaseFontTT::getTextWidth(const byte *text, int maxLength) {
}
if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
- textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+ textStr = WideString(textStr.c_str(), (uint32)maxLength);
}
//text = text.substr(0, MaxLength); // TODO: Remove
@@ -156,19 +155,19 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign
return;
}
- WideString textStr = (const char *)text;
+ WideString textStr;
// TODO: Why do we still insist on Widestrings everywhere?
- /* if (_gameRef->_textEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text);
- else text = StringUtil::AnsiToWide((char *)Text);*/
// HACK: J.U.L.I.A. uses CP1252, we need to fix that,
// And we still don't have any UTF8-support.
- if (_gameRef->_textEncoding != TEXT_UTF8) {
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ textStr = StringUtil::utf8ToWide((const char *)text);
+ } else {
textStr = StringUtil::ansiToWide((const char *)text);
}
if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
- textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+ textStr = WideString(textStr.c_str(), (uint32)maxLength);
}
//text = text.substr(0, MaxLength); // TODO: Remove
@@ -227,7 +226,7 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign
// and paint it
if (surface) {
Rect32 rc;
- BasePlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight());
+ rc.setRect(0, 0, surface->getWidth(), surface->getHeight());
for (uint32 i = 0; i < _layers.size(); i++) {
uint32 color = _layers[i]->_color;
uint32 origForceAlpha = renderer->_forceAlphaColor;
@@ -249,7 +248,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
//TextLineList lines;
// TODO: Use WideString-conversion here.
//WrapText(text, width, maxHeight, lines);
- Common::Array<Common::String> lines;
+ Common::Array<WideString> lines;
_font->wordWrapText(text, width, lines);
while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) {
@@ -268,16 +267,17 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
alignment = Graphics::kTextAlignRight;
}
- debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
+ // TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array.
+ //debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
Graphics::Surface *surface = new Graphics::Surface();
if (_deletableFont) { // We actually have a TTF
- surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
} else { // We are using a fallback, they can't do 32bpp
surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
}
uint32 useColor = 0xffffffff;
- Common::Array<Common::String>::iterator it;
+ Common::Array<WideString>::iterator it;
int heightOffset = 0;
for (it = lines.begin(); it != lines.end(); ++it) {
_font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment);
@@ -285,7 +285,27 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
}
BaseSurface *retSurface = _gameRef->_renderer->createSurface();
- Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ Graphics::Surface *convertedSurface = surface->convertTo(_gameRef->_renderer->getPixelFormat());
+
+ if (_deletableFont) {
+ // Reconstruct the alpha channel of the font.
+
+ // Since we painted it with color 0xFFFFFFFF onto a black background,
+ // the alpha channel is gone, but the color value of each pixel corresponds
+ // to its original alpha value.
+
+ Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat();
+ uint32 *pixels = (uint32 *)convertedSurface->getPixels();
+
+ // This is a Surface we created ourselves, so no empty space between rows.
+ for (int i = 0; i < surface->w * surface->h; ++i) {
+ uint8 a, r, g, b;
+ format.colorToRGB(*pixels, r, g, b);
+ a = r;
+ *pixels++ = format.ARGBToColor(a, r, g, b);
+ }
+ }
+
retSurface->putSurface(*convertedSurface, true);
convertedSurface->free();
surface->free();
@@ -304,7 +324,7 @@ int BaseFontTT::getLetterHeight() {
//////////////////////////////////////////////////////////////////////
bool BaseFontTT::loadFile(const Common::String &filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "BaseFontTT::LoadFile failed for file '%s'", filename.c_str());
return STATUS_FAILED;
@@ -341,7 +361,7 @@ TOKEN_DEF(OFFSET_X)
TOKEN_DEF(OFFSET_Y)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////
-bool BaseFontTT::loadBuffer(byte *buffer) {
+bool BaseFontTT::loadBuffer(char *buffer) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(TTFONT)
TOKEN_TABLE(SIZE)
@@ -361,15 +381,15 @@ bool BaseFontTT::loadBuffer(byte *buffer) {
int cmd;
BaseParser parser;
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_TTFONT) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_TTFONT) {
_gameRef->LOG(0, "'TTFONT' keyword expected.");
return STATUS_FAILED;
}
- buffer = (byte *)params;
+ buffer = params;
uint32 baseColor = 0x00000000;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_SIZE:
parser.scanStr(params, "%d", &_fontHeight);
@@ -419,7 +439,7 @@ bool BaseFontTT::loadBuffer(byte *buffer) {
case TOKEN_LAYER: {
BaseTTFontLayer *layer = new BaseTTFontLayer;
- if (layer && DID_SUCCEED(parseLayer(layer, (byte *)params))) {
+ if (layer && DID_SUCCEED(parseLayer(layer, params))) {
_layers.add(layer);
} else {
delete layer;
@@ -452,7 +472,7 @@ bool BaseFontTT::loadBuffer(byte *buffer) {
//////////////////////////////////////////////////////////////////////////
-bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, byte *buffer) {
+bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, char *buffer) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(OFFSET_X)
TOKEN_TABLE(OFFSET_Y)
@@ -464,7 +484,7 @@ bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, byte *buffer) {
int cmd;
BaseParser parser;
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_OFFSET_X:
parser.scanStr(params, "%d", &layer->_offsetX);
@@ -501,25 +521,25 @@ bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, byte *buffer) {
bool BaseFontTT::persist(BasePersistenceManager *persistMgr) {
BaseFont::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_isBold));
- persistMgr->transfer(TMEMBER(_isItalic));
- persistMgr->transfer(TMEMBER(_isUnderline));
- persistMgr->transfer(TMEMBER(_isStriked));
- persistMgr->transfer(TMEMBER(_fontHeight));
- persistMgr->transfer(TMEMBER(_fontFile));
+ persistMgr->transferBool(TMEMBER(_isBold));
+ persistMgr->transferBool(TMEMBER(_isItalic));
+ persistMgr->transferBool(TMEMBER(_isUnderline));
+ persistMgr->transferBool(TMEMBER(_isStriked));
+ persistMgr->transferSint32(TMEMBER(_fontHeight));
+ persistMgr->transferCharPtr(TMEMBER(_fontFile));
// persist layers
int32 numLayers;
if (persistMgr->getIsSaving()) {
numLayers = _layers.size();
- persistMgr->transfer(TMEMBER(numLayers));
+ persistMgr->transferSint32(TMEMBER(numLayers));
for (int i = 0; i < numLayers; i++) {
_layers[i]->persist(persistMgr);
}
} else {
numLayers = _layers.size();
- persistMgr->transfer(TMEMBER(numLayers));
+ persistMgr->transferSint32(TMEMBER(numLayers));
for (int i = 0; i < numLayers; i++) {
BaseTTFontLayer *layer = new BaseTTFontLayer;
layer->persist(persistMgr);
@@ -549,17 +569,26 @@ bool BaseFontTT::initFont() {
return STATUS_FAILED;
}
#ifdef USE_FREETYPE2
+ Common::String fallbackFilename;
+ // Handle Bold atleast for the fallback-case.
+ // TODO: Handle italic. (Needs a test-case)
+ if (_isBold) {
+ fallbackFilename = "FreeSansBold.ttf";
+ } else {
+ fallbackFilename = "FreeSans.ttf";
+ }
+
Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(_fontFile);
if (!file) {
if (Common::String(_fontFile) != "arial.ttf") {
warning("%s has no replacement font yet, using FreeSans for now (if available)", _fontFile);
}
// Fallback1: Try to find FreeSans.ttf
- file = SearchMan.createReadStreamForMember("FreeSans.ttf");
+ file = SearchMan.createReadStreamForMember(fallbackFilename);
}
if (file) {
- _deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72).
+ _deletableFont = Graphics::loadTTFFont(*file, _fontHeight, 96); // Use the same dpi as WME (96 vs 72).
_font = _deletableFont;
BaseFileManager::getEngineInstance()->closeFile(file);
file = nullptr;
@@ -582,9 +611,9 @@ bool BaseFontTT::initFont() {
}
if (themeFile) {
Common::Archive *themeArchive = Common::makeZipArchive(themeFile);
- if (themeArchive->hasFile("FreeSans.ttf")) {
+ if (themeArchive->hasFile(fallbackFilename)) {
file = nullptr;
- file = themeArchive->createReadStreamForMember("FreeSans.ttf");
+ file = themeArchive->createReadStreamForMember(fallbackFilename);
_deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72).
_font = _deletableFont;
}
@@ -599,7 +628,7 @@ bool BaseFontTT::initFont() {
// Fallback3: Try to ask FontMan for the FreeSans.ttf ScummModern.zip uses:
if (!_font) {
// Really not desireable, as we will get a font with dpi-72 then
- Common::String fontName = Common::String::format("%s-%s@%d", "FreeSans.ttf", "ASCII", _fontHeight);
+ Common::String fontName = Common::String::format("%s-%s@%d", fallbackFilename.c_str(), "ASCII", _fontHeight);
warning("Looking for %s", fontName.c_str());
_font = FontMan.getFontByName(fontName);
}
@@ -619,9 +648,9 @@ void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight
//TextLineList lines;
if (maxWidth >= 0) {
- Common::Array<Common::String> lines;
+ Common::Array<WideString> lines;
_font->wordWrapText(text, maxWidth, lines);
- Common::Array<Common::String>::iterator it;
+ Common::Array<WideString>::iterator it;
textWidth = 0;
for (it = lines.begin(); it != lines.end(); ++it) {
textWidth = MAX(textWidth, _font->getStringWidth(*it));
@@ -644,4 +673,4 @@ void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight
}*/
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_truetype.h b/engines/wintermute/base/font/base_font_truetype.h
index f93505921f..edb41a155f 100644
--- a/engines/wintermute/base/font/base_font_truetype.h
+++ b/engines/wintermute/base/font/base_font_truetype.h
@@ -56,9 +56,8 @@ private:
bool _marked;
uint32 _lastUsed;
- BaseCachedTTFontText() {
+ BaseCachedTTFontText() : _text() {
//_text = L"";
- _text = "";
_width = _maxHeight = _maxLength = -1;
_align = TAL_LEFT;
_surface = nullptr;
@@ -84,9 +83,9 @@ public:
}
bool persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_offsetX));
- persistMgr->transfer(TMEMBER(_offsetY));
- persistMgr->transfer(TMEMBER(_color));
+ persistMgr->transferSint32(TMEMBER(_offsetX));
+ persistMgr->transferSint32(TMEMBER(_offsetY));
+ persistMgr->transferUint32(TMEMBER(_color));
return STATUS_OK;
}
@@ -105,7 +104,7 @@ public:
virtual void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1) override;
virtual int getLetterHeight() override;
- bool loadBuffer(byte *buffer);
+ bool loadBuffer(char *buffer);
bool loadFile(const Common::String &filename);
float getLineHeight() const {
@@ -116,7 +115,7 @@ public:
void initLoop();
private:
- bool parseLayer(BaseTTFontLayer *layer, byte *buffer);
+ bool parseLayer(BaseTTFontLayer *layer, char *buffer);
void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight);
@@ -135,7 +134,7 @@ private:
size_t _maxCharWidth;
size_t _maxCharHeight;
-public:
+private:
bool _isBold;
bool _isItalic;
bool _isUnderline;
@@ -148,6 +147,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
index 75de95128f..d0dbae352e 100644
--- a/engines/wintermute/base/gfx/base_image.cpp
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -228,4 +228,4 @@ bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) {
return true;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h
index 017305e5d0..4b04fd1252 100644
--- a/engines/wintermute/base/gfx/base_image.h
+++ b/engines/wintermute/base/gfx/base_image.h
@@ -67,6 +67,6 @@ private:
BaseFileManager *_fileManager;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp
index c20881e425..858a7fc6dc 100644
--- a/engines/wintermute/base/gfx/base_renderer.cpp
+++ b/engines/wintermute/base/gfx/base_renderer.cpp
@@ -65,7 +65,7 @@ BaseRenderer::BaseRenderer(BaseGame *inGame) : BaseClass(inGame) {
_loadImageX = _loadImageY = 0;
_width = _height = _bPP = 0;
- BasePlatform::setRectEmpty(&_monitorRect);
+ _monitorRect.setEmpty();
_realWidth = _realHeight = 0;
_drawOffsetX = _drawOffsetY = 0;
@@ -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;
}
@@ -167,12 +173,12 @@ void BaseRenderer::endSaveLoad() {
}
void BaseRenderer::persistSaveLoadImages(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_loadImageName));
- persistMgr->transfer(TMEMBER(_saveImageName));
- persistMgr->transfer(TMEMBER(_saveImageX));
- persistMgr->transfer(TMEMBER(_saveImageY));
- persistMgr->transfer(TMEMBER(_loadImageX));
- persistMgr->transfer(TMEMBER(_loadImageY));
+ persistMgr->transferString(TMEMBER(_loadImageName));
+ persistMgr->transferString(TMEMBER(_saveImageName));
+ persistMgr->transferSint32(TMEMBER(_saveImageX));
+ persistMgr->transferSint32(TMEMBER(_saveImageY));
+ persistMgr->transferSint32(TMEMBER(_loadImageX));
+ persistMgr->transferSint32(TMEMBER(_loadImageY));
}
//////////////////////////////////////////////////////////////////////
@@ -368,7 +374,7 @@ bool BaseRenderer::displayIndicator() {
}
if (_saveLoadImage && !_hasDrawnSaveLoadImage) {
Rect32 rc;
- BasePlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight());
+ rc.setRect(0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight());
if (_loadInProgress) {
_saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc);
} else {
@@ -395,4 +401,4 @@ bool BaseRenderer::displayIndicator() {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h
index bfef29a5ed..b6615bc8fc 100644
--- a/engines/wintermute/base/gfx/base_renderer.h
+++ b/engines/wintermute/base/gfx/base_renderer.h
@@ -84,7 +84,7 @@ public:
* @param a the alpha component to fade too.
* @param rect the portion of the screen to fade (if nullptr, the entire screen will be faded).
*/
- virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) = 0;
+ virtual void fadeToColor(byte r, byte g, byte b, byte a) = 0;
virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); // Unused outside indicator-display
virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); // Unused outside indicator-display
@@ -228,6 +228,6 @@ private:
BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp
index 2002463ea4..19639c0c33 100644
--- a/engines/wintermute/base/gfx/base_surface.cpp
+++ b/engines/wintermute/base/gfx/base_surface.cpp
@@ -75,8 +75,8 @@ bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) {
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurface::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return displayTransZoom(x, y, rect, zoomX, zoomY, alpha, blendMode, mirrorX, mirrorY);
+bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) {
+ return displayTransform(x, y, rect, newRect, transform);
}
//////////////////////////////////////////////////////////////////////////
@@ -146,4 +146,4 @@ void BaseSurface::setSize(int width, int height) {
_height = height;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h
index b83efa0bb8..a53748e9aa 100644
--- a/engines/wintermute/base/gfx/base_surface.h
+++ b/engines/wintermute/base/gfx/base_surface.h
@@ -32,6 +32,7 @@
#include "engines/wintermute/base/base.h"
#include "engines/wintermute/math/rect32.h"
#include "graphics/surface.h"
+#include "engines/wintermute/graphics/transform_struct.h"
namespace Wintermute {
@@ -53,9 +54,9 @@ public:
virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0;
virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0;
virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
- virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
- virtual bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) = 0;
+ virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) = 0;
virtual bool restore();
virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0;
virtual bool create(int width, int height);
@@ -95,6 +96,6 @@ protected:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index e1424cea87..ff63789d18 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -51,23 +51,19 @@ BaseRenderer *makeOSystemRenderer(BaseGame *inGame) {
BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) {
_renderSurface = new Graphics::Surface();
_blankSurface = new Graphics::Surface();
- _drawNum = 1;
+ _lastFrameIter = _renderQueue.end();
_needsFlip = true;
- _spriteBatch = false;
- _batchNum = 0;
_skipThisFrame = false;
- _previousTicket = nullptr;
_borderLeft = _borderRight = _borderTop = _borderBottom = 0;
_ratioX = _ratioY = 1.0f;
- setAlphaMod(255);
- setColorMod(255, 255, 255);
_dirtyRect = nullptr;
_disableDirtyRects = false;
- _tempDisableDirtyRects = 0;
if (ConfMan.hasKey("dirty_rects")) {
_disableDirtyRects = !ConfMan.getBool("dirty_rects");
}
+
+ _lastScreenChangeID = g_system->getScreenChangeID();
}
//////////////////////////////////////////////////////////////////////////
@@ -85,7 +81,6 @@ BaseRenderOSystem::~BaseRenderOSystem() {
delete _renderSurface;
_blankSurface->free();
delete _blankSurface;
- TransparentSurface::destroyLookup();
}
//////////////////////////////////////////////////////////////////////////
@@ -128,7 +123,7 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
_windowed = !ConfMan.getBool("fullscreen");
- Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
g_system->beginGFXTransaction();
g_system->initSize(_width, _height, &format);
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
@@ -150,18 +145,6 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
return STATUS_OK;
}
-void BaseRenderOSystem::setAlphaMod(byte alpha) {
- byte r = RGBCOLGetR(_colorMod);
- byte g = RGBCOLGetB(_colorMod);
- byte b = RGBCOLGetB(_colorMod);
- _colorMod = BS_ARGB(alpha, r, g, b);
-}
-
-void BaseRenderOSystem::setColorMod(byte r, byte g, byte b) {
- byte alpha = RGBCOLGetA(_colorMod);
- _colorMod = BS_ARGB(alpha, r, g, b);
-}
-
bool BaseRenderOSystem::indicatorFlip() {
g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight);
g_system->updateScreen();
@@ -169,20 +152,24 @@ bool BaseRenderOSystem::indicatorFlip() {
}
bool BaseRenderOSystem::flip() {
- if (_renderQueue.size() > DIRTY_RECT_LIMIT) {
- _tempDisableDirtyRects++;
- }
if (_skipThisFrame) {
_skipThisFrame = false;
delete _dirtyRect;
_dirtyRect = nullptr;
g_system->updateScreen();
_needsFlip = false;
- _drawNum = 1;
+
+ // Reset ticketing state
+ _lastFrameIter = _renderQueue.end();
+ RenderQueueIterator it;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
+ (*it)->_wantsDraw = false;
+ }
+
addDirtyRect(_renderRect);
return true;
}
- if (!_tempDisableDirtyRects && !_disableDirtyRects) {
+ if (!_disableDirtyRects) {
drawTickets();
} else {
// Clear the scale-buffered tickets that wasn't reused.
@@ -198,33 +185,23 @@ bool BaseRenderOSystem::flip() {
}
}
}
- if (_needsFlip || _disableDirtyRects || _tempDisableDirtyRects) {
- if (_disableDirtyRects || _tempDisableDirtyRects) {
- g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+
+ int oldScreenChangeID = _lastScreenChangeID;
+ _lastScreenChangeID = g_system->getScreenChangeID();
+ bool screenChanged = _lastScreenChangeID != oldScreenChangeID;
+
+ if (_needsFlip || _disableDirtyRects || screenChanged) {
+ if (_disableDirtyRects || screenChanged) {
+ g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
}
- // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
+ // g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
delete _dirtyRect;
_dirtyRect = nullptr;
- g_system->updateScreen();
_needsFlip = false;
}
- _drawNum = 1;
-
- if (_tempDisableDirtyRects && !_disableDirtyRects) {
- _tempDisableDirtyRects--;
- if (!_tempDisableDirtyRects) {
- Common::Rect screen(_screenRect.top, _screenRect.left, _screenRect.bottom, _screenRect.right);
- addDirtyRect(screen);
-
- // The queue has been ignored but updated, and is guaranteed to be in draw-order when run without dirty-rects.
- RenderQueueIterator it = _renderQueue.begin();
- int drawNum = 1;
- while (it != _renderQueue.end()) {
- (*it)->_drawNum = drawNum++;
- ++it;
- }
- }
- }
+ _lastFrameIter = _renderQueue.end();
+
+ g_system->updateScreen();
return STATUS_OK;
}
@@ -232,7 +209,7 @@ bool BaseRenderOSystem::flip() {
//////////////////////////////////////////////////////////////////////////
bool BaseRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) {
_clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b);
- if (!_disableDirtyRects && !_tempDisableDirtyRects) {
+ if (!_disableDirtyRects) {
return STATUS_OK;
}
if (!rect) {
@@ -256,37 +233,30 @@ void BaseRenderOSystem::fade(uint16 alpha) {
return fadeToColor(0, 0, 0, dwAlpha);
}
-
//////////////////////////////////////////////////////////////////////////
-void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) {
+void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a) {
Common::Rect fillRect;
- if (rect) {
- fillRect.left = rect->left;
- fillRect.top = rect->top;
- fillRect.setWidth(rect->width());
- fillRect.setHeight(rect->height());
- } else {
- Rect32 rc;
- _gameRef->getCurrentViewportRect(&rc);
- fillRect.left = (int16)rc.left;
- fillRect.top = (int16)rc.top;
- fillRect.setWidth((int16)(rc.right - rc.left));
- fillRect.setHeight((int16)(rc.bottom - rc.top));
- }
+ Rect32 rc;
+ _gameRef->getCurrentViewportRect(&rc);
+ fillRect.left = (int16)rc.left;
+ fillRect.top = (int16)rc.top;
+ fillRect.setWidth((int16)(rc.right - rc.left));
+ fillRect.setHeight((int16)(rc.bottom - rc.top));
+
modTargetRect(&fillRect);
//TODO: This is only here until I'm sure about the final pixelformat
uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b);
- setAlphaMod(255);
- setColorMod(255, 255, 255);
Graphics::Surface surf;
surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format);
Common::Rect sizeRect(fillRect);
sizeRect.translate(-fillRect.top, -fillRect.left);
surf.fillRect(fillRect, col);
- drawSurface(nullptr, &surf, &sizeRect, &fillRect, false, false);
+ TransformStruct temp = TransformStruct();
+ temp._alphaDisable = false;
+ drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp);
surf.free();
//SDL_SetRenderDrawColor(_renderer, r, g, b, a);
@@ -298,21 +268,15 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const {
return _renderSurface->format;
}
-void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) {
- if (_tempDisableDirtyRects || _disableDirtyRects) {
- RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha);
- ticket->_colorMod = _colorMod;
+void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) {
+
+ if (_disableDirtyRects) {
+ RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
ticket->_wantsDraw = true;
_renderQueue.push_back(ticket);
- _previousTicket = ticket;
drawFromSurface(ticket);
return;
}
- // Start searching from the beginning for the first and second items (since it's empty the first time around
- // then keep incrementing the start-position, to avoid comparing against already used tickets.
- if (_drawNum == 0 || _drawNum == 1) {
- _lastAddedTicket = _renderQueue.begin();
- }
// Skip rects that are completely outside the screen:
if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) {
@@ -320,88 +284,35 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S
}
if (owner) { // Fade-tickets are owner-less
- RenderTicket compare(owner, nullptr, srcRect, dstRect, mirrorX, mirrorY, disableAlpha);
- compare._batchNum = _batchNum;
- if (_spriteBatch) {
- _batchNum++;
- }
- compare._colorMod = _colorMod;
- RenderQueueIterator it;
+ RenderTicket compare(owner, nullptr, srcRect, dstRect, transform);
+ RenderQueueIterator it = _lastFrameIter;
+ ++it;
// Avoid calling end() and operator* every time, when potentially going through
// LOTS of tickets.
RenderQueueIterator endIterator = _renderQueue.end();
RenderTicket *compareTicket = nullptr;
- for (it = _lastAddedTicket; it != endIterator; ++it) {
+ for (; it != endIterator; ++it) {
compareTicket = *it;
if (*(compareTicket) == compare && compareTicket->_isValid) {
- compareTicket->_colorMod = _colorMod;
if (_disableDirtyRects) {
drawFromSurface(compareTicket);
} else {
- drawFromTicket(compareTicket);
- _previousTicket = compareTicket;
- }
- if (_renderQueue.size() > DIRTY_RECT_LIMIT) {
- drawTickets();
- _tempDisableDirtyRects = 3;
+ drawFromQueuedTicket(it);
}
return;
}
}
}
- RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha);
- ticket->_colorMod = _colorMod;
+ RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
if (!_disableDirtyRects) {
drawFromTicket(ticket);
- _previousTicket = ticket;
} else {
ticket->_wantsDraw = true;
_renderQueue.push_back(ticket);
- _previousTicket = ticket;
drawFromSurface(ticket);
}
}
-void BaseRenderOSystem::repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY) {
- if (_previousTicket && _lastAddedTicket != _renderQueue.end()) {
- RenderTicket *origTicket = _previousTicket;
-
- // Make sure drawSurface WILL start from the correct _lastAddedTicket
- if (!_tempDisableDirtyRects && !_disableDirtyRects && *_lastAddedTicket != origTicket) {
- RenderQueueIterator it;
- RenderQueueIterator endIterator = _renderQueue.end();
- for (it = _renderQueue.begin(); it != endIterator; ++it) {
- if ((*it) == _previousTicket) {
- _lastAddedTicket = it;
- break;
- }
- }
- }
- Common::Rect srcRect(0, 0, 0, 0);
- srcRect.setWidth(origTicket->getSrcRect()->width());
- srcRect.setHeight(origTicket->getSrcRect()->height());
-
- Common::Rect dstRect = origTicket->_dstRect;
- int initLeft = dstRect.left;
- int initRight = dstRect.right;
-
- for (int i = 0; i < numTimesY; i++) {
- if (i == 0) {
- dstRect.translate(offsetX, 0);
- }
- for (int j = (i == 0 ? 1 : 0); j < numTimesX; j++) {
- drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, false, false);
- dstRect.translate(offsetX, 0);
- }
- dstRect.left = initLeft;
- dstRect.right = initRight;
- dstRect.translate(0, offsetY);
- }
- } else {
- error("Repeat-draw failed (did you forget to draw something before this?)");
- }
-}
-
void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) {
addDirtyRect(renderTicket->_dstRect);
renderTicket->_isValid = false;
@@ -419,59 +330,37 @@ void BaseRenderOSystem::invalidateTicketsFromSurface(BaseSurfaceOSystem *surf) {
void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) {
renderTicket->_wantsDraw = true;
- // A new item always has _drawNum == 0
- if (renderTicket->_drawNum == 0) {
- // In-order
- if (_renderQueue.empty() || _drawNum > (_renderQueue.back())->_drawNum) {
- renderTicket->_drawNum = _drawNum++;
- _renderQueue.push_back(renderTicket);
- addDirtyRect(renderTicket->_dstRect);
- ++_lastAddedTicket;
- } else {
- // Before something
- RenderQueueIterator pos;
- for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) {
- if ((*pos)->_drawNum >= _drawNum) {
- break;
- }
- }
- _renderQueue.insert(pos, renderTicket);
- renderTicket->_drawNum = _drawNum++;
- // Increment the following tickets, so they still are in line
- RenderQueueIterator it;
- for (it = pos; it != _renderQueue.end(); ++it) {
- (*it)->_drawNum++;
- (*it)->_wantsDraw = false;
- }
- addDirtyRect(renderTicket->_dstRect);
- _lastAddedTicket = pos;
- }
+
+ ++_lastFrameIter;
+ // In-order
+ if (_renderQueue.empty() || _lastFrameIter == _renderQueue.end()) {
+ _lastFrameIter--;
+ _renderQueue.push_back(renderTicket);
+ ++_lastFrameIter;
+ addDirtyRect(renderTicket->_dstRect);
} else {
- // Was drawn last round, still in the same order
- if (_drawNum == renderTicket->_drawNum) {
- _drawNum++;
- ++_lastAddedTicket;
- } else {
- // Remove the ticket from the list
- RenderQueueIterator it = _renderQueue.begin();
- while (it != _renderQueue.end()) {
- if ((*it) == renderTicket) {
- it = _renderQueue.erase(it);
- break;
- } else {
- ++it;
- }
- }
- if (it != _renderQueue.end()) {
- // Decreement the following tickets.
- for (; it != _renderQueue.end(); ++it) {
- (*it)->_drawNum--;
- }
- }
- // Is not in order, so readd it as if it was a new ticket
- renderTicket->_drawNum = 0;
- drawFromTicket(renderTicket);
- }
+ // Before something
+ RenderQueueIterator pos = _lastFrameIter;
+ _renderQueue.insert(pos, renderTicket);
+ --_lastFrameIter;
+ addDirtyRect(renderTicket->_dstRect);
+ }
+}
+
+void BaseRenderOSystem::drawFromQueuedTicket(const RenderQueueIterator &ticket) {
+ RenderTicket *renderTicket = *ticket;
+ assert(!renderTicket->_wantsDraw);
+ renderTicket->_wantsDraw = true;
+
+ ++_lastFrameIter;
+ // Not in the same order?
+ if (*_lastFrameIter != renderTicket) {
+ --_lastFrameIter;
+ // Remove the ticket from the list
+ assert(*_lastFrameIter != renderTicket);
+ _renderQueue.erase(ticket);
+ // Is not in order, so readd it as if it was a new ticket
+ drawFromTicket(renderTicket);
}
}
@@ -490,16 +379,13 @@ void BaseRenderOSystem::drawTickets() {
// Note: We draw invalid tickets too, otherwise we wouldn't be honouring
// the draw request they obviously made BEFORE becoming invalid, either way
// we have a copy of their data, so their invalidness won't affect us.
- uint32 decrement = 0;
while (it != _renderQueue.end()) {
if ((*it)->_wantsDraw == false) {
RenderTicket *ticket = *it;
addDirtyRect((*it)->_dstRect);
it = _renderQueue.erase(it);
delete ticket;
- decrement++;
} else {
- (*it)->_drawNum -= decrement;
++it;
}
}
@@ -512,17 +398,12 @@ void BaseRenderOSystem::drawTickets() {
}
return;
}
- // The color-mods are stored in the RenderTickets on add, since we set that state again during
- // draw, we need to keep track of what it was prior to draw.
- uint32 oldColorMod = _colorMod;
// Apply the clear-color to the dirty rect.
_renderSurface->fillRect(*_dirtyRect, _clearColor);
- _drawNum = 1;
+ _lastFrameIter = _renderQueue.end();
for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
RenderTicket *ticket = *it;
- assert(ticket->_drawNum == _drawNum);
- ++_drawNum;
if (ticket->_dstRect.intersects(*_dirtyRect)) {
// dstClip is the area we want redrawn.
Common::Rect dstClip(ticket->_dstRect);
@@ -535,7 +416,6 @@ void BaseRenderOSystem::drawTickets() {
// convert from screen-coords to surface-coords.
dstClip.translate(-offsetX, -offsetY);
- _colorMod = ticket->_colorMod;
drawFromSurface(ticket, &pos, &dstClip);
_needsFlip = true;
}
@@ -544,21 +424,15 @@ void BaseRenderOSystem::drawTickets() {
}
g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
- // Revert the colorMod-state.
- _colorMod = oldColorMod;
-
it = _renderQueue.begin();
// Clean out the old tickets
- decrement = 0;
while (it != _renderQueue.end()) {
if ((*it)->_isValid == false) {
RenderTicket *ticket = *it;
addDirtyRect((*it)->_dstRect);
it = _renderQueue.erase(it);
delete ticket;
- decrement++;
} else {
- (*it)->_drawNum -= decrement;
++it;
}
}
@@ -578,7 +452,7 @@ void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *dstR
bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
// This function isn't used outside of indicator-displaying, and thus quite unused in
// BaseRenderOSystem when dirty-rects are enabled.
- if (!_tempDisableDirtyRects && !_disableDirtyRects && !_indicatorDisplay) {
+ if (!_disableDirtyRects && !_indicatorDisplay) {
error("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet");
}
@@ -625,8 +499,8 @@ bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) {
// TODO: Hopefully this is the same logic that ScummVM uses.
rect.left = (int16)(left + _borderLeft);
rect.top = (int16)(top + _borderTop);
- rect.right = (int16)((right - left) * _ratioX);
- rect.bottom = (int16)((bottom - top) * _ratioY);
+ rect.setWidth((int16)((right - left) * _ratioX));
+ rect.setHeight((int16)((bottom - top) * _ratioY));
_renderRect = rect;
return STATUS_OK;
@@ -643,15 +517,13 @@ Rect32 BaseRenderOSystem::getViewPort() {
//////////////////////////////////////////////////////////////////////////
void BaseRenderOSystem::modTargetRect(Common::Rect *rect) {
- // FIXME: This is wrong in quite a few ways right now, and ends up
- // breaking the notebook in Dirty Split, so we disable the correction
- // for now, this will need fixing when a game with odd aspect-ratios
- // show up.
return;
- rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left);
- rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top);
- rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX));
- rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY));
+ int newWidth = (int16)MathUtil::roundUp(rect->width() * _ratioX);
+ int newHeight = (int16)MathUtil::roundUp(rect->height() * _ratioY);
+ rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft);
+ rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop);
+ rect->setWidth(newWidth);
+ rect->setHeight(newHeight);
}
//////////////////////////////////////////////////////////////////////////
@@ -686,28 +558,22 @@ void BaseRenderOSystem::endSaveLoad() {
it = _renderQueue.erase(it);
delete ticket;
}
- _lastAddedTicket = _renderQueue.begin();
- _previousTicket = nullptr;
// HACK: After a save the buffer will be drawn before the scripts get to update it,
// so just skip this single frame.
_skipThisFrame = true;
- _drawNum = 1;
+ _lastFrameIter = _renderQueue.end();
_renderSurface->fillRect(Common::Rect(0, 0, _renderSurface->h, _renderSurface->w), _renderSurface->format.ARGBToColor(255, 0, 0, 0));
- g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+ g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
g_system->updateScreen();
}
bool BaseRenderOSystem::startSpriteBatch() {
- _spriteBatch = true;
- _batchNum = 1;
return STATUS_OK;
}
bool BaseRenderOSystem::endSpriteBatch() {
- _spriteBatch = false;
- _batchNum = 0;
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
index 3cb0fa82a3..8996c8b2e8 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -33,15 +33,37 @@
#include "common/rect.h"
#include "graphics/surface.h"
#include "common/list.h"
+#include "engines/wintermute/graphics/transform_struct.h"
namespace Wintermute {
class BaseSurfaceOSystem;
class RenderTicket;
+/**
+ * A 2D-renderer implementation for WME.
+ * This renderer makes use of a "ticket"-system, where all draw-calls
+ * are stored as tickets until flip() is called, and compared against the tickets
+ * from last frame, to determine which calls were the same as last round
+ * (i.e. in the exact same order, with the exact same arguments), and thus
+ * figure out which parts of the screen need to be redrawn.
+ *
+ * Important concepts to handle here, is the ordered number of any ticket
+ * which is called the "drawNum", every frame this starts from scratch, and
+ * then the incoming tickets created from the draw-calls are checked to see whether
+ * they came before, on, or after the drawNum they had last frame. Everything else
+ * being equal, this information is then used to check whether the draw order changed,
+ * which will then create a need for redrawing, as we draw with an alpha-channel here.
+ *
+ * There is also a draw path that draws without tickets, for debugging purposes,
+ * as well as to accomodate situations with large enough amounts of draw calls,
+ * that there will be too much overhead involved with comparing the generated tickets.
+ */
class BaseRenderOSystem : public BaseRenderer {
public:
BaseRenderOSystem(BaseGame *inGame);
~BaseRenderOSystem();
+ typedef Common::List<RenderTicket *>::iterator RenderQueueIterator;
+
Common::String getName() const;
bool initRenderer(int width, int height, bool windowed) override;
@@ -50,17 +72,25 @@ public:
bool fill(byte r, byte g, byte b, Common::Rect *rect = nullptr) override;
Graphics::PixelFormat getPixelFormat() const override;
void fade(uint16 alpha) override;
- void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) override;
+ void fadeToColor(byte r, byte g, byte b, byte a) override;
bool drawLine(int x1, int y1, int x2, int y2, uint32 color) override;
BaseImage *takeScreenshot() override;
- void setAlphaMod(byte alpha);
- void setColorMod(byte r, byte g, byte b);
void invalidateTicket(RenderTicket *renderTicket);
void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf);
+ /**
+ * Insert a new ticket into the queue, adding a dirty rect
+ * @param renderTicket the ticket to be added.
+ */
void drawFromTicket(RenderTicket *renderTicket);
+ /**
+ * Re-insert an existing ticket into the queue, adding a dirty rect
+ * out-of-order from last draw from the ticket.
+ * @param ticket iterator pointing to the ticket to be added.
+ */
+ void drawFromQueuedTicket(const RenderQueueIterator &ticket);
bool setViewport(int left, int top, int right, int bottom) override;
bool setViewport(Rect32 *rect) override { return BaseRenderer::setViewport(rect); }
@@ -80,24 +110,27 @@ public:
virtual bool startSpriteBatch() override;
virtual bool endSpriteBatch() override;
void endSaveLoad();
- void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false) ;
- void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY);
+ void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform);
BaseSurface *createSurface() override;
private:
- void addDirtyRect(const Common::Rect &rect) ;
+ /**
+ * Mark a specified rect of the screen as dirty.
+ * @param rect the region to be marked as dirty
+ */
+ void addDirtyRect(const Common::Rect &rect);
+ /**
+ * Traverse the tickets that are dirty, and draw them
+ */
void drawTickets();
// Non-dirty-rects:
void drawFromSurface(RenderTicket *ticket);
// Dirty-rects:
void drawFromSurface(RenderTicket *ticket, Common::Rect *dstRect, Common::Rect *clipRect);
- typedef Common::List<RenderTicket *>::iterator RenderQueueIterator;
Common::Rect *_dirtyRect;
Common::List<RenderTicket *> _renderQueue;
- RenderQueueIterator _lastAddedTicket;
- RenderTicket *_previousTicket;
bool _needsFlip;
- uint32 _drawNum;
+ RenderQueueIterator _lastFrameIter;
Common::Rect _renderRect;
Graphics::Surface *_renderSurface;
Graphics::Surface *_blankSurface;
@@ -108,17 +141,14 @@ private:
int _borderBottom;
bool _disableDirtyRects;
- uint32 _tempDisableDirtyRects;
- bool _spriteBatch;
- uint32 _batchNum;
float _ratioX;
float _ratioY;
- uint32 _colorMod;
uint32 _clearColor;
bool _skipThisFrame;
+ int _lastScreenChangeID; // previous value of OSystem::getScreenChangeID()
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index 0572ef2f6e..9ec8573a87 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -37,6 +37,7 @@
#include "graphics/decoders/jpeg.h"
#include "graphics/decoders/tga.h"
#include "engines/wintermute/graphics/transparent_surface.h"
+#include "engines/wintermute/graphics/transform_tools.h"
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
#include "common/stream.h"
@@ -48,10 +49,11 @@ namespace Wintermute {
BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) {
_surface = new Graphics::Surface();
_alphaMask = nullptr;
- _hasAlpha = true;
+ _alphaType = TransparentSurface::ALPHA_FULL;
_lockPixels = nullptr;
_lockPitch = 0;
_loaded = false;
+ _rotation = 0;
}
//////////////////////////////////////////////////////////////////////////
@@ -70,22 +72,37 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() {
renderer->invalidateTicketsFromSurface(this);
}
-bool hasTransparency(Graphics::Surface *surf) {
+TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) {
if (surf->format.bytesPerPixel != 4) {
- warning("hasTransparency:: non 32 bpp surface passed as argument");
- return false;
+ warning("hasTransparencyType:: non 32 bpp surface passed as argument");
+ return TransparentSurface::ALPHA_OPAQUE;
}
uint8 r, g, b, a;
+ bool seenAlpha = false;
+ bool seenFullAlpha = false;
for (int i = 0; i < surf->h; i++) {
+ if (seenFullAlpha) {
+ break;
+ }
for (int j = 0; j < surf->w; j++) {
- uint32 pix = *(uint32 *)surf->getBasePtr(j, i);
+ uint32 pix = *(const uint32 *)surf->getBasePtr(j, i);
surf->format.colorToARGB(pix, a, r, g, b);
if (a != 255) {
- return true;
+ seenAlpha = true;
+ if (a != 0) {
+ seenFullAlpha = true;
+ break;
+ }
}
}
}
- return false;
+ if (seenFullAlpha) {
+ return TransparentSurface::ALPHA_FULL;
+ } else if (seenAlpha) {
+ return TransparentSurface::ALPHA_BINARY;
+ } else {
+ return TransparentSurface::ALPHA_OPAQUE;
+ }
}
//////////////////////////////////////////////////////////////////////////
@@ -127,49 +144,46 @@ bool BaseSurfaceOSystem::finishLoad() {
_width = image->getSurface()->w;
_height = image->getSurface()->h;
- bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G');
+ bool isSaveGameGrayscale = _filename.matchString("savegame:*g", true);
if (isSaveGameGrayscale) {
warning("grayscaleConversion not yet implemented");
// FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); TODO
}
- // no alpha, set color key
- /* if (surface->format.bytesPerPixel != 4)
- SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue));*/
-
- // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?)
- // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow.
_surface->free();
delete _surface;
bool needsColorKey = false;
bool replaceAlpha = true;
- if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
- _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
- needsColorKey = true;
- replaceAlpha = false;
- } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) {
+ if (image->getSurface()->format.bytesPerPixel == 1) {
+ if (!image->getPalette()) {
+ error("Missing palette while loading 8bit image %s", _filename.c_str());
+ }
_surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
needsColorKey = true;
- } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) {
- _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
- if (image->getSurface()->format.bytesPerPixel == 3) {
- needsColorKey = true;
- }
} else {
- _surface = new Graphics::Surface();
- _surface->copyFrom(*image->getSurface());
- if (_surface->format.aBits() == 0) {
+ if (image->getSurface()->format != g_system->getScreenFormat()) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
+ } else {
+ _surface = new Graphics::Surface();
+ _surface->copyFrom(*image->getSurface());
+ }
+
+ if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
+ // 32 bpp BMPs have nothing useful in their alpha-channel -> color-key
+ needsColorKey = true;
+ replaceAlpha = false;
+ } else if (image->getSurface()->format.aBits() == 0) {
needsColorKey = true;
}
}
-
+
if (needsColorKey) {
TransparentSurface trans(*_surface);
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
}
- _hasAlpha = hasTransparency(_surface);
+ _alphaType = hasTransparencyType(_surface);
_valid = true;
_gameRef->addMem(_width * _height * 4);
@@ -233,7 +247,7 @@ uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y)
warning("BaseSurfaceOSystem::GetPixel - Not ported yet");
int bpp = surface->format.bytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
- uint8 *p = (uint8 *)surface->pixels + y * surface->pitch + x * bpp;
+ uint8 *p = (uint8 *)surface->getBasePtr(x, y);
switch (bpp) {
case 1:
@@ -319,39 +333,64 @@ bool BaseSurfaceOSystem::endPixelOp() {
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return drawSprite(x, y, &rect, 100, 100, 0xFFFFFFFF, true, blendMode, mirrorX, mirrorY);
+ _rotation = 0;
+ return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY);
+ _rotation = 0;
+ return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
- return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY, offsetX, offsetY);
+ _rotation = 0;
+ return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY));
}
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY);
+ _rotation = 0;
+ return drawSprite(x, y, &rect, nullptr, TransformStruct((int32)zoomX, (int32)zoomY, blendMode, alpha, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return drawSprite(x, y, &rect, zoomX, zoomY, alpha, !transparent, blendMode, mirrorX, mirrorY);
+ _rotation = 0;
+ TransformStruct transform;
+ if (transparent) {
+ transform = TransformStruct((int32)zoomX, (int32)zoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY);
+ } else {
+ transform = TransformStruct((int32)zoomX, (int32)zoomY, mirrorX, mirrorY);
+ }
+ return drawSprite(x, y, &rect, nullptr, transform);
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
- return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY);
+bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) {
+ _rotation = (uint32)transform._angle;
+ if (transform._angle < 0.0f) {
+ warning("Negative rotation: %d %d", transform._angle, _rotation);
+ _rotation = (uint32)(360.0f + transform._angle);
+ warning("Negative post rotation: %d %d", transform._angle, _rotation);
+ }
+ return drawSprite(x, y, &rect, &newRect, transform);
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
+bool BaseSurfaceOSystem::displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) {
+ assert(numTimesX > 0 && numTimesY > 0);
+ TransformStruct transform(numTimesX, numTimesY);
+ return drawSprite(x, y, &rect, nullptr, transform);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) {
BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
if (!_loaded) {
@@ -359,24 +398,9 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo
}
if (renderer->_forceAlphaColor != 0) {
- alpha = renderer->_forceAlphaColor;
+ transform._rgbaMod = renderer->_forceAlphaColor;
}
- byte r = RGBCOLGetR(alpha);
- byte g = RGBCOLGetG(alpha);
- byte b = RGBCOLGetB(alpha);
- byte a = RGBCOLGetA(alpha);
-
- renderer->setAlphaMod(a);
- renderer->setColorMod(r, g, b);
-
-#if 0 // These are kept for reference if BlendMode is reimplemented at some point.
- if (alphaDisable) {
- SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE);
- } else {
- SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND);
- }
-#endif
// TODO: This _might_ miss the intended behaviour by 1 in each direction
// But I think it fits the model used in Wintermute.
Common::Rect srcRect;
@@ -386,47 +410,38 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo
srcRect.setHeight(rect->bottom - rect->top);
Common::Rect position;
- position.left = x + offsetX;
- position.top = y + offsetY;
- // Crop off-by-ones:
- if (position.left == -1) {
- position.left = 0; // TODO: Something is wrong
- }
- if (position.top == -1) {
- position.top = 0; // TODO: Something is wrong
- }
+ if (newRect) {
+ position.top = y;
+ position.left = x;
+ position.setWidth(newRect->width());
+ position.setHeight(newRect->height());
+ } else {
- position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f));
- position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f));
+ Rect32 r;
+ r.top = 0;
+ r.left = 0;
+ r.setWidth(rect->width());
+ r.setHeight(rect->height());
- renderer->modTargetRect(&position);
+ r = TransformTools::newRect(r, transform, 0);
- /* position.left += offsetX;
- position.top += offsetY;*/
+ position.top = r.top + y + transform._offset.y;
+ position.left = r.left + x + transform._offset.x;
+ position.setWidth(r.width() * transform._numTimesX);
+ position.setHeight(r.height() * transform._numTimesY);
+ }
+ renderer->modTargetRect(&position);
// TODO: This actually requires us to have the SAME source-offsets every time,
// But no checking is in place for that yet.
- // TODO: Optimize by not doing alpha-blits if we lack or disable alpha
- bool hasAlpha;
- if (_hasAlpha && !alphaDisable) {
- hasAlpha = true;
- } else {
- hasAlpha = false;
- }
- if (alphaDisable) {
- warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored");
+ // Optimize by not doing alpha-blits if we lack alpha
+ if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) {
+ transform._alphaDisable = true;
}
- renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha);
-
- return STATUS_OK;
-}
-
-bool BaseSurfaceOSystem::repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) {
- BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
- renderer->repeatLastDraw(offsetX, offsetY, numTimesX, numTimesY);
+ renderer->drawSurface(this, _surface, &srcRect, &position, transform);
return STATUS_OK;
}
@@ -434,11 +449,15 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl
_loaded = true;
_surface->free();
_surface->copyFrom(surface);
- _hasAlpha = hasAlpha;
+ if (hasAlpha) {
+ _alphaType = TransparentSurface::ALPHA_FULL;
+ } else {
+ _alphaType = TransparentSurface::ALPHA_OPAQUE;
+ }
BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
renderer->invalidateTicketsFromSurface(this);
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
index 9091ec65b1..67f45f66db 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -30,6 +30,7 @@
#define WINTERMUTE_BASE_SURFACESDL_H
#include "graphics/surface.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
#include "engines/wintermute/base/gfx/base_surface.h"
#include "common/list.h"
@@ -51,13 +52,13 @@ public:
bool endPixelOp() override;
- bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override;
+ bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override;
bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) override;
+ bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override;
+ virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY);
virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override;
/* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin);
@@ -81,20 +82,22 @@ public:
return _height;
}
+ TransparentSurface::AlphaType getAlphaType() const { return _alphaType; }
private:
Graphics::Surface *_surface;
bool _loaded;
bool finishLoad();
- bool drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0);
+ bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transformStruct);
void genAlphaMask(Graphics::Surface *surface);
uint32 getPixelAt(Graphics::Surface *surface, int x, int y);
- bool _hasAlpha;
+ uint32 _rotation;
+ TransparentSurface::AlphaType _alphaType;
void *_lockPixels;
int _lockPitch;
byte *_alphaMask;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index 36c5d7b740..1cd35e3b04 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.
@@ -26,22 +26,21 @@
* Copyright (c) 2011 Jan Nedoma
*/
-#include "engines/wintermute/graphics/transparent_surface.h"
+
#include "engines/wintermute/base/gfx/osystem/render_ticket.h"
+#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
+#include "engines/wintermute/graphics/transform_tools.h"
+#include "common/textconsole.h"
namespace Wintermute {
-RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner),
-_srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) {
- _colorMod = 0;
- _batchNum = 0;
- _mirror = TransparentSurface::FLIP_NONE;
- if (mirrorX) {
- _mirror |= TransparentSurface::FLIP_V;
- }
- if (mirrorY) {
- _mirror |= TransparentSurface::FLIP_H;
- }
+RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct transform) :
+ _owner(owner),
+ _srcRect(*srcRect),
+ _dstRect(*dstRect),
+ _isValid(true),
+ _wantsDraw(true),
+ _transform(transform) {
if (surf) {
_surface = new Graphics::Surface();
_surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format);
@@ -51,7 +50,22 @@ _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(
memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel);
}
// Then scale it if necessary
- if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) {
+ //
+ // NB: The numTimesX/numTimesY properties don't yet mix well with
+ // scaling and rotation, but there is no need for that functionality at
+ // the moment.
+ // NB: Mirroring and rotation are probably done in the wrong order.
+ // (Mirroring should most likely be done before rotation. See also
+ // TransformTools.)
+ if (_transform._angle != kDefaultAngle) {
+ TransparentSurface src(*_surface, false);
+ Graphics::Surface *temp = src.rotoscale(transform);
+ _surface->free();
+ delete _surface;
+ _surface = temp;
+ } else if ((dstRect->width() != srcRect->width() ||
+ dstRect->height() != srcRect->height()) &&
+ _transform._numTimesX * _transform._numTimesY == 1) {
TransparentSurface src(*_surface, false);
Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height());
_surface->free();
@@ -70,46 +84,108 @@ RenderTicket::~RenderTicket() {
}
}
-bool RenderTicket::operator==(RenderTicket &t) {
+bool RenderTicket::operator==(const RenderTicket &t) const {
if ((t._owner != _owner) ||
- (t._batchNum != _batchNum) ||
- (t._hasAlpha != _hasAlpha) ||
- (t._mirror != _mirror) ||
- (t._colorMod != _colorMod) ||
+ (t._transform != _transform) ||
(t._dstRect != _dstRect) ||
- (t._srcRect != _srcRect)) {
+ (t._srcRect != _srcRect)
+ ) {
return false;
}
return true;
}
// Replacement for SDL2's SDL_RenderCopy
-void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) {
+void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const {
TransparentSurface src(*getSurface(), false);
Common::Rect clipRect;
clipRect.setWidth(getSurface()->w);
clipRect.setHeight(getSurface()->h);
- src._enableAlphaBlit = _hasAlpha;
- src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _mirror, &clipRect, _colorMod, clipRect.width(), clipRect.height());
+ if (_owner) {
+ if (_transform._alphaDisable) {
+ src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE);
+ } else {
+ src.setAlphaMode(_owner->getAlphaType());
+ }
+ }
+
+ int y = _dstRect.top;
+ int w = _dstRect.width() / _transform._numTimesX;
+ int h = _dstRect.height() / _transform._numTimesY;
+
+ for (int ry = 0; ry < _transform._numTimesY; ++ry) {
+ int x = _dstRect.left;
+ for (int rx = 0; rx < _transform._numTimesX; ++rx) {
+ src.blit(*_targetSurface, x, y, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height());
+ x += w;
+ }
+ y += h;
+ }
}
-void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) {
+void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const {
TransparentSurface src(*getSurface(), false);
bool doDelete = false;
if (!clipRect) {
doDelete = true;
clipRect = new Common::Rect();
- clipRect->setWidth(getSurface()->w);
- clipRect->setHeight(getSurface()->h);
+ clipRect->setWidth(getSurface()->w * _transform._numTimesX);
+ clipRect->setHeight(getSurface()->h * _transform._numTimesY);
+ }
+
+ if (_owner) {
+ if (_transform._alphaDisable) {
+ src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE);
+ } else {
+ src.setAlphaMode(_owner->getAlphaType());
+ }
+ }
+
+ if (_transform._numTimesX * _transform._numTimesY == 1) {
+
+ src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode);
+
+ } else {
+
+ // clipRect is a subrect of the full numTimesX*numTimesY rect
+ Common::Rect subRect;
+
+ int y = 0;
+ int w = getSurface()->w;
+ int h = getSurface()->h;
+ assert(w == _dstRect.width() / _transform._numTimesX);
+ assert(h == _dstRect.height() / _transform._numTimesY);
+
+ int basex = dstRect->left - clipRect->left;
+ int basey = dstRect->top - clipRect->top;
+
+ for (int ry = 0; ry < _transform._numTimesY; ++ry) {
+ int x = 0;
+ for (int rx = 0; rx < _transform._numTimesX; ++rx) {
+
+ subRect.left = x;
+ subRect.top = y;
+ subRect.setWidth(w);
+ subRect.setHeight(h);
+
+ if (subRect.intersects(*clipRect)) {
+ subRect.clip(*clipRect);
+ subRect.translate(-x, -y);
+ src.blit(*_targetSurface, basex + x + subRect.left, basey + y + subRect.top, _transform._flip, &subRect, _transform._rgbaMod, subRect.width(), subRect.height(), _transform._blendMode);
+
+ }
+
+ x += w;
+ }
+ y += h;
+ }
}
- src._enableAlphaBlit = _hasAlpha;
- src.blit(*_targetSurface, dstRect->left, dstRect->top, _mirror, clipRect, _colorMod, clipRect->width(), clipRect->height());
if (doDelete) {
delete clipRect;
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h
index 968b42b5e1..e824c09fe7 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.
@@ -29,41 +29,52 @@
#ifndef WINTERMUTE_RENDER_TICKET_H
#define WINTERMUTE_RENDER_TICKET_H
+#include "engines/wintermute/graphics/transparent_surface.h"
#include "graphics/surface.h"
#include "common/rect.h"
namespace Wintermute {
class BaseSurfaceOSystem;
+/**
+ * A single RenderTicket.
+ * A render ticket is a collection of the data and draw specifications made
+ * for a single draw-call in the OSystem-backend for WME. The ticket additionally
+ * holds the order in which this call was made, so that it can be detected if
+ * the same call is done in the following frame. Thus allowing us to potentially
+ * skip drawing the same region again, unless anything has changed. Since a surface
+ * can have a potentially large amount of draw-calls made to it, at varying rotation,
+ * zoom, and crop-levels we also need to hold a copy of the necessary data.
+ * (Video-surfaces may even change their data). The promise that is made when a ticket
+ * is created is that what the state was of the surface at THAT point, is what will end
+ * up on screen at flip() time.
+ */
class RenderTicket {
public:
- RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false);
- RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {}
+ RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform);
+ RenderTicket() : _isValid(true), _wantsDraw(false), _transform(TransformStruct()) {}
~RenderTicket();
- const Graphics::Surface *getSurface() { return _surface; }
+ const Graphics::Surface *getSurface() const { return _surface; }
// Non-dirty-rects:
- void drawToSurface(Graphics::Surface *_targetSurface);
+ void drawToSurface(Graphics::Surface *_targetSurface) const;
// Dirty-rects:
- void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect);
+ void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const;
Common::Rect _dstRect;
- uint32 _batchNum;
bool _isValid;
bool _wantsDraw;
- uint32 _drawNum;
- uint32 _colorMod;
+ TransformStruct _transform;
+
BaseSurfaceOSystem *_owner;
- bool operator==(RenderTicket &a);
- const Common::Rect *getSrcRect() { return &_srcRect; }
+ bool operator==(const RenderTicket &a) const;
+ const Common::Rect *getSrcRect() const { return &_srcRect; }
private:
Graphics::Surface *_surface;
Common::Rect _srcRect;
- bool _hasAlpha;
- uint32 _mirror;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
index c86e1ce369..061352b60f 100644
--- a/engines/wintermute/base/particles/part_emitter.cpp
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -38,7 +38,6 @@
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
#include "common/math.h"
@@ -50,7 +49,7 @@ IMPLEMENT_PERSISTENT(PartEmitter, false)
PartEmitter::PartEmitter(BaseGame *inGame, BaseScriptHolder *owner) : BaseObject(inGame) {
_width = _height = 0;
- BasePlatform::setRectEmpty(&_border);
+ _border.setEmpty();
_borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0;
_angle1 = _angle2 = 0;
@@ -198,7 +197,7 @@ bool PartEmitter::initParticle(PartParticle *particle, uint32 currentTime, uint3
float angVelocity = BaseUtils::randomFloat(_angVelocity1, _angVelocity2);
float growthRate = BaseUtils::randomFloat(_growthRate1, _growthRate2);
- if (!BasePlatform::isRectEmpty(&_border)) {
+ if (!_border.isRectEmpty()) {
int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f);
int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f);
int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f);
@@ -386,7 +385,7 @@ bool PartEmitter::compareZ(const PartParticle *p1, const PartParticle *p2) {
//////////////////////////////////////////////////////////////////////////
bool PartEmitter::setBorder(int x, int y, int width, int height) {
- BasePlatform::setRect(&_border, x, y, x + width, y + height);
+ _border.setRect(x, y, x + width, y + height);
return STATUS_OK;
}
@@ -1157,61 +1156,61 @@ const char *PartEmitter::scToString() {
bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_width));
- persistMgr->transfer(TMEMBER(_height));
+ persistMgr->transferSint32(TMEMBER(_width));
+ persistMgr->transferSint32(TMEMBER(_height));
- persistMgr->transfer(TMEMBER(_angle1));
- persistMgr->transfer(TMEMBER(_angle2));
+ persistMgr->transferSint32(TMEMBER(_angle1));
+ persistMgr->transferSint32(TMEMBER(_angle2));
- persistMgr->transfer(TMEMBER(_velocity1));
- persistMgr->transfer(TMEMBER(_velocity2));
- persistMgr->transfer(TMEMBER(_velocityZBased));
+ persistMgr->transferFloat(TMEMBER(_velocity1));
+ persistMgr->transferFloat(TMEMBER(_velocity2));
+ persistMgr->transferBool(TMEMBER(_velocityZBased));
- persistMgr->transfer(TMEMBER(_scale1));
- persistMgr->transfer(TMEMBER(_scale2));
- persistMgr->transfer(TMEMBER(_scaleZBased));
+ persistMgr->transferFloat(TMEMBER(_scale1));
+ persistMgr->transferFloat(TMEMBER(_scale2));
+ persistMgr->transferBool(TMEMBER(_scaleZBased));
- persistMgr->transfer(TMEMBER(_maxParticles));
+ persistMgr->transferSint32(TMEMBER(_maxParticles));
- persistMgr->transfer(TMEMBER(_lifeTime1));
- persistMgr->transfer(TMEMBER(_lifeTime2));
- persistMgr->transfer(TMEMBER(_lifeTimeZBased));
+ persistMgr->transferSint32(TMEMBER(_lifeTime1));
+ persistMgr->transferSint32(TMEMBER(_lifeTime2));
+ persistMgr->transferBool(TMEMBER(_lifeTimeZBased));
- persistMgr->transfer(TMEMBER(_genInterval));
- persistMgr->transfer(TMEMBER(_genAmount));
+ persistMgr->transferSint32(TMEMBER(_genInterval));
+ persistMgr->transferSint32(TMEMBER(_genAmount));
- persistMgr->transfer(TMEMBER(_running));
- persistMgr->transfer(TMEMBER(_overheadTime));
+ persistMgr->transferBool(TMEMBER(_running));
+ persistMgr->transferSint32(TMEMBER(_overheadTime));
- persistMgr->transfer(TMEMBER(_border));
- persistMgr->transfer(TMEMBER(_borderThicknessLeft));
- persistMgr->transfer(TMEMBER(_borderThicknessRight));
- persistMgr->transfer(TMEMBER(_borderThicknessTop));
- persistMgr->transfer(TMEMBER(_borderThicknessBottom));
+ persistMgr->transferRect32(TMEMBER(_border));
+ persistMgr->transferSint32(TMEMBER(_borderThicknessLeft));
+ persistMgr->transferSint32(TMEMBER(_borderThicknessRight));
+ persistMgr->transferSint32(TMEMBER(_borderThicknessTop));
+ persistMgr->transferSint32(TMEMBER(_borderThicknessBottom));
- persistMgr->transfer(TMEMBER(_fadeInTime));
- persistMgr->transfer(TMEMBER(_fadeOutTime));
+ persistMgr->transferSint32(TMEMBER(_fadeInTime));
+ persistMgr->transferSint32(TMEMBER(_fadeOutTime));
- persistMgr->transfer(TMEMBER(_alpha1));
- persistMgr->transfer(TMEMBER(_alpha2));
- persistMgr->transfer(TMEMBER(_alphaTimeBased));
+ persistMgr->transferSint32(TMEMBER(_alpha1));
+ persistMgr->transferSint32(TMEMBER(_alpha2));
+ persistMgr->transferBool(TMEMBER(_alphaTimeBased));
- persistMgr->transfer(TMEMBER(_angVelocity1));
- persistMgr->transfer(TMEMBER(_angVelocity2));
+ persistMgr->transferFloat(TMEMBER(_angVelocity1));
+ persistMgr->transferFloat(TMEMBER(_angVelocity2));
- persistMgr->transfer(TMEMBER(_rotation1));
- persistMgr->transfer(TMEMBER(_rotation2));
+ persistMgr->transferFloat(TMEMBER(_rotation1));
+ persistMgr->transferFloat(TMEMBER(_rotation2));
- persistMgr->transfer(TMEMBER(_growthRate1));
- persistMgr->transfer(TMEMBER(_growthRate2));
- persistMgr->transfer(TMEMBER(_exponentialGrowth));
+ persistMgr->transferFloat(TMEMBER(_growthRate1));
+ persistMgr->transferFloat(TMEMBER(_growthRate2));
+ persistMgr->transferBool(TMEMBER(_exponentialGrowth));
- persistMgr->transfer(TMEMBER(_useRegion));
+ persistMgr->transferBool(TMEMBER(_useRegion));
- persistMgr->transfer(TMEMBER_INT(_maxBatches));
- persistMgr->transfer(TMEMBER_INT(_batchesGenerated));
+ persistMgr->transferSint32(TMEMBER_INT(_maxBatches));
+ persistMgr->transferSint32(TMEMBER_INT(_batchesGenerated));
- persistMgr->transfer(TMEMBER(_emitEvent));
+ persistMgr->transferCharPtr(TMEMBER(_emitEvent));
persistMgr->transferPtr(TMEMBER_PTR(_owner));
@@ -1220,12 +1219,12 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
uint32 numForces;
if (persistMgr->getIsSaving()) {
numForces = _forces.size();
- persistMgr->transfer(TMEMBER(numForces));
+ persistMgr->transferUint32(TMEMBER(numForces));
for (uint32 i = 0; i < _forces.size(); i++) {
_forces[i]->persist(persistMgr);
}
} else {
- persistMgr->transfer(TMEMBER(numForces));
+ persistMgr->transferUint32(TMEMBER(numForces));
for (uint32 i = 0; i < numForces; i++) {
PartForce *force = new PartForce(_gameRef);
force->persist(persistMgr);
@@ -1236,12 +1235,12 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
uint32 numParticles;
if (persistMgr->getIsSaving()) {
numParticles = _particles.size();
- persistMgr->transfer(TMEMBER(numParticles));
+ persistMgr->transferUint32(TMEMBER(numParticles));
for (uint32 i = 0; i < _particles.size(); i++) {
_particles[i]->persist(persistMgr);
}
} else {
- persistMgr->transfer(TMEMBER(numParticles));
+ persistMgr->transferUint32(TMEMBER(numParticles));
for (uint32 i = 0; i < numParticles; i++) {
PartParticle *particle = new PartParticle(_gameRef);
particle->persist(persistMgr);
@@ -1252,4 +1251,4 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h
index a0d701f338..94b4dc8126 100644
--- a/engines/wintermute/base/particles/part_emitter.h
+++ b/engines/wintermute/base/particles/part_emitter.h
@@ -135,6 +135,6 @@ private:
BaseArray<char *> _sprites;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/particles/part_force.cpp b/engines/wintermute/base/particles/part_force.cpp
index df84162504..39d98c182e 100644
--- a/engines/wintermute/base/particles/part_force.cpp
+++ b/engines/wintermute/base/particles/part_force.cpp
@@ -49,17 +49,17 @@ PartForce::~PartForce(void) {
bool PartForce::persist(BasePersistenceManager *persistMgr) {
if (persistMgr->getIsSaving()) {
const char *name = getName();
- persistMgr->transfer(TMEMBER(name));
+ persistMgr->transferConstChar(TMEMBER(name));
} else {
const char *name;
- persistMgr->transfer(TMEMBER(name));
+ persistMgr->transferConstChar(TMEMBER(name));
setName(name);
}
- persistMgr->transfer(TMEMBER(_pos));
- persistMgr->transfer(TMEMBER(_direction));
- persistMgr->transfer(TMEMBER_INT(_type));
+ persistMgr->transferVector2(TMEMBER(_pos));
+ persistMgr->transferVector2(TMEMBER(_direction));
+ persistMgr->transferSint32(TMEMBER_INT(_type));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_force.h b/engines/wintermute/base/particles/part_force.h
index 27f4cb7d90..cdb1ce40f9 100644
--- a/engines/wintermute/base/particles/part_force.h
+++ b/engines/wintermute/base/particles/part_force.h
@@ -52,6 +52,6 @@ public:
bool persist(BasePersistenceManager *PersistMgr);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp
index f1aba114de..11470561f0 100644
--- a/engines/wintermute/base/particles/part_particle.cpp
+++ b/engines/wintermute/base/particles/part_particle.cpp
@@ -45,7 +45,7 @@ PartParticle::PartParticle(BaseGame *inGame) : BaseClass(inGame) {
_creationTime = 0;
_lifeTime = 0;
_isDead = true;
- BasePlatform::setRectEmpty(&_border);
+ _border.setEmpty();
_state = PARTICLE_NORMAL;
_fadeStart = 0;
@@ -125,7 +125,7 @@ bool PartParticle::update(PartEmitter *emitter, uint32 currentTime, uint32 timer
}
// particle hit the border
- if (!_isDead && !BasePlatform::isRectEmpty(&_border)) {
+ if (!_isDead && !_border.isRectEmpty()) {
Point32 p;
p.x = (int32)_pos.x;
p.y = (int32)_pos.y;
@@ -230,32 +230,32 @@ bool PartParticle::fadeOut(uint32 currentTime, int fadeTime) {
//////////////////////////////////////////////////////////////////////////
bool PartParticle::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_alpha1));
- persistMgr->transfer(TMEMBER(_alpha2));
- persistMgr->transfer(TMEMBER(_border));
- persistMgr->transfer(TMEMBER(_pos));
- persistMgr->transfer(TMEMBER(_posZ));
- persistMgr->transfer(TMEMBER(_velocity));
- persistMgr->transfer(TMEMBER(_scale));
- persistMgr->transfer(TMEMBER(_creationTime));
- persistMgr->transfer(TMEMBER(_lifeTime));
- persistMgr->transfer(TMEMBER(_isDead));
- persistMgr->transfer(TMEMBER_INT(_state));
- persistMgr->transfer(TMEMBER(_fadeStart));
- persistMgr->transfer(TMEMBER(_fadeTime));
- persistMgr->transfer(TMEMBER(_currentAlpha));
- persistMgr->transfer(TMEMBER(_angVelocity));
- persistMgr->transfer(TMEMBER(_rotation));
- persistMgr->transfer(TMEMBER(_growthRate));
- persistMgr->transfer(TMEMBER(_exponentialGrowth));
- persistMgr->transfer(TMEMBER(_fadeStartAlpha));
+ persistMgr->transferSint32(TMEMBER(_alpha1));
+ persistMgr->transferSint32(TMEMBER(_alpha2));
+ persistMgr->transferRect32(TMEMBER(_border));
+ persistMgr->transferVector2(TMEMBER(_pos));
+ persistMgr->transferFloat(TMEMBER(_posZ));
+ persistMgr->transferVector2(TMEMBER(_velocity));
+ persistMgr->transferFloat(TMEMBER(_scale));
+ persistMgr->transferUint32(TMEMBER(_creationTime));
+ persistMgr->transferSint32(TMEMBER(_lifeTime));
+ persistMgr->transferBool(TMEMBER(_isDead));
+ persistMgr->transferSint32(TMEMBER_INT(_state));
+ persistMgr->transferUint32(TMEMBER(_fadeStart));
+ persistMgr->transferSint32(TMEMBER(_fadeTime));
+ persistMgr->transferSint32(TMEMBER(_currentAlpha));
+ persistMgr->transferFloat(TMEMBER(_angVelocity));
+ persistMgr->transferFloat(TMEMBER(_rotation));
+ persistMgr->transferFloat(TMEMBER(_growthRate));
+ persistMgr->transferBool(TMEMBER(_exponentialGrowth));
+ persistMgr->transferSint32(TMEMBER(_fadeStartAlpha));
if (persistMgr->getIsSaving()) {
const char *filename = _sprite->getFilename();
- persistMgr->transfer(TMEMBER(filename));
+ persistMgr->transferConstChar(TMEMBER(filename));
} else {
char *filename;
- persistMgr->transfer(TMEMBER(filename));
+ persistMgr->transferCharPtr(TMEMBER(filename));
SystemClassRegistry::getInstance()->_disabled = true;
setSprite(filename);
SystemClassRegistry::getInstance()->_disabled = false;
@@ -266,4 +266,4 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_particle.h b/engines/wintermute/base/particles/part_particle.h
index 8cca6b4057..281d87cf72 100644
--- a/engines/wintermute/base/particles/part_particle.h
+++ b/engines/wintermute/base/particles/part_particle.h
@@ -85,6 +85,6 @@ private:
int32 _fadeStartAlpha;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/save_thumb_helper.cpp b/engines/wintermute/base/save_thumb_helper.cpp
index bab29c5cf8..77514849a6 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;
@@ -107,4 +107,4 @@ bool SaveThumbHelper::storeScummVMThumbNail(bool doFlip) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/save_thumb_helper.h b/engines/wintermute/base/save_thumb_helper.h
index d3bc5f5523..44792e3d75 100644
--- a/engines/wintermute/base/save_thumb_helper.h
+++ b/engines/wintermute/base/save_thumb_helper.h
@@ -47,6 +47,6 @@ private:
BaseGame *_gameRef;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp
index 1b7dfd42ed..8d37909bb4 100644
--- a/engines/wintermute/base/saveload.cpp
+++ b/engines/wintermute/base/saveload.cpp
@@ -201,4 +201,4 @@ bool SaveLoad::emptySaveSlot(int slot) {
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/saveload.h b/engines/wintermute/base/saveload.h
index 722f7a89b6..15d4d86b26 100644
--- a/engines/wintermute/base/saveload.h
+++ b/engines/wintermute/base/saveload.h
@@ -52,6 +52,6 @@ private:
static void afterLoadScript(void *script, void *data);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/dcscript.h b/engines/wintermute/base/scriptables/dcscript.h
index 4aae897dc2..d6bb3cd176 100644
--- a/engines/wintermute/base/scriptables/dcscript.h
+++ b/engines/wintermute/base/scriptables/dcscript.h
@@ -136,6 +136,6 @@ typedef enum {
ELEMENT_STRING = 0
} TElementType;
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
index 1b945c2e1c..5e4ae3ea95 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;
}
@@ -1248,15 +1249,15 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) {
// buffer
if (persistMgr->getIsSaving()) {
if (_state != SCRIPT_PERSISTENT && _state != SCRIPT_FINISHED && _state != SCRIPT_THREAD_FINISHED) {
- persistMgr->transfer(TMEMBER(_bufferSize));
+ persistMgr->transferUint32(TMEMBER(_bufferSize));
persistMgr->putBytes(_buffer, _bufferSize);
} else {
// don't save idle/finished scripts
int32 bufferSize = 0;
- persistMgr->transfer(TMEMBER(bufferSize));
+ persistMgr->transferSint32(TMEMBER(bufferSize));
}
} else {
- persistMgr->transfer(TMEMBER(_bufferSize));
+ persistMgr->transferUint32(TMEMBER(_bufferSize));
if (_bufferSize > 0) {
_buffer = new byte[_bufferSize];
persistMgr->getBytes(_buffer, _bufferSize);
@@ -1269,31 +1270,31 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) {
}
persistMgr->transferPtr(TMEMBER_PTR(_callStack));
- persistMgr->transfer(TMEMBER(_currentLine));
+ persistMgr->transferSint32(TMEMBER(_currentLine));
persistMgr->transferPtr(TMEMBER_PTR(_engine));
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_freezable));
+ persistMgr->transferCharPtr(TMEMBER(_filename));
+ persistMgr->transferBool(TMEMBER(_freezable));
persistMgr->transferPtr(TMEMBER_PTR(_globals));
- persistMgr->transfer(TMEMBER(_iP));
+ persistMgr->transferUint32(TMEMBER(_iP));
persistMgr->transferPtr(TMEMBER_PTR(_scopeStack));
persistMgr->transferPtr(TMEMBER_PTR(_stack));
- persistMgr->transfer(TMEMBER_INT(_state));
+ persistMgr->transferSint32(TMEMBER_INT(_state));
persistMgr->transferPtr(TMEMBER_PTR(_operand));
- persistMgr->transfer(TMEMBER_INT(_origState));
+ persistMgr->transferSint32(TMEMBER_INT(_origState));
persistMgr->transferPtr(TMEMBER_PTR(_owner));
persistMgr->transferPtr(TMEMBER_PTR(_reg1));
- persistMgr->transfer(TMEMBER(_thread));
- persistMgr->transfer(TMEMBER(_threadEvent));
+ persistMgr->transferBool(TMEMBER(_thread));
+ persistMgr->transferCharPtr(TMEMBER(_threadEvent));
persistMgr->transferPtr(TMEMBER_PTR(_thisStack));
- persistMgr->transfer(TMEMBER(_timeSlice));
+ persistMgr->transferUint32(TMEMBER(_timeSlice));
persistMgr->transferPtr(TMEMBER_PTR(_waitObject));
persistMgr->transferPtr(TMEMBER_PTR(_waitScript));
- persistMgr->transfer(TMEMBER(_waitTime));
- persistMgr->transfer(TMEMBER(_waitFrozen));
+ persistMgr->transferUint32(TMEMBER(_waitTime));
+ persistMgr->transferBool(TMEMBER(_waitFrozen));
- persistMgr->transfer(TMEMBER(_methodThread));
- persistMgr->transfer(TMEMBER(_methodThread));
- persistMgr->transfer(TMEMBER(_unbreakable));
+ persistMgr->transferBool(TMEMBER(_methodThread));
+ persistMgr->transferBool(TMEMBER(_methodThread)); // TODO-SAVE: Deduplicate.
+ persistMgr->transferBool(TMEMBER(_unbreakable));
persistMgr->transferPtr(TMEMBER_PTR(_parentScript));
if (!persistMgr->getIsSaving()) {
@@ -1464,4 +1465,4 @@ void ScScript::afterLoad() {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h
index ee9f45e204..488ff63606 100644
--- a/engines/wintermute/base/scriptables/script.h
+++ b/engines/wintermute/base/scriptables/script.h
@@ -169,6 +169,6 @@ public:
virtual const char *dbgGetFilename();
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp
index f83fb36843..bb819b23e4 100644
--- a/engines/wintermute/base/scriptables/script_engine.cpp
+++ b/engines/wintermute/base/scriptables/script_engine.cpp
@@ -362,6 +362,8 @@ bool ScEngine::tick() {
//////////////////////////////////////////////////////////////////////////
bool ScEngine::tickUnbreakable() {
+ ScScript *oldScript = _currentScript;
+
// execute unbreakable scripts
for (uint32 i = 0; i < _scripts.size(); i++) {
if (!_scripts[i]->_unbreakable) {
@@ -373,9 +375,12 @@ bool ScEngine::tickUnbreakable() {
_scripts[i]->executeInstruction();
}
_scripts[i]->finish();
- _currentScript = nullptr;
+ _currentScript = oldScript;
}
- removeFinishedScripts();
+
+ // NB: Don't remove finished scripts here since we could be recursively
+ // executing scripts. Doing so could invalidate the outer iteration in
+ // ::tick() over _scripts.
return STATUS_OK;
}
@@ -605,4 +610,4 @@ void ScEngine::dumpStats() {
}*/
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_engine.h b/engines/wintermute/base/scriptables/script_engine.h
index 639875ffb6..622b3c4b94 100644
--- a/engines/wintermute/base/scriptables/script_engine.h
+++ b/engines/wintermute/base/scriptables/script_engine.h
@@ -130,6 +130,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp
index a466d361ec..c4ad045557 100644
--- a/engines/wintermute/base/scriptables/script_ext_array.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_array.cpp
@@ -214,7 +214,7 @@ bool SXArray::scSetProperty(const char *name, ScValue *value) {
bool SXArray::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_length));
+ persistMgr->transferSint32(TMEMBER(_length));
persistMgr->transferPtr(TMEMBER_PTR(_values));
return STATUS_OK;
@@ -249,4 +249,4 @@ bool SXArray::push(ScValue *val) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h
index 68f808641e..e6381a011e 100644
--- a/engines/wintermute/base/scriptables/script_ext_array.h
+++ b/engines/wintermute/base/scriptables/script_ext_array.h
@@ -51,6 +51,6 @@ private:
Common::String _strRep;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp
index afca0c4bbf..6b9c5ff68a 100644
--- a/engines/wintermute/base/scriptables/script_ext_date.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_date.cpp
@@ -243,15 +243,15 @@ bool SXDate::persist(BasePersistenceManager *persistMgr) {
int32 hour = _tm.tm_hour;
int32 min = _tm.tm_min;
int32 sec = _tm.tm_sec;
- persistMgr->transfer(TMEMBER(year));
- persistMgr->transfer(TMEMBER(mon));
- persistMgr->transfer(TMEMBER(mday));
- persistMgr->transfer(TMEMBER(hour));
- persistMgr->transfer(TMEMBER(min));
- persistMgr->transfer(TMEMBER(sec));
+ persistMgr->transferSint32(TMEMBER(year));
+ persistMgr->transferSint32(TMEMBER(mon));
+ persistMgr->transferSint32(TMEMBER(mday));
+ persistMgr->transferSint32(TMEMBER(hour));
+ persistMgr->transferSint32(TMEMBER(min));
+ persistMgr->transferSint32(TMEMBER(sec));
if (persistMgr->checkVersion(1, 2, 1)) {
int32 wday = _tm.tm_wday;
- persistMgr->transfer(TMEMBER(wday));
+ persistMgr->transferSint32(TMEMBER(wday));
_tm.tm_wday = wday;
}
_tm.tm_year = year;
@@ -307,4 +307,4 @@ int SXDate::scCompare(BaseScriptable *Value) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h
index 062b7c55c7..0ccf093a7b 100644
--- a/engines/wintermute/base/scriptables/script_ext_date.h
+++ b/engines/wintermute/base/scriptables/script_ext_date.h
@@ -49,6 +49,6 @@ private:
Common::String _strRep;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp
index 29e032a759..dcd4f01f7c 100644
--- a/engines/wintermute/base/scriptables/script_ext_file.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_file.cpp
@@ -766,16 +766,16 @@ bool SXFile::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_mode));
- persistMgr->transfer(TMEMBER(_textMode));
+ persistMgr->transferCharPtr(TMEMBER(_filename));
+ persistMgr->transferSint32(TMEMBER(_mode));
+ persistMgr->transferBool(TMEMBER(_textMode));
uint32 pos = 0;
if (persistMgr->getIsSaving()) {
pos = getPos();
- persistMgr->transfer(TMEMBER(pos));
+ persistMgr->transferUint32(TMEMBER(pos));
} else {
- persistMgr->transfer(TMEMBER(pos));
+ persistMgr->transferUint32(TMEMBER(pos));
// try to re-open file if needed
_writeFile = nullptr;
@@ -825,4 +825,4 @@ Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool
error("SXFile::openForAppend - WriteFiles not supported");
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h
index fa2384109f..a1298929f2 100644
--- a/engines/wintermute/base/scriptables/script_ext_file.h
+++ b/engines/wintermute/base/scriptables/script_ext_file.h
@@ -61,6 +61,6 @@ private:
Common::WriteStream *openForAppend(const Common::String &filename, bool binary);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp
index d816fbec65..ec53b983e7 100644
--- a/engines/wintermute/base/scriptables/script_ext_math.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_math.cpp
@@ -31,7 +31,6 @@
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/persistent.h"
#include "common/math.h"
-#include <math.h>
namespace Wintermute {
@@ -292,4 +291,4 @@ bool SXMath::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h
index 48c43ea7e8..1aa274a96f 100644
--- a/engines/wintermute/base/scriptables/script_ext_math.h
+++ b/engines/wintermute/base/scriptables/script_ext_math.h
@@ -48,6 +48,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
index 9de9905fea..39f8b58644 100644
--- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
@@ -498,7 +498,7 @@ bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_size));
+ persistMgr->transferSint32(TMEMBER(_size));
if (persistMgr->getIsSaving()) {
if (_size > 0) {
@@ -526,4 +526,4 @@ int SXMemBuffer::scCompare(BaseScriptable *val) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
index 6700a03f50..4aad8b6484 100644
--- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
@@ -55,6 +55,6 @@ private:
bool checkBounds(ScScript *script, int start, int length);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_object.cpp b/engines/wintermute/base/scriptables/script_ext_object.cpp
index b87aac81f9..a72b244f0a 100644
--- a/engines/wintermute/base/scriptables/script_ext_object.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_object.cpp
@@ -64,4 +64,4 @@ bool SXObject::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_object.h b/engines/wintermute/base/scriptables/script_ext_object.h
index c85d16d44e..566111292a 100644
--- a/engines/wintermute/base/scriptables/script_ext_object.h
+++ b/engines/wintermute/base/scriptables/script_ext_object.h
@@ -41,6 +41,6 @@ public:
virtual ~SXObject();
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp
index 7cb3b9360b..65bec03bc1 100644
--- a/engines/wintermute/base/scriptables/script_ext_string.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_string.cpp
@@ -298,21 +298,13 @@ bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
uint32 start = 0;
for(uint32 i = 0; i < str.size() + 1; i++) {
- char ch = str.c_str()[i];
- if(ch=='\0' || delims.contains(ch))
- {
- char *part = new char[i - start + 1];
- if(i != start) {
- Common::strlcpy(part, str.c_str() + start, i - start + 1);
- part[i - start] = '\0';
+ uint32 ch = str[i];
+ if (ch =='\0' || delims.contains(ch)) {
+ if (i != start) {
+ parts.push_back(WideString(str.c_str() + start, i - start + 1));
} else {
- part[0] = '\0';
+ parts.push_back(WideString());
}
- val = new ScValue(_gameRef, part);
- array->push(val);
- delete[] part;
- delete val;
- val = nullptr;
start = i + 1;
}
}
@@ -406,7 +398,7 @@ bool SXString::persist(BasePersistenceManager *persistMgr) {
BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_capacity));
+ persistMgr->transferSint32(TMEMBER(_capacity));
if (persistMgr->getIsSaving()) {
if (_capacity > 0) {
@@ -430,4 +422,4 @@ int SXString::scCompare(BaseScriptable *val) {
return strcmp(_string, ((SXString *)val)->_string);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h
index 50b61deba4..7a95c59b4c 100644
--- a/engines/wintermute/base/scriptables/script_ext_string.h
+++ b/engines/wintermute/base/scriptables/script_ext_string.h
@@ -53,6 +53,6 @@ private:
int32 _capacity;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp
index b53457c81b..c828b3918e 100644
--- a/engines/wintermute/base/scriptables/script_stack.cpp
+++ b/engines/wintermute/base/scriptables/script_stack.cpp
@@ -186,10 +186,10 @@ bool ScStack::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_sP));
+ persistMgr->transferSint32(TMEMBER(_sP));
_values.persist(persistMgr);
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_stack.h b/engines/wintermute/base/scriptables/script_stack.h
index 82c3debefa..ee04485a51 100644
--- a/engines/wintermute/base/scriptables/script_stack.h
+++ b/engines/wintermute/base/scriptables/script_stack.h
@@ -61,6 +61,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp
index 5e2923e029..52367646a5 100644
--- a/engines/wintermute/base/scriptables/script_value.cpp
+++ b/engines/wintermute/base/scriptables/script_value.cpp
@@ -791,32 +791,32 @@ void ScValue::setValue(ScValue *val) {
bool ScValue::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_persistent));
- persistMgr->transfer(TMEMBER(_isConstVar));
- persistMgr->transfer(TMEMBER_INT(_type));
- persistMgr->transfer(TMEMBER(_valBool));
- persistMgr->transfer(TMEMBER(_valFloat));
- persistMgr->transfer(TMEMBER(_valInt));
+ persistMgr->transferBool(TMEMBER(_persistent));
+ persistMgr->transferBool(TMEMBER(_isConstVar));
+ persistMgr->transferSint32(TMEMBER_INT(_type));
+ persistMgr->transferBool(TMEMBER(_valBool));
+ persistMgr->transferDouble(TMEMBER(_valFloat));
+ persistMgr->transferSint32(TMEMBER(_valInt));
persistMgr->transferPtr(TMEMBER_PTR(_valNative));
int32 size;
const char *str;
if (persistMgr->getIsSaving()) {
size = _valObject.size();
- persistMgr->transfer("", &size);
+ persistMgr->transferSint32("", &size);
_valIter = _valObject.begin();
while (_valIter != _valObject.end()) {
str = _valIter->_key.c_str();
- persistMgr->transfer("", &str);
+ persistMgr->transferConstChar("", &str);
persistMgr->transferPtr("", &_valIter->_value);
_valIter++;
}
} else {
ScValue *val = nullptr;
- persistMgr->transfer("", &size);
+ persistMgr->transferSint32("", &size);
for (int i = 0; i < size; i++) {
- persistMgr->transfer("", &str);
+ persistMgr->transferConstChar("", &str);
persistMgr->transferPtr("", &val);
_valObject[str] = val;
@@ -825,7 +825,18 @@ bool ScValue::persist(BasePersistenceManager *persistMgr) {
}
persistMgr->transferPtr(TMEMBER_PTR(_valRef));
- persistMgr->transfer(TMEMBER(_valString));
+ persistMgr->transferCharPtr(TMEMBER(_valString));
+
+ if (!persistMgr->getIsSaving() && !persistMgr->checkVersion(1,2,2)) {
+ // Savegames prior to 1.2.2 stored empty strings as NULL.
+ // We disambiguate those by turning NULL strings into empty
+ // strings if _type is VAL_STRING instead of VAL_NULL.
+
+ if (_type == VAL_STRING && !_valString) {
+ _valString = new char[1];
+ _valString[0] = '\0';
+ }
+ }
/* // TODO: Convert to Debug-statements.
FILE* f = fopen("c:\\val.log", "a+");
@@ -992,4 +1003,4 @@ bool ScValue::setProperty(const char *propName) {
return ret;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h
index a8e815023e..90ad9f182a 100644
--- a/engines/wintermute/base/scriptables/script_value.h
+++ b/engines/wintermute/base/scriptables/script_value.h
@@ -108,6 +108,6 @@ public:
bool setProperty(const char *propName);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp
index d027c03c8b..f9cd59e4fb 100644
--- a/engines/wintermute/base/sound/base_sound.cpp
+++ b/engines/wintermute/base/sound/base_sound.cpp
@@ -166,16 +166,16 @@ bool BaseSound::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_soundFilename));
- persistMgr->transfer(TMEMBER(_soundLooping));
- persistMgr->transfer(TMEMBER(_soundPaused));
- persistMgr->transfer(TMEMBER(_soundFreezePaused));
- persistMgr->transfer(TMEMBER(_soundPlaying));
- persistMgr->transfer(TMEMBER(_soundPosition));
- persistMgr->transfer(TMEMBER(_soundPrivateVolume));
- persistMgr->transfer(TMEMBER(_soundStreamed));
- persistMgr->transfer(TMEMBER_INT(_soundType));
- persistMgr->transfer(TMEMBER(_soundLoopStart));
+ persistMgr->transferString(TMEMBER(_soundFilename));
+ persistMgr->transferBool(TMEMBER(_soundLooping));
+ persistMgr->transferBool(TMEMBER(_soundPaused));
+ persistMgr->transferBool(TMEMBER(_soundFreezePaused));
+ persistMgr->transferBool(TMEMBER(_soundPlaying));
+ persistMgr->transferUint32(TMEMBER(_soundPosition));
+ persistMgr->transferSint32(TMEMBER(_soundPrivateVolume));
+ persistMgr->transferBool(TMEMBER(_soundStreamed));
+ persistMgr->transferSint32(TMEMBER_INT(_soundType));
+ persistMgr->transferUint32(TMEMBER(_soundLoopStart));
return STATUS_OK;
}
@@ -289,4 +289,4 @@ bool BaseSound::applyFX(TSFXType type, float param1, float param2, float param3,
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound.h b/engines/wintermute/base/sound/base_sound.h
index 3412e6c3a3..0a984d240a 100644
--- a/engines/wintermute/base/sound/base_sound.h
+++ b/engines/wintermute/base/sound/base_sound.h
@@ -82,6 +82,6 @@ private:
BaseSoundBuffer *_sound;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
index 9c919abac6..7666a441a3 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.cpp
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -292,4 +292,4 @@ bool BaseSoundBuffer::applyFX(TSFXType type, float param1, float param2, float p
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h
index e78d062cd4..53b86f64c6 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.h
+++ b/engines/wintermute/base/sound/base_sound_buffer.h
@@ -95,6 +95,6 @@ private:
int32 _volume;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp
index f3e7bfb408..68e62f25b0 100644
--- a/engines/wintermute/base/sound/base_sound_manager.cpp
+++ b/engines/wintermute/base/sound/base_sound_manager.cpp
@@ -287,4 +287,4 @@ float BaseSoundMgr::posToPan(int x, int y) {
return minPan + relPos * (maxPan - minPan);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_manager.h b/engines/wintermute/base/sound/base_sound_manager.h
index 602571765f..5993a05001 100644
--- a/engines/wintermute/base/sound/base_sound_manager.h
+++ b/engines/wintermute/base/sound/base_sound_manager.h
@@ -64,6 +64,6 @@ private:
bool setMasterVolume(byte percent);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/base/timer.cpp b/engines/wintermute/base/timer.cpp
index 5dfc117f48..f1f79af760 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.
@@ -66,9 +66,9 @@ uint32 Timer::getTimeLast() const {
}
void Timer::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_timer));
- persistMgr->transfer(TMEMBER(_timerDelta));
- persistMgr->transfer(TMEMBER(_timerLast));
+ persistMgr->transferUint32(TMEMBER(_timer));
+ persistMgr->transferUint32(TMEMBER(_timerDelta));
+ persistMgr->transferUint32(TMEMBER(_timerLast));
}
} // End of namespace Wintermute
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/coll_templ.h b/engines/wintermute/coll_templ.h
index 4a8e92c121..307989e58d 100644
--- a/engines/wintermute/coll_templ.h
+++ b/engines/wintermute/coll_templ.h
@@ -67,7 +67,7 @@ class BaseArray : public BaseArrayBase<TYPE> {
int32 j;
if (persistMgr->getIsSaving()) {
j = Common::Array<TYPE>::size();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
typename Common::Array<TYPE>::const_iterator it = Common::Array<TYPE>::begin();
for (; it != Common::Array<TYPE>::end(); ++it) {
TYPE obj = *it;
@@ -75,7 +75,7 @@ class BaseArray : public BaseArrayBase<TYPE> {
}
} else {
Common::Array<TYPE>::clear();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
for (int i = 0; i < j; i++) {
TYPE obj = nullptr;
persistMgr->transferPtr("", &obj);
@@ -93,18 +93,18 @@ class BaseArray<char *> : public BaseArrayBase<char *> {
int32 j;
if (persistMgr->getIsSaving()) {
j = Common::Array<char *>::size();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
Common::Array<char *>::const_iterator it = Common::Array<char *>::begin();
for (; it != Common::Array<char *>::end(); ++it) {
char * obj = *it;
- persistMgr->transfer("", &obj);
+ persistMgr->transferCharPtr("", &obj);
}
} else {
Common::Array<char *>::clear();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
for (int i = 0; i < j; i++) {
char * obj = nullptr;
- persistMgr->transfer("", &obj);
+ persistMgr->transferCharPtr("", &obj);
add(obj);
}
}
@@ -119,18 +119,18 @@ public:
int32 j;
if (persistMgr->getIsSaving()) {
j = Common::Array<const char *>::size();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
Common::Array<const char *>::const_iterator it = Common::Array<const char *>::begin();
for (; it != Common::Array<const char *>::end(); ++it) {
const char * obj = *it;
- persistMgr->transfer("", &obj);
+ persistMgr->transferConstChar("", &obj);
}
} else {
Common::Array<const char *>::clear();
- persistMgr->transfer("ArraySize", &j);
+ persistMgr->transferSint32("ArraySize", &j);
for (int i = 0; i < j; i++) {
const char * obj = nullptr;
- persistMgr->transfer("", &obj);
+ persistMgr->transferConstChar("", &obj);
add(obj);
}
}
@@ -138,6 +138,6 @@ public:
}
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/configure.engine b/engines/wintermute/configure.engine
new file mode 100644
index 0000000000..673549b46b
--- /dev/null
+++ b/engines/wintermute/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine wintermute "Wintermute" no "" "" "jpeg png zlib vorbis 16bit"
diff --git a/engines/wintermute/dcgf.h b/engines/wintermute/dcgf.h
index fe92194443..3db443965e 100644
--- a/engines/wintermute/dcgf.h
+++ b/engines/wintermute/dcgf.h
@@ -33,7 +33,7 @@
//////////////////////////////////////////////////////////////////////////
#define DCGF_VER_MAJOR 1
#define DCGF_VER_MINOR 2
-#define DCGF_VER_BUILD 1
+#define DCGF_VER_BUILD 2
#define DCGF_VER_SUFFIX "ScummVM"
#define DCGF_VER_BETA true
diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h
index bd4966eb6b..4371ee4889 100644
--- a/engines/wintermute/dctypes.h
+++ b/engines/wintermute/dctypes.h
@@ -31,6 +31,7 @@
#include "common/str.h"
+#include "common/ustr.h"
#include "common/list.h"
#include "common/array.h"
@@ -41,7 +42,7 @@ namespace Wintermute {
//typedef std::wstring WideString;
typedef Common::String AnsiString;
typedef Common::String Utf8String;
-typedef Common::String WideString; // NB: Not actually true I presume.
+typedef Common::U32String WideString;
typedef Common::List<WideString> WideStringList;
typedef Common::List<AnsiString> AnsiStringList;
@@ -220,6 +221,6 @@ enum TShadowType {
SHADOW_STENCIL = 3
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp
index 92b8e6251f..8c8b8255ab 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.
@@ -81,4 +81,4 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) {
return true;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
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.cpp b/engines/wintermute/detection.cpp
index 1bf2c76a50..f4bd437803 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -68,6 +68,7 @@ static char s_fallbackGameIdBuf[256];
static const char *directoryGlobs[] = {
"language", // To detect the various languages
+ "languages", // To detect the various languages
0
};
@@ -181,7 +182,7 @@ public:
}
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#if PLUGIN_ENABLED_DYNAMIC(WINTERMUTE)
REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, Wintermute::WintermuteMetaEngine);
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 00ec51a715..46e05f2768 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -27,6 +27,7 @@ namespace Wintermute {
static const PlainGameDescriptor wintermuteGames[] = {
{"5ld", "Five Lethal Demons"},
{"5ma", "Five Magical Amulets"},
+ {"bthreshold", "Beyond the Threshold"},
{"actualdest", "Actual Destination"},
{"carolreed4", "Carol Reed 4 - East Side Story"},
{"carolreed5", "Carol Reed 5 - The Colour of Murder"},
@@ -36,17 +37,29 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"carolreed9", "Carol Reed 9 - Cold Case Summer"},
{"chivalry", "Chivalry is Not Dead"},
{"deadcity", "Dead City"},
+ {"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"},
{"dirtysplit", "Dirty Split"},
{"dreamscape", "Dreamscape"},
+ {"escapemansion", "Escape from the Mansion"},
{"ghostsheet", "Ghost in the Sheet"},
{"hamlet", "Hamlet or the last game without MMORPS features, shaders and product placement"},
+ {"helga", "Helga Deep In Trouble"},
+ {"jamesperis", "James Peris: No License Nor Control"},
+ {"looky", "Looky"},
{"julia", "J.U.L.I.A."},
{"mirage", "Mirage"},
+ {"paintaria", "Paintaria"},
{"pigeons", "Pigeons in the Park"},
{"reversion1", "Reversion: The Escape"},
- {"reversion2", "Reversion: The Meeting"},
+ {"reversion2", "Reversion: The Meeting"},
{"rosemary", "Rosemary"},
+ {"shaban", "Shaban"},
+ {"shinestar", "The Shine of a Star"},
+ {"spaceinvaders", "Space Invaders"},
+ {"spacemadness", "Space Madness"},
{"thebox", "The Box"},
+ {"tib", "Fairy Tales About Toshechka and Boshechka"},
+ {"tradestory", "The Trader of Stories"},
{"twc", "the white chamber"},
{"wintermute", "Wintermute engine game"},
{0, 0}
@@ -83,6 +96,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Beyond the Threshold
+ {
+ "bthreshold",
+ "",
+ AD_ENTRY1s("data.dcp", "d49bf9ccb2e74507447c82d6ad3e2bc4", 12773712),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Carol Reed 4 - East Side Story (Demo)
{
"carolreed4",
@@ -125,6 +148,17 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Carol Reed 7 - Blue Madonna (Demo)
+ {
+ "carolreed7",
+ "Demo",
+ AD_ENTRY1s("data.dcp", "0372ad0c775266f6355e9e8ae397a2f1", 103719442),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Carol Reed 7 - Blue Madonna
{
"carolreed7",
@@ -175,6 +209,22 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_TESTING,
GUIO0()
},
+ // Dead City (Czech)
+ {
+ "deadcity",
+ "",
+ {
+ // The Czech data are in data.dcp, so in this case we'll have to
+ // just detect the english version twice, to give the user a choice.
+ {"english.dcp", 0, "c591046d6de7e381d76f70e0787b2b1f", 415935},
+ {"data.dcp", 0, "7ebfd50d1a22370ed7b079bcaa631d62", 9070205},
+ AD_LISTEND
+ },
+ Common::CZ_CZE,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Dead City (English)
{
"deadcity",
@@ -237,6 +287,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Des Reves Elastiques Avec Mille Insectes Nommes Georges
+ {
+ "dreaming",
+ "",
+ AD_ENTRY1s("data.dcp", "4af26d97ea063fc1277ce30ae431de90", 8804073),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Dreamscape
{
"dreamscape",
@@ -247,6 +307,26 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Escape from the Mansion
+ {
+ "escapemansion",
+ "Beta 1",
+ AD_ENTRY1s("data.dcp", "d8e348b2312cc36a929cad75f12e0b3a", 21452380),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Escape from the Mansion
+ {
+ "escapemansion",
+ "Beta 2",
+ AD_ENTRY1s("data.dcp", "ded5fa6c5f2afdaf2cafb53e52cd3dd8", 21455763),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Ghosts in the Sheet
{
"ghostsheet",
@@ -268,6 +348,63 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Helga Deep In Trouble (Demo) (English)
+ {
+ "helga",
+ "Demo",
+ {
+ {"english.dcp", 0, "b3a93e678f0ef97200f691cd1724643f", 135864},
+ {"data.dcp", 0, "45134ed93bc391edf148b79cdcbf2a09", 154266028},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // 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::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,
+ GUIO0()
+ },
// J.U.L.I.A. (English)
{
"julia",
@@ -289,6 +426,61 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DEMO,
GUIO0()
},
+ // J.U.L.I.A. (English) (Greenlight Demo)
+ {
+ "julia",
+ "Greenlight Demo",
+ AD_ENTRY1s("data.dcp", "4befd448d36b0dae9c3ab1aa7cb8b78d", 7271886),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // Looky Demo (English)
+ {
+ "looky",
+ "Demo",
+ {
+ {"english.dcp", 0, "1388e1dd320f4d553dea3b0316812f9d", 1358442},
+ {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // Looky Demo (German)
+ {
+ "looky",
+ "Demo",
+ {
+ {"german.dcp", 0, "606c048426dfbe94442b59fd34a5c76e", 14339496},
+ {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // Looky (German)
+ {
+ "looky",
+ "",
+ {
+ {"german.dcp", 0, "bf4c2b8c26342342441a6d64934ab832", 107027865},
+ {"data.dcp", 0, "50de0beaa5ad621aa9f020df901d1e74", 1342214},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Mirage
{
"mirage",
@@ -299,6 +491,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Paintaria
+ {
+ "paintaria",
+ "",
+ AD_ENTRY1s("data.dcp", "354c08440c98150ff0d4008dd2865880", 48326040),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Pigeons in the Park
{
"pigeons",
@@ -535,6 +737,47 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Shaban
+ {
+ "shaban",
+ "",
+ AD_ENTRY1s("data.dcp", "35f702ca9baabc5c620e0be230195c8a", 755388466),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // The Shine of a Star
+ {
+ "shinestar",
+ "",
+ AD_ENTRY1s("data.dcp", "f05abe9e2427a5e4f73648fa09c4ba8e", 94113060),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Space Invaders (Demo)
+ {
+ "spaceinvaders",
+ "Demo",
+ AD_ENTRY1s("data.dcp", "3f27adefdf72f2c1601cf555c80a509f", 1308361),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // Space Madness
+ {
+ "spacemadness",
+ "1.0.2",
+ AD_ENTRY1s("data.dcp", "b9b83135dc7a9e1b4b5f50195dbeb630", 39546622),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Box
{
"thebox",
@@ -545,6 +788,27 @@ 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",
+ "Demo",
+ AD_ENTRY1s("data.dcp", "0a0b51191636cc8ead89b905281c3218", 40401902),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// the white chamber (multi-language)
{
"twc",
diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp
new file mode 100644
index 0000000000..822c06f42f
--- /dev/null
+++ b/engines/wintermute/graphics/transform_struct.cpp
@@ -0,0 +1,119 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "engines/wintermute/graphics/transform_struct.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
+
+namespace Wintermute {
+void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Point32 offset) {
+ _zoom = zoom;
+ _angle = angle;
+ _hotspot = hotspot;
+ _blendMode = blendMode;
+ _rgbaMod = rgbaMod;
+ _alphaDisable = alphaDisable;
+ _flip = 0;
+ _flip += TransparentSurface::FLIP_H * mirrorX;
+ _flip += TransparentSurface::FLIP_V * mirrorY;
+ _offset = offset;
+ _numTimesX = 1;
+ _numTimesY = 1;
+}
+
+TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) {
+ init(Point32(zoomX, zoomY),
+ angle,
+ Point32(hotspotX, hotspotY),
+ false,
+ blendMode,
+ rgbaMod,
+ mirrorX, mirrorY,
+ Point32(offsetX, offsetY));
+}
+
+TransformStruct::TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) {
+ init(Point32((int32)(zoomX / 100.0 * kDefaultZoomX),
+ (int32)(zoomY / 100.0 * kDefaultZoomY)),
+ angle,
+ Point32(hotspotX, hotspotY),
+ false,
+ blendMode,
+ rgbaMod,
+ mirrorX, mirrorY,
+ Point32(offsetX, offsetY));
+}
+
+TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) {
+ init(Point32(zoomX, zoomY),
+ kDefaultAngle,
+ Point32(kDefaultHotspotX, kDefaultHotspotY),
+ false,
+ blendMode,
+ rgbaMod,
+ mirrorX,
+ mirrorY,
+ Point32(kDefaultOffsetX, kDefaultOffsetY));
+}
+
+TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) {
+ init(Point32(zoomX, zoomY),
+ angle,
+ Point32(hotspotX, hotspotY),
+ true,
+ BLEND_NORMAL,
+ kDefaultRgbaMod,
+ false, false,
+ Point32(kDefaultOffsetX, kDefaultOffsetY));
+}
+
+TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) {
+ init(Point32(kDefaultZoomX, kDefaultZoomY),
+ kDefaultAngle,
+ Point32(kDefaultHotspotX, kDefaultHotspotY),
+ false,
+ BLEND_NORMAL,
+ kDefaultRgbaMod,
+ false, false,
+ Point32(kDefaultOffsetX, kDefaultOffsetY));
+ _numTimesX = numTimesX;
+ _numTimesY = numTimesY;
+}
+
+TransformStruct::TransformStruct() {
+ init(Point32(kDefaultZoomX, kDefaultZoomY),
+ kDefaultAngle,
+ Point32(kDefaultHotspotX, kDefaultHotspotY),
+ true,
+ BLEND_NORMAL,
+ kDefaultRgbaMod,
+ false, false,
+ Point32(kDefaultOffsetX, kDefaultOffsetY));
+}
+
+bool TransformStruct::getMirrorX() const {
+ return (bool)(_flip & TransparentSurface::FLIP_H);
+}
+
+bool TransformStruct::getMirrorY() const {
+ return (bool)(_flip & TransparentSurface::FLIP_V);
+}
+} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h
new file mode 100644
index 0000000000..d5a03ea331
--- /dev/null
+++ b/engines/wintermute/graphics/transform_struct.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WINTERMUTE_TRANSFORM_STRUCT_H
+#define WINTERMUTE_TRANSFORM_STRUCT_H
+
+#include "engines/wintermute/math/rect32.h"
+#include "engines/wintermute/dctypes.h"
+
+namespace Wintermute {
+/**
+ * Contains all the required information that define a transform.
+ * Same source sprite + same TransformStruct = Same resulting sprite.
+ * Has a number of overloaded constructors to accomodate various argument lists.
+ */
+
+const int32 kDefaultZoomX = 100;
+const int32 kDefaultZoomY = 100;
+const uint32 kDefaultRgbaMod = 0xFFFFFFFF;
+const int32 kDefaultHotspotX = 0;
+const int32 kDefaultHotspotY = 0;
+const int32 kDefaultOffsetX = 0;
+const int32 kDefaultOffsetY = 0;
+const int32 kDefaultAngle = 0;
+
+struct TransformStruct {
+private:
+ void init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Point32 offset);
+
+public:
+ TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0);
+ TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0);
+ TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false);
+ TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0);
+ TransformStruct(int32 numTimesX, int32 numTimesY);
+ TransformStruct();
+
+ Point32 _zoom; ///< Zoom; 100 = no zoom
+ Point32 _hotspot; ///< Position of the hotspot
+ int32 _angle; ///< Rotation angle, in degrees
+ byte _flip; ///< Bitflag: see TransparentSurface::FLIP_XXX
+ bool _alphaDisable;
+ TSpriteBlendMode _blendMode;
+ uint32 _rgbaMod; ///< RGBa
+ Point32 _offset;
+ int32 _numTimesX;
+ int32 _numTimesY;
+
+ bool getMirrorX() const;
+ bool getMirrorY() const;
+
+ bool operator==(const TransformStruct &compare) const {
+ return (compare._angle == _angle &&
+ compare._flip == _flip &&
+ compare._zoom == _zoom &&
+ compare._offset == _offset &&
+ compare._alphaDisable == _alphaDisable &&
+ compare._rgbaMod == _rgbaMod &&
+ compare._blendMode == _blendMode &&
+ compare._numTimesX == _numTimesX &&
+ compare._numTimesY == _numTimesY
+ );
+ }
+
+ bool operator!=(const TransformStruct &compare) const {
+ return !(compare == *this);
+ }
+};
+} // End of namespace Wintermute
+#endif
diff --git a/engines/wintermute/graphics/transform_tools.cpp b/engines/wintermute/graphics/transform_tools.cpp
new file mode 100644
index 0000000000..dc92cdbbfd
--- /dev/null
+++ b/engines/wintermute/graphics/transform_tools.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 "engines/wintermute/graphics/transform_tools.h"
+#include <math.h>
+
+namespace Wintermute {
+
+FloatPoint TransformTools::transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX, const bool mirrorY) {
+ float rotateRad = rotate * M_PI / 180.0f;
+ float x = point.x;
+ float y = point.y;
+ x = (x * zoom.x) / kDefaultZoomX;
+ y = (y * zoom.y) / kDefaultZoomY;
+#if 0
+ // TODO: Mirroring should be done before rotation, but the blitting
+ // code does the inverse, so we match that for now.
+ if (mirrorX)
+ x *= -1;
+ if (mirrorY)
+ y *= -1;
+#endif
+ FloatPoint newPoint;
+ newPoint.x = x * cos(rotateRad) - y * sin(rotateRad);
+ newPoint.y = x * sin(rotateRad) + y * cos(rotateRad);
+ if (mirrorX) {
+ newPoint.x *= -1;
+ }
+ if (mirrorY) {
+ newPoint.y *= -1;
+ }
+ return newPoint;
+}
+
+Rect32 TransformTools::newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot) {
+ Point32 nw(oldRect.left, oldRect.top);
+ Point32 ne(oldRect.right, oldRect.top);
+ Point32 sw(oldRect.left, oldRect.bottom);
+ Point32 se(oldRect.right, oldRect.bottom);
+
+ FloatPoint nw1, ne1, sw1, se1;
+
+ nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom);
+ ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom);
+ sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom);
+ se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom);
+
+ float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y)));
+ float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y)));
+ float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x)));
+ float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x)));
+
+ if (newHotspot) {
+ newHotspot->y = (uint32)(-floor(top));
+ newHotspot->x = (uint32)(-floor(left));
+ }
+
+ Rect32 res;
+ res.top = (int32)(floor(top)) + transform._hotspot.y;
+ res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y;
+ res.left = (int32)(floor(left)) + transform._hotspot.x;
+ res.right = (int32)(ceil(right)) + transform._hotspot.x;
+
+ return res;
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transform_tools.h b/engines/wintermute/graphics/transform_tools.h
new file mode 100644
index 0000000000..9a73e3b69f
--- /dev/null
+++ b/engines/wintermute/graphics/transform_tools.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WINTERMUTE_TRANSFORM_TOOLS_H
+#define WINTERMUTE_TRANSFORM_TOOLS_H
+
+#include "engines/wintermute/math/rect32.h"
+#include "engines/wintermute/math/floatpoint.h"
+#include "engines/wintermute/graphics/transform_struct.h"
+
+namespace Wintermute {
+
+class TransformTools {
+public:
+ /**
+ * Basic transform (scale + rotate) for a single point
+ */
+ static FloatPoint transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX = false, const bool mirrorY = false);
+
+ /**
+ * @param &point the point on which the transform is to be applied
+ * @param rotate the angle in degrees
+ * @param &zoom zoom x,y in percent
+ * @param mirrorX flip along the vertical axis?
+ * @param mirrorY flip along the horizontal axis?
+ * @return the smallest rect that can contain the transformed sprite
+ * and, as a side-effect, "newHotspot" will tell you where the hotspot will
+ * have ended up in the new rect, for centering.
+ */
+ static Rect32 newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot);
+};
+
+} // End of namespace Wintermute
+#endif
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp
index dcdcbf247e..053acf29e9 100644
--- a/engines/wintermute/graphics/transparent_surface.cpp
+++ b/engines/wintermute/graphics/transparent_surface.cpp
@@ -17,28 +17,268 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * The bottom part of this is file is adapted from SDL_rotozoom.c. The
+ * relevant copyright notice for those specific functions can be found at the
+ * top of that section.
+ *
*/
+
+
#include "common/algorithm.h"
#include "common/endian.h"
#include "common/util.h"
#include "common/rect.h"
+#include "common/math.h"
#include "common/textconsole.h"
#include "graphics/primitives.h"
#include "engines/wintermute/graphics/transparent_surface.h"
+#include "engines/wintermute/graphics/transform_tools.h"
+
+//#define ENABLE_BILINEAR
namespace Wintermute {
-byte *TransparentSurface::_lookup = nullptr;
+void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
+void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
+
+// These gather together various blendPixel functions for use with templates.
+
+class BlenderAdditive {
+public:
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
+ inline void blendPixel(byte *in, byte *out);
+ inline void blendPixel(byte *in, byte *out, int colorMod);
+};
+
+class BlenderSubtractive {
+public:
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
+ inline void blendPixel(byte *in, byte *out);
+ inline void blendPixel(byte *in, byte *out, int colorMod);
+};
+
+class BlenderNormal {
+public:
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
+ inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
+ inline void blendPixel(byte *in, byte *out);
+ inline void blendPixel(byte *in, byte *out, int colorMod);
+};
+
+/**
+ * Perform additive blending of a pixel, applying beforehand a given colormod.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ * @param *outa, *outr, *outg, *outb pointer to the colormod components.
+ */
+void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
+ if (*ca != 255) {
+ ina = (ina) * (*ca) >> 8;
+ }
+
+ if (ina == 0) {
+ return;
+ } else {
+ if (*cb != 255)
+ *outb = MIN(*outb + ((inb * (*cb) * ina) >> 16), 255);
+ else
+ *outb = MIN(*outb + (inb * ina >> 8), 255);
+
+ if (*cg != 255)
+ *outg = MIN(*outg + ((ing * (*cg) * ina) >> 16), 255);
+ else
+ *outg = MIN(*outg + (ing * ina >> 8), 255);
+
+ if (*cr != 255)
+ *outr = MIN(*outr + ((inr * (*cr) * ina) >> 16), 255);
+ else
+ *outr = MIN(*outr + (inr * ina >> 8), 255);
+ }
+}
+
+/**
+ * Perform subtractive blending of a pixel, applying beforehand a given colormod.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ * @param *outa, *outr, *outg, *outb pointer to the colormod components.
+ */
+void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
+ //if (*ca != 255) {
+ // ina = ina * (*ca) >> 8;
+ // }
+
+ // As weird as it is, evidence suggests that alphamod is ignored when doing
+ // subtractive...
+
+ // TODO if ina == 255 fast version
+
+ if (ina == 0) {
+ return;
+ } else {
+ if (*cb != 255)
+ *outb = MAX(*outb - ((inb * (*cb) * (*outb) * ina) >> 24), 0);
+ else
+ *outb = MAX(*outb - (inb * (*outb) * ina >> 16), 0);
+
+ if (*cg != 255)
+ *outg = MAX(*outg - ((ing * (*cg) * (*outg) * ina) >> 24), 0);
+ else
+ *outg = MAX(*outg - (ing * (*outg) * ina >> 16), 0);
+
+ if (*cr != 255)
+ *outr = MAX(*outr - ((inr * (*cr) * (*outr) * ina) >> 24), 0);
+ else
+ *outr = MAX(*outr - (inr * (*outr) * ina >> 16), 0);
+ }
+}
+
+/**
+ * Perform "regular" alphablending of a pixel, applying beforehand a given colormod.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ * @param *outa, *outr, *outg, *outb pointer to the colormod components.
+ */
+
+void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
+ if (*ca != 255) {
+ ina = ina * (*ca) >> 8;
+ }
+
+ if (ina == 0) {
+ return;
+ } else if (ina == 255) {
+ if (*cb != 255)
+ *outb = (inb * (*cb)) >> 8;
+ else
+ *outb = inb;
+
+ if (*cr != 255)
+ *outr = (inr * (*cr)) >> 8;
+ else
+ *outr = inr;
+
+ if (*cg != 255)
+ *outg = (ing * (*cg)) >> 8;
+ else
+ *outg = ing;
+
+ *outa = ina;
-void TransparentSurface::destroyLookup() {
- delete[] _lookup;
- _lookup = nullptr;
+ return;
+
+ } else {
+
+ *outa = 255;
+ *outb = (*outb * (255 - ina) >> 8);
+ *outr = (*outr * (255 - ina) >> 8);
+ *outg = (*outg * (255 - ina) >> 8);
+
+ if (*cb == 0)
+ *outb = *outb;
+ else if (*cb != 255)
+ *outb = *outb + (inb * ina * (*cb) >> 16);
+ else
+ *outb = *outb + (inb * ina >> 8);
+
+ if (*cr == 0)
+ *outr = *outr;
+ else if (*cr != 255)
+ *outr = *outr + (inr * ina * (*cr) >> 16);
+ else
+ *outr = *outr + (inr * ina >> 8);
+
+ if (*cg == 0)
+ *outg = *outg;
+ else if (*cg != 255)
+ *outg = *outg + (ing * ina * (*cg) >> 16);
+ else
+ *outg = *outg + (ing * ina >> 8);
+
+ return;
+ }
+}
+
+/**
+ * Perform "regular" alphablending of a pixel.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ */
+
+void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
+
+ if (ina == 0) {
+ return;
+ } else if (ina == 255) {
+ *outb = inb;
+ *outg = ing;
+ *outr = inr;
+ *outa = ina;
+ return;
+ } else {
+ *outa = 255;
+ *outb = ((inb * ina) + *outb * (255 - ina)) >> 8;
+ *outg = ((ing * ina) + *outg * (255 - ina)) >> 8;
+ *outr = ((inr * ina) + *outr * (255 - ina)) >> 8;
+ }
+}
+
+/**
+ * Perform subtractive blending of a pixel.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ */
+void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
+
+ if (ina == 0) {
+ return;
+ } else if (ina == 255) {
+ *outa = *outa;
+ *outr = *outr - (inr * (*outr) >> 8);
+ *outg = *outg - (ing * (*outg) >> 8);
+ *outb = *outb - (inb * (*outb) >> 8);
+ return;
+ } else {
+ *outa = *outa;
+ *outb = MAX(*outb - ((inb * (*outb)) * ina >> 16), 0);
+ *outg = MAX(*outg - ((ing * (*outg)) * ina >> 16), 0);
+ *outr = MAX(*outr - ((inr * (*outr)) * ina >> 16), 0);
+ return;
+ }
+}
+
+/**
+ * Perform additive blending of a pixel.
+ * @param ina, inr, ing, inb: the input pixel, split into its components.
+ * @param *outa, *outr, *outg, *outb pointer to the output pixel.
+ */
+void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
+
+ if (ina == 0) {
+ return;
+ } else if (ina == 255) {
+ *outa = *outa;
+ *outr = MIN(*outr + inr, 255);
+ *outg = MIN(*outg + ing, 255);
+ *outb = MIN(*outb + inb, 255);
+ return;
+ } else {
+ *outa = *outa;
+ *outb = MIN((inb * ina >> 8) + *outb, 255);
+ *outg = MIN((ing * ina >> 8) + *outg, 255);
+ *outr = MIN((inr * ina >> 8) + *outr, 255);
+ return;
+ }
}
-TransparentSurface::TransparentSurface() : Surface(), _enableAlphaBlit(true) {}
-TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _enableAlphaBlit(true) {
+TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {}
+
+TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) {
if (copyData) {
copyFrom(surf);
} else {
@@ -46,25 +286,27 @@ TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Sur
h = surf.h;
pitch = surf.pitch;
format = surf.format;
- pixels = surf.pixels;
+ // We need to cast the const qualifier away here because 'pixels'
+ // always needs to be writable. 'surf' however is a constant Surface,
+ // thus getPixels will always return const pixel data.
+ pixels = const_cast<void *>(surf.getPixels());
}
}
-void doBlitOpaque(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
- byte *in, *out;
+/**
+ * Optimized version of doBlit to be used w/opaque blitting (no alpha).
+ */
+void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
-#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
-#else
- const int aIndex = 0;
-#endif
+ byte *in;
+ byte *out;
for (uint32 i = 0; i < height; i++) {
out = outo;
in = ino;
memcpy(out, in, width * 4);
for (uint32 j = 0; j < width; j++) {
- out[aIndex] = 0xFF;
+ out[TransparentSurface::kAIndex] = 0xFF;
out += 4;
}
outo += pitch;
@@ -72,98 +314,110 @@ void doBlitOpaque(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pit
}
}
-void TransparentSurface::generateLookup() {
- _lookup = new byte[256 * 256];
- for (int i = 0; i < 256; i++) {
- for (int j = 0; j < 256; j++) {
- _lookup[(i << 8) + j] = (i * j) >> 8;
- }
- }
-}
-
-void TransparentSurface::doBlitAlpha(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
- byte *in, *out;
-
- if (!_lookup) {
- generateLookup();
- }
-
-#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
- const int bIndex = 0;
- const int gIndex = 1;
- const int rIndex = 2;
-#else
- const int aIndex = 0;
- const int bIndex = 3;
- const int gIndex = 2;
- const int rIndex = 1;
-#endif
-
- const int bShift = 0;//img->format.bShift;
- const int gShift = 8;//img->format.gShift;
- const int rShift = 16;//img->format.rShift;
- const int aShift = 24;//img->format.aShift;
+/**
+ * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending).
+ */
+void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
- const int bShiftTarget = 0;//target.format.bShift;
- const int gShiftTarget = 8;//target.format.gShift;
- const int rShiftTarget = 16;//target.format.rShift;
+ byte *in;
+ byte *out;
for (uint32 i = 0; i < height; i++) {
out = outo;
in = ino;
for (uint32 j = 0; j < width; j++) {
uint32 pix = *(uint32 *)in;
- uint32 oPix = *(uint32 *) out;
- int b = (pix >> bShift) & 0xff;
- int g = (pix >> gShift) & 0xff;
- int r = (pix >> rShift) & 0xff;
- int a = (pix >> aShift) & 0xff;
- int outb, outg, outr, outa;
- in += inStep;
+ int a = (pix >> TransparentSurface::kAShift) & 0xff;
- switch (a) {
- case 0: // Full transparency
- out += 4;
- break;
- case 255: // Full opacity
- outb = b;
- outg = g;
- outr = r;
- outa = a;
-
- out[aIndex] = outa;
- out[bIndex] = outb;
- out[gIndex] = outg;
- out[rIndex] = outr;
- out += 4;
- break;
-
- default: // alpha blending
- outa = 255;
-
- outb = _lookup[(((oPix >> bShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outg = _lookup[(((oPix >> gShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outr = _lookup[(((oPix >> rShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outb += _lookup[b + (a << 8)];
- outg += _lookup[g + (a << 8)];
- outr += _lookup[r + (a << 8)];
-
- out[aIndex] = outa;
- out[bIndex] = outb;
- out[gIndex] = outg;
- out[rIndex] = outr;
- out += 4;
+ if (a == 0) { // Full transparency
+ } else { // Full opacity (Any value not exactly 0 is Opaque here)
+ *(uint32 *)out = pix;
+ out[TransparentSurface::kAIndex] = 0xFF;
}
+ out += 4;
+ in += inStep;
}
outo += pitch;
ino += inoStep;
}
}
+/**
+ * What we have here is a template method that calls blendPixel() from a different
+ * class - the one we call it with - thus performing a different type of blending.
+ *
+ * @param ino a pointer to the input surface
+ * @param outo a pointer to the output surface
+ * @param width width of the input surface
+ * @param height height of the input surface
+ * @param pitch pitch of the output surface - that is, width in bytes of every row, usually bpp * width of the TARGET surface (the area we are blitting to might be smaller, do the math)
+ * @inStep size in bytes to skip to address each pixel, usually bpp of the source surface
+ * @inoStep width in bytes of every row on the *input* surface / kind of like pitch
+ * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod
+ */
-Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) {
- int ca = (color >> 24) & 0xff;
+template<class Blender>
+void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+ Blender b;
+ byte *in;
+ byte *out;
+
+ if (color == 0xffffffff) {
+
+ for (uint32 i = 0; i < height; i++) {
+ out = outo;
+ in = ino;
+ for (uint32 j = 0; j < width; j++) {
+
+ byte *outa = &out[TransparentSurface::kAIndex];
+ byte *outr = &out[TransparentSurface::kRIndex];
+ byte *outg = &out[TransparentSurface::kGIndex];
+ byte *outb = &out[TransparentSurface::kBIndex];
+
+ b.blendPixel(in[TransparentSurface::kAIndex],
+ in[TransparentSurface::kRIndex],
+ in[TransparentSurface::kGIndex],
+ in[TransparentSurface::kBIndex],
+ outa, outr, outg, outb);
+
+ in += inStep;
+ out += 4;
+ }
+ outo += pitch;
+ ino += inoStep;
+ }
+ } else {
+
+ byte ca = (color >> TransparentSurface::kAModShift) & 0xFF;
+ byte cr = (color >> TransparentSurface::kRModShift) & 0xFF;
+ byte cg = (color >> TransparentSurface::kGModShift) & 0xFF;
+ byte cb = (color >> TransparentSurface::kBModShift) & 0xFF;
+
+ for (uint32 i = 0; i < height; i++) {
+ out = outo;
+ in = ino;
+ for (uint32 j = 0; j < width; j++) {
+
+ byte *outa = &out[TransparentSurface::kAIndex];
+ byte *outr = &out[TransparentSurface::kRIndex];
+ byte *outg = &out[TransparentSurface::kGIndex];
+ byte *outb = &out[TransparentSurface::kBIndex];
+
+ b.blendPixel(in[TransparentSurface::kAIndex],
+ in[TransparentSurface::kRIndex],
+ in[TransparentSurface::kGIndex],
+ in[TransparentSurface::kBIndex],
+ outa, outr, outg, outb, &ca, &cr, &cg, &cb);
+ in += inStep;
+ out += 4;
+ }
+ outo += pitch;
+ ino += inoStep;
+ }
+ }
+}
+
+Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) {
Common::Rect retSize;
retSize.top = 0;
@@ -171,21 +425,11 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
retSize.setWidth(0);
retSize.setHeight(0);
// Check if we need to draw anything at all
+ int ca = (color >> 24) & 0xff;
+
if (ca == 0)
return retSize;
- int cr = (color >> 16) & 0xff;
- int cg = (color >> 8) & 0xff;
- int cb = (color >> 0) & 0xff;
-
- // Compensate for transparency. Since we're coming
- // down to 255 alpha, we just compensate for the colors here
- if (ca != 255) {
- cr = cr * ca >> 8;
- cg = cg * ca >> 8;
- cb = cb * ca >> 8;
- }
-
// Create an encapsulating surface for the data
TransparentSurface srcImage(*this, false);
// TODO: Is the data really in the screen format?
@@ -195,7 +439,19 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
}
if (pPartRect) {
- srcImage.pixels = &((char *)pixels)[pPartRect->top * srcImage.pitch + pPartRect->left * 4];
+
+ int xOffset = pPartRect->left;
+ int yOffset = pPartRect->top;
+
+ if (flipping & FLIP_V) {
+ yOffset = srcImage.h - pPartRect->bottom;
+ }
+
+ if (flipping & FLIP_H) {
+ xOffset = srcImage.w - pPartRect->right;
+ }
+
+ srcImage.pixels = getBasePtr(xOffset, yOffset);
srcImage.w = pPartRect->width();
srcImage.h = pPartRect->height();
@@ -224,7 +480,7 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
if ((width != srcImage.w) || (height != srcImage.h)) {
// Scale the image
img = imgScaled = srcImage.scale(width, height);
- savedPixels = (byte *)img->pixels;
+ savedPixels = (byte *)img->getPixels();
} else {
img = &srcImage;
}
@@ -232,13 +488,13 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
// Handle off-screen clipping
if (posY < 0) {
img->h = MAX(0, (int)img->h - -posY);
- img->pixels = (byte *)img->pixels + img->pitch * -posY;
+ img->setPixels((byte *)img->getBasePtr(0, -posY));
posY = 0;
}
if (posX < 0) {
img->w = MAX(0, (int)img->w - -posX);
- img->pixels = (byte *)img->pixels + (-posX * 4);
+ img->setPixels((byte *)img->getBasePtr(-posX, 0));
posX = 0;
}
@@ -250,132 +506,41 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
int inStep = 4;
int inoStep = img->pitch;
- if (flipping & TransparentSurface::FLIP_V) {
+ if (flipping & TransparentSurface::FLIP_H) {
inStep = -inStep;
xp = img->w - 1;
}
- if (flipping & TransparentSurface::FLIP_H) {
+ if (flipping & TransparentSurface::FLIP_V) {
inoStep = -inoStep;
yp = img->h - 1;
}
- byte *ino = (byte *)img->getBasePtr(xp, yp);
+ byte *ino= (byte *)img->getBasePtr(xp, yp);
byte *outo = (byte *)target.getBasePtr(posX, posY);
- byte *in, *out;
-#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
- const int bIndex = 0;
- const int gIndex = 1;
- const int rIndex = 2;
-#else
- const int aIndex = 0;
- const int bIndex = 3;
- const int gIndex = 2;
- const int rIndex = 1;
-#endif
- const int bShift = 0;//img->format.bShift;
- const int gShift = 8;//img->format.gShift;
- const int rShift = 16;//img->format.rShift;
- const int aShift = 24;//img->format.aShift;
-
- const int bShiftTarget = 0;//target.format.bShift;
- const int gShiftTarget = 8;//target.format.gShift;
- const int rShiftTarget = 16;//target.format.rShift;
-
- if (ca == 255 && cb == 255 && cg == 255 && cr == 255) {
- if (_enableAlphaBlit) {
- doBlitAlpha(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
- } else {
- doBlitOpaque(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
- }
+ if (color == 0xFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) {
+ doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
+ } else if (color == 0xFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) {
+ doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
} else {
- for (int i = 0; i < img->h; i++) {
- out = outo;
- in = ino;
- for (int j = 0; j < img->w; j++) {
- uint32 pix = *(uint32 *)in;
- uint32 o_pix = *(uint32 *) out;
- int b = (pix >> bShift) & 0xff;
- int g = (pix >> gShift) & 0xff;
- int r = (pix >> rShift) & 0xff;
- int a = (pix >> aShift) & 0xff;
- int outb, outg, outr, outa;
- in += inStep;
-
- if (ca != 255) {
- a = a * ca >> 8;
- }
-
- switch (a) {
- case 0: // Full transparency
- out += 4;
- break;
- case 255: // Full opacity
- if (cb != 255)
- outb = (b * cb) >> 8;
- else
- outb = b;
-
- if (cg != 255)
- outg = (g * cg) >> 8;
- else
- outg = g;
-
- if (cr != 255)
- outr = (r * cr) >> 8;
- else
- outr = r;
- outa = a;
- out[aIndex] = outa;
- out[bIndex] = outb;
- out[gIndex] = outg;
- out[rIndex] = outr;
- out += 4;
- break;
-
- default: // alpha blending
- outa = 255;
- outb = (o_pix >> bShiftTarget) & 0xff;
- outg = (o_pix >> gShiftTarget) & 0xff;
- outr = (o_pix >> rShiftTarget) & 0xff;
- if (cb == 0)
- outb = 0;
- else if (cb != 255)
- outb += ((b - outb) * a * cb) >> 16;
- else
- outb += ((b - outb) * a) >> 8;
- if (cg == 0)
- outg = 0;
- else if (cg != 255)
- outg += ((g - outg) * a * cg) >> 16;
- else
- outg += ((g - outg) * a) >> 8;
- if (cr == 0)
- outr = 0;
- else if (cr != 255)
- outr += ((r - outr) * a * cr) >> 16;
- else
- outr += ((r - outr) * a) >> 8;
- out[aIndex] = outa;
- out[bIndex] = outb;
- out[gIndex] = outg;
- out[rIndex] = outr;
- out += 4;
- }
- }
- outo += target.pitch;
- ino += inoStep;
+ if (blendMode == BLEND_ADDITIVE) {
+ doBlit<BlenderAdditive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
+ } else if (blendMode == BLEND_SUBTRACTIVE) {
+ doBlit<BlenderSubtractive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
+ } else {
+ assert(blendMode == BLEND_NORMAL);
+ doBlit<BlenderNormal>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
}
}
+
}
retSize.setWidth(img->w);
retSize.setHeight(img->h);
if (imgScaled) {
- imgScaled->pixels = savedPixels;
+ imgScaled->setPixels(savedPixels);
imgScaled->free();
delete imgScaled;
}
@@ -383,38 +548,6 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
return retSize;
}
-TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const {
- Common::Rect srcRect(0, 0, (int16)w, (int16)h);
- Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight);
- return scale(srcRect, dstRect);
-}
-
-// Copied from clone2727's https://github.com/clone2727/scummvm/blob/pegasus/engines/pegasus/surface.cpp#L247
-TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
- // I'm doing simple linear scaling here
- // dstRect(x, y) = srcRect(x * srcW / dstW, y * srcH / dstH);
- TransparentSurface *target = new TransparentSurface();
-
- assert(format.bytesPerPixel == 4);
-
- int srcW = srcRect.width();
- int srcH = srcRect.height();
- int dstW = dstRect.width();
- int dstH = dstRect.height();
-
- target->create((uint16)dstW, (uint16)dstH, this->format);
-
- for (int y = 0; y < dstH; y++) {
- for (int x = 0; x < dstW; x++) {
- uint32 color = READ_UINT32((const byte *)getBasePtr(x * srcW / dstW + srcRect.left,
- y * srcH / dstH + srcRect.top));
- WRITE_UINT32((byte *)target->getBasePtr(x + dstRect.left, y + dstRect.top), color);
- }
- }
- return target;
-
-}
-
/**
* Writes a color key to the alpha channel of the surface
* @param rKey the red component of the color key
@@ -440,4 +573,351 @@ void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool
}
}
-} // End of namespace Graphics
+TransparentSurface::AlphaType TransparentSurface::getAlphaMode() const {
+ return _alphaMode;
+}
+
+void TransparentSurface::setAlphaMode(TransparentSurface::AlphaType mode) {
+ _alphaMode = mode;
+}
+
+
+
+
+
+
+/*
+
+The below two functions are adapted from SDL_rotozoom.c,
+taken from SDL_gfx-2.0.18.
+
+Its copyright notice:
+
+=============================================================================
+SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
+
+Copyright (C) 2001-2012 Andreas Schiffler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+Andreas Schiffler -- aschiffler at ferzkopp dot net
+=============================================================================
+
+
+The functions have been adapted for different structures and coordinate
+systems.
+
+*/
+
+
+
+
+
+TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
+
+ assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway.
+
+ Point32 newHotspot;
+ Common::Rect srcRect(0, 0, (int16)w, (int16)h);
+ Rect32 rect = TransformTools::newRect(Rect32(srcRect), transform, &newHotspot);
+ Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top));
+
+ TransparentSurface *target = new TransparentSurface();
+ assert(format.bytesPerPixel == 4);
+
+ int srcW = w;
+ int srcH = h;
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ target->create((uint16)dstW, (uint16)dstH, this->format);
+
+ if (transform._zoom.x == 0 || transform._zoom.y == 0)
+ return target;
+
+ uint32 invAngle = 360 - (transform._angle % 360);
+ float invCos = cos(invAngle * M_PI / 180.0);
+ float invSin = sin(invAngle * M_PI / 180.0);
+
+ struct tColorRGBA { byte r; byte g; byte b; byte a; };
+ int icosx = (int)(invCos * (65536.0f * kDefaultZoomX / transform._zoom.x));
+ int isinx = (int)(invSin * (65536.0f * kDefaultZoomX / transform._zoom.x));
+ int icosy = (int)(invCos * (65536.0f * kDefaultZoomY / transform._zoom.y));
+ int isiny = (int)(invSin * (65536.0f * kDefaultZoomY / transform._zoom.y));
+
+
+ bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
+
+ int xd = (srcRect.left + transform._hotspot.x) << 16;
+ int yd = (srcRect.top + transform._hotspot.y) << 16;
+ int cx = newHotspot.x;
+ int cy = newHotspot.y;
+
+ int ax = -icosx * cx;
+ int ay = -isiny * cx;
+ int sw = srcW - 1;
+ int sh = srcH - 1;
+
+ tColorRGBA *pc = (tColorRGBA*)target->getBasePtr(0, 0);
+
+ for (int y = 0; y < dstH; y++) {
+ int t = cy - y;
+ int sdx = ax + (isinx * t) + xd;
+ int sdy = ay - (icosy * t) + yd;
+ for (int x = 0; x < dstW; x++) {
+ int dx = (sdx >> 16);
+ int dy = (sdy >> 16);
+ if (flipx) dx = sw - dx;
+ if (flipy) dy = sh - dy;
+
+#ifdef ENABLE_BILINEAR
+ if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) {
+ const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy);
+ tColorRGBA c00, c01, c10, c11, cswap;
+ c00 = *sp;
+ sp += 1;
+ c01 = *sp;
+ sp += (this->pitch/4);
+ c11 = *sp;
+ sp -= 1;
+ c10 = *sp;
+ if (flipx) {
+ cswap = c00; c00=c01; c01=cswap;
+ cswap = c10; c10=c11; c11=cswap;
+ }
+ if (flipy) {
+ cswap = c00; c00=c10; c10=cswap;
+ cswap = c01; c01=c11; c11=cswap;
+ }
+ /*
+ * Interpolate colors
+ */
+ int ex = (sdx & 0xffff);
+ int ey = (sdy & 0xffff);
+ int t1, t2;
+ t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
+ t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
+ pc->r = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
+ t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
+ pc->g = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
+ t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
+ pc->b = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
+ t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
+ pc->a = (((t2 - t1) * ey) >> 16) + t1;
+ }
+#else
+ if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) {
+ const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy);
+ *pc = *sp;
+ }
+#endif
+ sdx += icosx;
+ sdy += isiny;
+ pc++;
+ }
+ }
+ return target;
+}
+
+TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const {
+
+ Common::Rect srcRect(0, 0, (int16)w, (int16)h);
+ Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight);
+
+ TransparentSurface *target = new TransparentSurface();
+
+ assert(format.bytesPerPixel == 4);
+
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ target->create((uint16)dstW, (uint16)dstH, this->format);
+
+#ifdef ENABLE_BILINEAR
+
+ // NB: The actual order of these bytes may not be correct, but
+ // since all values are treated equal, that does not matter.
+ struct tColorRGBA { byte r; byte g; byte b; byte a; };
+
+ bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
+
+
+ int *sax = new int[dstW+1];
+ int *say = new int[dstH+1];
+ assert(sax && say);
+
+ /*
+ * Precalculate row increments
+ */
+ int spixelw = (srcW - 1);
+ int spixelh = (srcH - 1);
+ int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1));
+ int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1));
+
+ /* Maximum scaled source size */
+ int ssx = (srcW << 16) - 1;
+ int ssy = (srcH << 16) - 1;
+
+ /* Precalculate horizontal row increments */
+ int csx = 0;
+ int *csax = sax;
+ for (int x = 0; x <= dstW; x++) {
+ *csax = csx;
+ csax++;
+ csx += sx;
+
+ /* Guard from overflows */
+ if (csx > ssx) {
+ csx = ssx;
+ }
+ }
+
+ /* Precalculate vertical row increments */
+ int csy = 0;
+ int *csay = say;
+ for (int y = 0; y <= dstH; y++) {
+ *csay = csy;
+ csay++;
+ csy += sy;
+
+ /* Guard from overflows */
+ if (csy > ssy) {
+ csy = ssy;
+ }
+ }
+
+ const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0,0);
+ tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0,0);
+ int spixelgap = srcW;
+
+ if (flipx)
+ sp += spixelw;
+ if (flipy)
+ sp += spixelgap * spixelh;
+
+ csay = say;
+ for (int y = 0; y < dstH; y++) {
+ const tColorRGBA *csp = sp;
+ csax = sax;
+ for (int x = 0; x < dstW; x++) {
+ /*
+ * Setup color source pointers
+ */
+ int ex = (*csax & 0xffff);
+ int ey = (*csay & 0xffff);
+ int cx = (*csax >> 16);
+ int cy = (*csay >> 16);
+
+ const tColorRGBA *c00, *c01, *c10, *c11;
+ c00 = sp;
+ c01 = sp;
+ c10 = sp;
+ if (cy < spixelh) {
+ if (flipy)
+ c10 -= spixelgap;
+ else
+ c10 += spixelgap;
+ }
+ c11 = c10;
+ if (cx < spixelw) {
+ if (flipx) {
+ c01--;
+ c11--;
+ } else {
+ c01++;
+ c11++;
+ }
+ }
+
+ /*
+ * Draw and interpolate colors
+ */
+ int t1, t2;
+ t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
+ t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
+ dp->r = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
+ t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
+ dp->g = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
+ t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
+ dp->b = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
+ t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
+ dp->a = (((t2 - t1) * ey) >> 16) + t1;
+
+ /*
+ * Advance source pointer x
+ */
+ int *salastx = csax;
+ csax++;
+ int sstepx = (*csax >> 16) - (*salastx >> 16);
+ if (flipx)
+ sp -= sstepx;
+ else
+ sp += sstepx;
+
+ /*
+ * Advance destination pointer x
+ */
+ dp++;
+ }
+ /*
+ * Advance source pointer y
+ */
+ int *salasty = csay;
+ csay++;
+ int sstepy = (*csay >> 16) - (*salasty >> 16);
+ sstepy *= spixelgap;
+ if (flipy)
+ sp = csp - sstepy;
+ else
+ sp = csp + sstepy;
+ }
+
+ delete[] sax;
+ delete[] say;
+
+#else
+
+ int *scaleCacheX = new int[dstW];
+ for (int x = 0; x < dstW; x++)
+ scaleCacheX[x] = (x * srcW) / dstW;
+
+ for (int y = 0; y < dstH; y++) {
+ uint32 *destP = (uint32 *)target->getBasePtr(0, y);
+ const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH);
+ for (int x = 0; x < dstW; x++)
+ *destP++ = srcP[scaleCacheX[x]];
+ }
+ delete[] scaleCacheX;
+
+#endif
+
+ return target;
+
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h
index dc079a1fbc..1f3827d1a9 100644
--- a/engines/wintermute/graphics/transparent_surface.h
+++ b/engines/wintermute/graphics/transparent_surface.h
@@ -23,6 +23,7 @@
#define GRAPHICS_TRANSPARENTSURFACE_H
#include "graphics/surface.h"
+#include "engines/wintermute/graphics/transform_struct.h"
/*
* This code is based on Broken Sword 2.5 engine
@@ -66,50 +67,94 @@ struct TransparentSurface : public Graphics::Surface {
FLIP_VH = FLIP_H | FLIP_V
};
- bool _enableAlphaBlit;
+ enum AlphaType {
+ ALPHA_OPAQUE = 0,
+ ALPHA_BINARY = 1,
+ ALPHA_FULL = 2
+ };
+
+ #ifdef SCUMM_LITTLE_ENDIAN
+ static const int kAIndex = 0;
+ static const int kBIndex = 1;
+ static const int kGIndex = 2;
+ static const int kRIndex = 3;
+ #else
+ static const int kAIndex = 3;
+ static const int kBIndex = 2;
+ static const int kGIndex = 1;
+ static const int kRIndex = 0;
+ #endif
+
+ static const int kBShift = 8;//img->format.bShift;
+ static const int kGShift = 16;//img->format.gShift;
+ static const int kRShift = 24;//img->format.rShift;
+ static const int kAShift = 0;//img->format.aShift;
+
+
+ static const int kBModShift = 0;//img->format.bShift;
+ static const int kGModShift = 8;//img->format.gShift;
+ static const int kRModShift = 16;//img->format.rShift;
+ static const int kAModShift = 24;//img->format.aShift;
+
/**
@brief renders the surface to another surface
- @param pDest a pointer to the target image. In most cases this is the framebuffer.
- @param PosX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br>
+ @param target a pointer to the target surface. In most cases this is the framebuffer.
+ @param posX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br>
The default value is 0.
- @param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br>
+ @param posY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br>
The default value is 0.
- @param Flipping how the the image should be flipped.<br>
+ @param flipping how the the image should be flipped.<br>
The default value is BS_Image::FLIP_NONE (no flipping)
- @param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br>
+ @param pPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br>
This referes to the unflipped and unscaled image.<br>
The default value is NULL.
- @param Color an ARGB color value, which determines the parameters for the color modulation und alpha blending.<br>
+ @param color an ARGB color value, which determines the parameters for the color modulation und alpha blending.<br>
The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).<br>
The color components determines the color for color modulation.<br>
The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation).
The macros BS_RGB and BS_ARGB can be used for the creation of the color value.
- @param Width the output width of the screen section.
+ @param width the output width of the screen section.
The images will be scaled if the output width of the screen section differs from the image section.<br>
The value -1 determines that the image should not be scaled.<br>
The default value is -1.
- @param Width the output height of the screen section.
+ @param height the output height of the screen section.
The images will be scaled if the output width of the screen section differs from the image section.<br>
The value -1 determines that the image should not be scaled.<br>
The default value is -1.
@return returns false if the rendering failed.
*/
-
Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0,
int flipping = FLIP_NONE,
Common::Rect *pPartRect = nullptr,
uint color = BS_ARGB(255, 255, 255, 255),
- int width = -1, int height = -1);
+ int width = -1, int height = -1,
+ TSpriteBlendMode blend = BLEND_NORMAL);
void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false);
- // The following scale-code supports arbitrary scaling (i.e. no repeats of column 0 at the end of lines)
+
+ /**
+ * @brief Scale function; this returns a transformed version of this surface after rotation and
+ * scaling. Please do not use this if angle != 0, use rotoscale.
+ *
+ * @param newWidth the resulting width.
+ * @param newHeight the resulting height.
+ * @see TransformStruct
+ */
TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
- TransparentSurface *scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const;
- static byte *_lookup;
- static void destroyLookup();
+
+ /**
+ * @brief Rotoscale function; this returns a transformed version of this surface after rotation and
+ * scaling. Please do not use this if angle == 0, use plain old scaling function.
+ *
+ * @param transform a TransformStruct wrapping the required info. @see TransformStruct
+ *
+ */
+ TransparentSurface *rotoscale(const TransformStruct &transform) const;
+ AlphaType getAlphaMode() const;
+ void setAlphaMode(AlphaType);
private:
- static void doBlitAlpha(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
- static void generateLookup();
+ AlphaType _alphaMode;
+
};
/**
@@ -124,8 +169,7 @@ private:
}
};*/
-
-} // End of namespace Graphics
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/math/floatpoint.h b/engines/wintermute/math/floatpoint.h
new file mode 100644
index 0000000000..0c47ef09d7
--- /dev/null
+++ b/engines/wintermute/math/floatpoint.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WINTERMUTE_FLOATPOINT_H
+#define WINTERMUTE_FLOATPOINT_H
+
+namespace Wintermute {
+
+struct FloatPoint {
+ float x;
+ float y;
+ FloatPoint() : x(0), y(0) {}
+ FloatPoint(float x1, float y1) : x(x1), y(y1) {}
+ bool operator==(const FloatPoint &p) const { return x == p.x && y == p.y; }
+ bool operator!=(const FloatPoint &p) const { return x != p.x || y != p.y; }
+ FloatPoint operator+(const FloatPoint &delta) const { return FloatPoint (x + delta.x, y + delta.y); }
+ FloatPoint operator-(const FloatPoint &delta) const { return FloatPoint (x - delta.x, y - delta.y); }
+
+ FloatPoint& operator+=(const FloatPoint &delta) {
+ x += delta.x;
+ y += delta.y;
+ return *this;
+ }
+ FloatPoint& operator-=(const FloatPoint &delta) {
+ x -= delta.x;
+ y -= delta.y;
+ return *this;
+ }
+};
+
+} // End of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/math/math_util.cpp b/engines/wintermute/math/math_util.cpp
index 31af77538a..903cea6d39 100644
--- a/engines/wintermute/math/math_util.cpp
+++ b/engines/wintermute/math/math_util.cpp
@@ -27,7 +27,7 @@
*/
#include "engines/wintermute/math/math_util.h"
-#include <math.h>
+#include "common/scummsys.h"
namespace Wintermute {
@@ -49,4 +49,4 @@ float MathUtil::roundUp(float val) {
return result;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/math/math_util.h b/engines/wintermute/math/math_util.h
index 38b6d9abf9..41a7a43e2e 100644
--- a/engines/wintermute/math/math_util.h
+++ b/engines/wintermute/math/math_util.h
@@ -37,6 +37,6 @@ public:
static float roundUp(float val);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/math/matrix4.cpp b/engines/wintermute/math/matrix4.cpp
index ca1eae8813..011766f510 100644
--- a/engines/wintermute/math/matrix4.cpp
+++ b/engines/wintermute/math/matrix4.cpp
@@ -28,7 +28,7 @@
#include "engines/wintermute/math/matrix4.h"
#include "engines/wintermute/math/vector2.h"
-#include <math.h>
+#include "common/scummsys.h"
namespace Wintermute {
@@ -83,4 +83,4 @@ void Matrix4::transformVector2(Vector2 &vec) {
vec.y = y;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/math/matrix4.h b/engines/wintermute/math/matrix4.h
index 273633f723..4198b50484 100644
--- a/engines/wintermute/math/matrix4.h
+++ b/engines/wintermute/math/matrix4.h
@@ -45,6 +45,6 @@ public:
float m[4][4];
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/math/rect32.h b/engines/wintermute/math/rect32.h
index 190c1135cf..a4a64690e2 100644
--- a/engines/wintermute/math/rect32.h
+++ b/engines/wintermute/math/rect32.h
@@ -24,12 +24,38 @@
#define WINTERMUTE_RECT32_H
#include "common/system.h"
+#include "engines/wintermute/math/floatpoint.h"
+#include "common/rect.h"
namespace Wintermute {
struct Point32 {
int32 x;
int32 y;
+ Point32() : x(0), y(0) {}
+ Point32(int32 x1, int32 y1) : x(x1), y(y1) {}
+ bool operator==(const Point32 &p) const { return x == p.x && y == p.y; }
+ bool operator!=(const Point32 &p) const { return x != p.x || y != p.y; }
+ Point32 operator+(const Point32 &delta) const { return Point32(x + delta.x, y + delta.y); }
+ Point32 operator-(const Point32 &delta) const { return Point32(x - delta.x, y - delta.y); }
+
+ Point32 &operator+=(const Point32 &delta) {
+ x += delta.x;
+ y += delta.y;
+ return *this;
+ }
+
+ Point32 &operator-=(const Point32 &delta) {
+ x -= delta.x;
+ y -= delta.y;
+ return *this;
+ }
+
+ operator FloatPoint() {
+ return FloatPoint(x,y);
+ }
+
+
};
struct Rect32 {
@@ -38,6 +64,7 @@ struct Rect32 {
Rect32() : top(0), left(0), bottom(0), right(0) {}
Rect32(int32 w, int32 h) : top(0), left(0), bottom(h), right(w) {}
+ Rect32(const Common::Rect &rect) : top(rect.top), left(rect.left), bottom(rect.bottom), right(rect.right) {}
Rect32(int32 x1, int32 y1, int32 x2, int32 y2) : top(y1), left(x1), bottom(y2), right(x2) {
assert(isValidRect());
}
@@ -67,12 +94,24 @@ struct Rect32 {
left = right = top = bottom = 0;
}
+ bool isRectEmpty() const {
+ return (left >= right) || (top >= bottom);
+ }
+
void offsetRect(int dx, int dy) {
left += dx;
top += dy;
right += dx;
bottom += dy;
}
+
+ void setRect(int32 newLeft, int32 newTop, int32 newRight, int32 newBottom) {
+ this->left = newLeft;
+ this->top = newTop;
+ this->right = newRight;
+ this->bottom = newBottom;
+ }
+
/**
* Check if the given rect is equal to this one.
*
@@ -89,6 +128,6 @@ struct Rect32 {
}
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/math/vector2.cpp b/engines/wintermute/math/vector2.cpp
index 74c5586d62..618ee9bda9 100644
--- a/engines/wintermute/math/vector2.cpp
+++ b/engines/wintermute/math/vector2.cpp
@@ -27,7 +27,7 @@
*/
#include "engines/wintermute/math/vector2.h"
-#include <math.h>
+#include "common/scummsys.h"
namespace Wintermute {
@@ -52,4 +52,4 @@ float Vector2::length() const {
return (float)sqrt(x * x + y * y);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/math/vector2.h b/engines/wintermute/math/vector2.h
index 31f31daaa0..e4ba97c517 100644
--- a/engines/wintermute/math/vector2.h
+++ b/engines/wintermute/math/vector2.h
@@ -70,6 +70,6 @@ public:
float y;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index 32931bf05f..95f9ba2ffb 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -89,6 +89,8 @@ MODULE_OBJS := \
base/save_thumb_helper.o \
base/timer.o \
detection.o \
+ graphics/transform_struct.o \
+ graphics/transform_tools.o \
graphics/transparent_surface.o \
math/math_util.o \
math/matrix4.o \
diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h
index 1464ae0fd6..ddc0791054 100644
--- a/engines/wintermute/persistent.h
+++ b/engines/wintermute/persistent.h
@@ -37,7 +37,7 @@ class BasePersistenceManager;
typedef void *(*PERSISTBUILD)(void);
typedef bool(*PERSISTLOAD)(void *, BasePersistenceManager *);
typedef void(*SYS_INSTANCE_CALLBACK)(void *instance, void *data);
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#include "engines/wintermute/system/sys_class_registry.h"
namespace Wintermute {
@@ -85,6 +85,6 @@ namespace Wintermute {
#define TMEMBER_PTR(memberName) #memberName, &memberName
#define TMEMBER_INT(memberName) #memberName, (int32*)&memberName
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp
index 362c0da624..9fa23c6074 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?
@@ -166,52 +169,16 @@ bool BasePlatform::setCursorPos(int x, int y) {
}
//////////////////////////////////////////////////////////////////////////
-bool BasePlatform::showWindow(int nCmdShow) {
- return false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-void BasePlatform::setCapture() {
- return;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool BasePlatform::releaseCapture() {
- return false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool BasePlatform::setRectEmpty(Rect32 *lprc) {
- lprc->left = lprc->right = lprc->top = lprc->bottom = 0;
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool BasePlatform::isRectEmpty(const Rect32 *lprc) {
- return (lprc->left >= lprc->right) || (lprc->top >= lprc->bottom);
-}
-
-//////////////////////////////////////////////////////////////////////////
bool BasePlatform::ptInRect(Rect32 *lprc, Point32 p) {
return (p.x >= lprc->left) && (p.x < lprc->right) && (p.y >= lprc->top) && (p.y < lprc->bottom);
}
//////////////////////////////////////////////////////////////////////////
-bool BasePlatform::setRect(Rect32 *lprc, int left, int top, int right, int bottom) {
- lprc->left = left;
- lprc->top = top;
- lprc->right = right;
- lprc->bottom = bottom;
-
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////
bool BasePlatform::intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2) {
- if (isRectEmpty(lprcSrc1) || isRectEmpty(lprcSrc2) ||
+ if (lprcSrc1->isRectEmpty() || lprcSrc2->isRectEmpty() ||
lprcSrc1->left >= lprcSrc2->right || lprcSrc2->left >= lprcSrc1->right ||
lprcSrc1->top >= lprcSrc2->bottom || lprcSrc2->top >= lprcSrc1->bottom) {
- setRectEmpty(lprcDst);
+ lprcDst->setEmpty();
return false;
}
lprcDst->left = MAX(lprcSrc1->left, lprcSrc2->left);
@@ -224,15 +191,15 @@ bool BasePlatform::intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const
//////////////////////////////////////////////////////////////////////////
bool BasePlatform::unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2) {
- if (isRectEmpty(lprcSrc1)) {
- if (isRectEmpty(lprcSrc2)) {
- setRectEmpty(lprcDst);
+ if (lprcSrc1->isRectEmpty()) {
+ if (lprcSrc2->isRectEmpty()) {
+ lprcDst->setEmpty();
return false;
} else {
*lprcDst = *lprcSrc2;
}
} else {
- if (isRectEmpty(lprcSrc2)) {
+ if (lprcSrc2->isRectEmpty()) {
*lprcDst = *lprcSrc1;
} else {
lprcDst->left = MIN(lprcSrc1->left, lprcSrc2->left);
@@ -272,4 +239,4 @@ char *BasePlatform::strlwr(char *string) {
return string;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/platform_osystem.h b/engines/wintermute/platform_osystem.h
index 8c39b29ea9..16d55745b9 100644
--- a/engines/wintermute/platform_osystem.h
+++ b/engines/wintermute/platform_osystem.h
@@ -48,13 +48,7 @@ public:
// Win32 API bindings
static bool getCursorPos(Point32 *lpPoint);
static bool setCursorPos(int x, int y);
- static bool showWindow(int nCmdShow);
- static void setCapture();
- static bool releaseCapture();
-
- static bool setRectEmpty(Rect32 *lprc);
- static bool isRectEmpty(const Rect32 *lprc);
static bool ptInRect(Rect32 *lprc, Point32 p);
static bool setRect(Rect32 *lprc, int left, int top, int right, int bottom);
static bool intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2);
@@ -70,6 +64,6 @@ private:
static WintermuteEngine *_engineRef;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/system/sys_class.cpp b/engines/wintermute/system/sys_class.cpp
index cda58bbb48..0577f29e2c 100644
--- a/engines/wintermute/system/sys_class.cpp
+++ b/engines/wintermute/system/sys_class.cpp
@@ -217,4 +217,4 @@ void SystemClass::instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpDat
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/system/sys_class.h b/engines/wintermute/system/sys_class.h
index 3f91723ed8..9fb3f70696 100644
--- a/engines/wintermute/system/sys_class.h
+++ b/engines/wintermute/system/sys_class.h
@@ -125,6 +125,6 @@ private:
InstanceMap _instanceMap;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/system/sys_class_registry.cpp b/engines/wintermute/system/sys_class_registry.cpp
index 8a6aae754f..20e4661efb 100644
--- a/engines/wintermute/system/sys_class_registry.cpp
+++ b/engines/wintermute/system/sys_class_registry.cpp
@@ -333,4 +333,4 @@ void SystemClassRegistry::dumpClasses(Common::WriteStream *stream) {
}
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/system/sys_class_registry.h b/engines/wintermute/system/sys_class_registry.h
index ef7218c7c1..48a6738ffb 100644
--- a/engines/wintermute/system/sys_class_registry.h
+++ b/engines/wintermute/system/sys_class_registry.h
@@ -101,6 +101,6 @@ public:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/system/sys_instance.cpp b/engines/wintermute/system/sys_instance.cpp
index d106119dba..b8e5c9b50a 100644
--- a/engines/wintermute/system/sys_instance.cpp
+++ b/engines/wintermute/system/sys_instance.cpp
@@ -46,4 +46,4 @@ SystemInstance::SystemInstance(void *instance, int id, SystemClass *sysClass) {
SystemInstance::~SystemInstance() {
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/system/sys_instance.h b/engines/wintermute/system/sys_instance.h
index 215a6d1437..115de28094 100644
--- a/engines/wintermute/system/sys_instance.h
+++ b/engines/wintermute/system/sys_instance.h
@@ -63,6 +63,6 @@ private:
SystemClass *_class;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp
index 9db1f4f4b4..7526174b64 100644
--- a/engines/wintermute/ui/ui_button.cpp
+++ b/engines/wintermute/ui/ui_button.cpp
@@ -103,7 +103,7 @@ UIButton::~UIButton() {
//////////////////////////////////////////////////////////////////////////
bool UIButton::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UIButton::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -162,7 +162,7 @@ TOKEN_DEF(PIXEL_PERFECT)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UIButton::loadBuffer(byte *buffer, bool complete) {
+bool UIButton::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(BUTTON)
TOKEN_TABLE(TEMPLATE)
@@ -202,38 +202,38 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_BUTTON) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_BUTTON) {
_gameRef->LOG(0, "'BUTTON' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_BACK:
delete _back;
_back = new UITiledImage(_gameRef);
- if (!_back || DID_FAIL(_back->loadFile((char *)params))) {
+ if (!_back || DID_FAIL(_back->loadFile(params))) {
delete _back;
_back = nullptr;
cmd = PARSERR_GENERIC;
@@ -243,7 +243,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_BACK_HOVER:
delete _backHover;
_backHover = new UITiledImage(_gameRef);
- if (!_backHover || DID_FAIL(_backHover->loadFile((char *)params))) {
+ if (!_backHover || DID_FAIL(_backHover->loadFile(params))) {
delete _backHover;
_backHover = nullptr;
cmd = PARSERR_GENERIC;
@@ -253,7 +253,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_BACK_PRESS:
delete _backPress;
_backPress = new UITiledImage(_gameRef);
- if (!_backPress || DID_FAIL(_backPress->loadFile((char *)params))) {
+ if (!_backPress || DID_FAIL(_backPress->loadFile(params))) {
delete _backPress;
_backPress = nullptr;
cmd = PARSERR_GENERIC;
@@ -263,7 +263,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_BACK_DISABLE:
delete _backDisable;
_backDisable = new UITiledImage(_gameRef);
- if (!_backDisable || DID_FAIL(_backDisable->loadFile((char *)params))) {
+ if (!_backDisable || DID_FAIL(_backDisable->loadFile(params))) {
delete _backDisable;
_backDisable = nullptr;
cmd = PARSERR_GENERIC;
@@ -273,7 +273,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_BACK_FOCUS:
delete _backFocus;
_backFocus = new UITiledImage(_gameRef);
- if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) {
+ if (!_backFocus || DID_FAIL(_backFocus->loadFile(params))) {
delete _backFocus;
_backFocus = nullptr;
cmd = PARSERR_GENERIC;
@@ -283,7 +283,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE:
delete _image;
_image = new BaseSprite(_gameRef);
- if (!_image || DID_FAIL(_image->loadFile((char *)params))) {
+ if (!_image || DID_FAIL(_image->loadFile(params))) {
delete _image;
_image = nullptr;
cmd = PARSERR_GENERIC;
@@ -293,7 +293,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE_HOVER:
delete _imageHover;
_imageHover = new BaseSprite(_gameRef);
- if (!_imageHover || DID_FAIL(_imageHover->loadFile((char *)params))) {
+ if (!_imageHover || DID_FAIL(_imageHover->loadFile(params))) {
delete _imageHover;
_imageHover = nullptr;
cmd = PARSERR_GENERIC;
@@ -303,7 +303,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE_PRESS:
delete _imagePress;
_imagePress = new BaseSprite(_gameRef);
- if (!_imagePress || DID_FAIL(_imagePress->loadFile((char *)params))) {
+ if (!_imagePress || DID_FAIL(_imagePress->loadFile(params))) {
delete _imagePress;
_imagePress = nullptr;
cmd = PARSERR_GENERIC;
@@ -313,7 +313,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE_DISABLE:
delete _imageDisable;
_imageDisable = new BaseSprite(_gameRef);
- if (!_imageDisable || DID_FAIL(_imageDisable->loadFile((char *)params))) {
+ if (!_imageDisable || DID_FAIL(_imageDisable->loadFile(params))) {
delete _imageDisable;
_imageDisable = nullptr;
cmd = PARSERR_GENERIC;
@@ -323,7 +323,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE_FOCUS:
delete _imageFocus;
_imageFocus = new BaseSprite(_gameRef);
- if (!_imageFocus || DID_FAIL(_imageFocus->loadFile((char *)params))) {
+ if (!_imageFocus || DID_FAIL(_imageFocus->loadFile(params))) {
delete _imageFocus;
_imageFocus = nullptr;
cmd = PARSERR_GENERIC;
@@ -334,7 +334,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
if (_font) {
_gameRef->_fontStorage->removeFont(_font);
}
- _font = _gameRef->_fontStorage->addFont((char *)params);
+ _font = _gameRef->_fontStorage->addFont(params);
if (!_font) {
cmd = PARSERR_GENERIC;
}
@@ -344,7 +344,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
if (_fontHover) {
_gameRef->_fontStorage->removeFont(_fontHover);
}
- _fontHover = _gameRef->_fontStorage->addFont((char *)params);
+ _fontHover = _gameRef->_fontStorage->addFont(params);
if (!_fontHover) {
cmd = PARSERR_GENERIC;
}
@@ -354,7 +354,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
if (_fontPress) {
_gameRef->_fontStorage->removeFont(_fontPress);
}
- _fontPress = _gameRef->_fontStorage->addFont((char *)params);
+ _fontPress = _gameRef->_fontStorage->addFont(params);
if (!_fontPress) {
cmd = PARSERR_GENERIC;
}
@@ -364,7 +364,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
if (_fontDisable) {
_gameRef->_fontStorage->removeFont(_fontDisable);
}
- _fontDisable = _gameRef->_fontStorage->addFont((char *)params);
+ _fontDisable = _gameRef->_fontStorage->addFont(params);
if (!_fontDisable) {
cmd = PARSERR_GENERIC;
}
@@ -374,21 +374,21 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
if (_fontFocus) {
_gameRef->_fontStorage->removeFont(_fontFocus);
}
- _fontFocus = _gameRef->_fontStorage->addFont((char *)params);
+ _fontFocus = _gameRef->_fontStorage->addFont(params);
if (!_fontFocus) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_TEXT:
- setText((char *)params);
+ setText(params);
_gameRef->expandStringByStringTable(&_text);
break;
case TOKEN_TEXT_ALIGN:
- if (scumm_stricmp((char *)params, "left") == 0) {
+ if (scumm_stricmp(params, "left") == 0) {
_align = TAL_LEFT;
- } else if (scumm_stricmp((char *)params, "right") == 0) {
+ } else if (scumm_stricmp(params, "right") == 0) {
_align = TAL_RIGHT;
} else {
_align = TAL_CENTER;
@@ -396,25 +396,25 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_WIDTH:
- parser.scanStr((char *)params, "%d", &_width);
+ parser.scanStr(params, "%d", &_width);
break;
case TOKEN_HEIGHT:
- parser.scanStr((char *)params, "%d", &_height);
+ parser.scanStr(params, "%d", &_height);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -422,35 +422,35 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PARENT_NOTIFY:
- parser.scanStr((char *)params, "%b", &_parentNotify);
+ parser.scanStr(params, "%b", &_parentNotify);
break;
case TOKEN_DISABLED:
- parser.scanStr((char *)params, "%b", &_disable);
+ parser.scanStr(params, "%b", &_disable);
break;
case TOKEN_VISIBLE:
- parser.scanStr((char *)params, "%b", &_visible);
+ parser.scanStr(params, "%b", &_visible);
break;
case TOKEN_FOCUSABLE:
- parser.scanStr((char *)params, "%b", &_canFocus);
+ parser.scanStr(params, "%b", &_canFocus);
break;
case TOKEN_CENTER_IMAGE:
- parser.scanStr((char *)params, "%b", &_centerImage);
+ parser.scanStr(params, "%b", &_centerImage);
break;
case TOKEN_PRESSED:
- parser.scanStr((char *)params, "%b", &_stayPressed);
+ parser.scanStr(params, "%b", &_stayPressed);
break;
case TOKEN_PIXEL_PERFECT:
- parser.scanStr((char *)params, "%b", &_pixelPerfect);
+ parser.scanStr(params, "%b", &_pixelPerfect);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -655,12 +655,12 @@ bool UIButton::display(int offsetX, int offsetY) {
BaseFont *font = 0;
//RECT rect;
- //BasePlatform::setRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height);
+ //rect.setRect(OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height);
//_hover = (!_disable && BasePlatform::ptInRect(&rect, _gameRef->_mousePos)!=FALSE);
_hover = (!_disable && _gameRef->_activeObject == this && (_gameRef->_interactive || _gameRef->_state == GAME_SEMI_FROZEN));
if ((_press && _hover && !_gameRef->_mouseLeftDown) ||
- (_oneTimePress && g_system->getMillis() - _oneTimePressTime >= 100)) {
+ (_oneTimePress && g_system->getMillis() - _oneTimePressTime >= 100)) {
press();
}
@@ -1178,25 +1178,25 @@ bool UIButton::persist(BasePersistenceManager *persistMgr) {
UIObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER_INT(_align));
+ persistMgr->transferSint32(TMEMBER_INT(_align));
persistMgr->transferPtr(TMEMBER_PTR(_backDisable));
persistMgr->transferPtr(TMEMBER_PTR(_backFocus));
persistMgr->transferPtr(TMEMBER_PTR(_backHover));
persistMgr->transferPtr(TMEMBER_PTR(_backPress));
- persistMgr->transfer(TMEMBER(_centerImage));
+ persistMgr->transferBool(TMEMBER(_centerImage));
persistMgr->transferPtr(TMEMBER_PTR(_fontDisable));
persistMgr->transferPtr(TMEMBER_PTR(_fontFocus));
persistMgr->transferPtr(TMEMBER_PTR(_fontHover));
persistMgr->transferPtr(TMEMBER_PTR(_fontPress));
- persistMgr->transfer(TMEMBER(_hover));
+ persistMgr->transferBool(TMEMBER(_hover));
persistMgr->transferPtr(TMEMBER_PTR(_image));
persistMgr->transferPtr(TMEMBER_PTR(_imageDisable));
persistMgr->transferPtr(TMEMBER_PTR(_imageFocus));
persistMgr->transferPtr(TMEMBER_PTR(_imageHover));
persistMgr->transferPtr(TMEMBER_PTR(_imagePress));
- persistMgr->transfer(TMEMBER(_pixelPerfect));
- persistMgr->transfer(TMEMBER(_press));
- persistMgr->transfer(TMEMBER(_stayPressed));
+ persistMgr->transferBool(TMEMBER(_pixelPerfect));
+ persistMgr->transferBool(TMEMBER(_press));
+ persistMgr->transferBool(TMEMBER(_stayPressed));
if (!persistMgr->getIsSaving()) {
_oneTimePress = false;
@@ -1206,4 +1206,28 @@ bool UIButton::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+void UIButton::setFontHover(BaseFont *font) {
+ _fontHover = font;
+}
+
+BaseFont *UIButton::getFontHover() {
+ return _fontHover;
+}
+
+void UIButton::setFontPress(BaseFont *font) {
+ _fontPress = font;
+}
+
+void UIButton::setImageHover(BaseSprite *sprite) {
+ _imageHover = sprite;
+}
+
+void UIButton::setImagePress(BaseSprite *sprite) {
+ _imagePress = sprite;
+}
+
+void UIButton::setTextAlign(TTextAlign align) {
+ _align = align;
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_button.h b/engines/wintermute/ui/ui_button.h
index 5db9356ef9..6452cfc4f7 100644
--- a/engines/wintermute/ui/ui_button.h
+++ b/engines/wintermute/ui/ui_button.h
@@ -37,35 +37,18 @@ namespace Wintermute {
class UIButton : public UIObject {
public:
- bool _pixelPerfect;
- bool _stayPressed;
- bool _centerImage;
- bool _oneTimePress;
- uint32 _oneTimePressTime;
+
DECLARE_PERSISTENT(UIButton, UIObject)
void press();
virtual bool display() { return display(0, 0); }
virtual bool display(int offsetX, int offsetY);
- bool _press;
- bool _hover;
+
void correctSize();
- TTextAlign _align;
- BaseSprite *_imageHover;
- BaseSprite *_imagePress;
- BaseSprite *_imageDisable;
- BaseSprite *_imageFocus;
- BaseFont *_fontDisable;
- BaseFont *_fontPress;
- BaseFont *_fontHover;
- BaseFont *_fontFocus;
- UITiledImage *_backPress;
- UITiledImage *_backHover;
- UITiledImage *_backDisable;
- UITiledImage *_backFocus;
+
UIButton(BaseGame *inGame = nullptr);
virtual ~UIButton();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
// scripting interface
@@ -73,8 +56,41 @@ public:
virtual bool scSetProperty(const char *name, ScValue *value) override;
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
virtual const char *scToString() override;
+
+
+ void setFontHover(BaseFont *font);
+ BaseFont *getFontHover();
+ void setFontPress(BaseFont *font);
+
+ void setTextAlign(TTextAlign align);
+
+ void setImageHover(BaseSprite *sprite);
+ void setImagePress(BaseSprite *sprite);
+
+private:
+ bool _pixelPerfect;
+ bool _stayPressed;
+ bool _centerImage;
+ bool _oneTimePress;
+ UITiledImage *_backPress;
+ UITiledImage *_backHover;
+ UITiledImage *_backDisable;
+ UITiledImage *_backFocus;
+ bool _press;
+ bool _hover;
+ BaseFont *_fontDisable;
+ BaseFont *_fontPress;
+ BaseFont *_fontHover;
+ BaseFont *_fontFocus;
+ BaseSprite *_imageHover;
+ BaseSprite *_imagePress;
+ BaseSprite *_imageDisable;
+ BaseSprite *_imageFocus;
+ uint32 _oneTimePressTime;
+ TTextAlign _align;
+
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_edit.cpp b/engines/wintermute/ui/ui_edit.cpp
index 91ca7326cb..1f224c79c8 100644
--- a/engines/wintermute/ui/ui_edit.cpp
+++ b/engines/wintermute/ui/ui_edit.cpp
@@ -94,7 +94,7 @@ UIEdit::~UIEdit() {
//////////////////////////////////////////////////////////////////////////
bool UIEdit::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UIEdit::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -139,7 +139,7 @@ TOKEN_DEF(EDIT)
TOKEN_DEF(CAPTION)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UIEdit::loadBuffer(byte *buffer, bool complete) {
+bool UIEdit::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(TEMPLATE)
TOKEN_TABLE(DISABLED)
@@ -165,34 +165,34 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(CAPTION)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_EDIT) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_EDIT) {
_gameRef->LOG(0, "'EDIT' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_BACK:
delete _back;
_back = new UITiledImage(_gameRef);
- if (!_back || DID_FAIL(_back->loadFile((char *)params))) {
+ if (!_back || DID_FAIL(_back->loadFile(params))) {
delete _back;
_back = nullptr;
cmd = PARSERR_GENERIC;
@@ -202,7 +202,7 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE:
delete _image;
_image = new BaseSprite(_gameRef);
- if (!_image || DID_FAIL(_image->loadFile((char *)params))) {
+ if (!_image || DID_FAIL(_image->loadFile(params))) {
delete _image;
_image = nullptr;
cmd = PARSERR_GENERIC;
@@ -213,7 +213,7 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) {
if (_font) {
_gameRef->_fontStorage->removeFont(_font);
}
- _font = _gameRef->_fontStorage->addFont((char *)params);
+ _font = _gameRef->_fontStorage->addFont(params);
if (!_font) {
cmd = PARSERR_GENERIC;
}
@@ -223,45 +223,45 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) {
if (_fontSelected) {
_gameRef->_fontStorage->removeFont(_fontSelected);
}
- _fontSelected = _gameRef->_fontStorage->addFont((char *)params);
+ _fontSelected = _gameRef->_fontStorage->addFont(params);
if (!_fontSelected) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_TEXT:
- setText((char *)params);
+ setText(params);
_gameRef->expandStringByStringTable(&_text);
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_WIDTH:
- parser.scanStr((char *)params, "%d", &_width);
+ parser.scanStr(params, "%d", &_width);
break;
case TOKEN_HEIGHT:
- parser.scanStr((char *)params, "%d", &_height);
+ parser.scanStr(params, "%d", &_height);
break;
case TOKEN_MAX_LENGTH:
- parser.scanStr((char *)params, "%d", &_maxLength);
+ parser.scanStr(params, "%d", &_maxLength);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -269,27 +269,27 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_CURSOR_BLINK_RATE:
- parser.scanStr((char *)params, "%d", &_cursorBlinkRate);
+ parser.scanStr(params, "%d", &_cursorBlinkRate);
break;
case TOKEN_FRAME_WIDTH:
- parser.scanStr((char *)params, "%d", &_frameWidth);
+ parser.scanStr(params, "%d", &_frameWidth);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PARENT_NOTIFY:
- parser.scanStr((char *)params, "%b", &_parentNotify);
+ parser.scanStr(params, "%b", &_parentNotify);
break;
case TOKEN_DISABLED:
- parser.scanStr((char *)params, "%b", &_disable);
+ parser.scanStr(params, "%b", &_disable);
break;
case TOKEN_VISIBLE:
- parser.scanStr((char *)params, "%b", &_visible);
+ parser.scanStr(params, "%b", &_visible);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -627,9 +627,9 @@ bool UIEdit::display(int offsetX, int offsetY) {
curFirst = true;
} else {
while (font->getTextWidth((byte *)_text + _scrollOffset, MAX<int32>(0, _selStart - _scrollOffset)) +
- sfont->getTextWidth((byte *)(_text + MAX<int32>(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart))
+ sfont->getTextWidth((byte *)(_text + MAX<int32>(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart))
- > _width - cursorWidth - 2 * _frameWidth) {
+ > _width - cursorWidth - 2 * _frameWidth) {
_scrollOffset++;
if (_scrollOffset >= (int)strlen(_text)) {
break;
@@ -932,14 +932,14 @@ bool UIEdit::persist(BasePersistenceManager *persistMgr) {
UIObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_cursorBlinkRate));
- persistMgr->transfer(TMEMBER(_cursorChar));
+ persistMgr->transferUint32(TMEMBER(_cursorBlinkRate));
+ persistMgr->transferCharPtr(TMEMBER(_cursorChar));
persistMgr->transferPtr(TMEMBER_PTR(_fontSelected));
- persistMgr->transfer(TMEMBER(_frameWidth));
- persistMgr->transfer(TMEMBER(_maxLength));
- persistMgr->transfer(TMEMBER(_scrollOffset));
- persistMgr->transfer(TMEMBER(_selEnd));
- persistMgr->transfer(TMEMBER(_selStart));
+ persistMgr->transferSint32(TMEMBER(_frameWidth));
+ persistMgr->transferSint32(TMEMBER(_maxLength));
+ persistMgr->transferSint32(TMEMBER(_scrollOffset));
+ persistMgr->transferSint32(TMEMBER(_selEnd));
+ persistMgr->transferSint32(TMEMBER(_selStart));
if (!persistMgr->getIsSaving()) {
_cursorVisible = false;
@@ -949,4 +949,4 @@ bool UIEdit::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_edit.h b/engines/wintermute/ui/ui_edit.h
index ac626f0f06..19ea5ecc5d 100644
--- a/engines/wintermute/ui/ui_edit.h
+++ b/engines/wintermute/ui/ui_edit.h
@@ -38,26 +38,20 @@ class BaseFont;
class UIEdit : public UIObject {
public:
DECLARE_PERSISTENT(UIEdit, UIObject)
- int32 _maxLength;
+
int insertChars(int pos, const byte *chars, int num);
int deleteChars(int start, int end);
- bool _cursorVisible;
- uint32 _lastBlinkTime;
+
virtual bool display(int offsetX, int offsetY);
virtual bool handleKeypress(Common::Event *event, bool printable = false);
- int32 _scrollOffset;
- int32 _frameWidth;
- uint32 _cursorBlinkRate;
+
void setCursorChar(const char *character);
- char *_cursorChar;
- int32 _selEnd;
- int32 _selStart;
- BaseFont *_fontSelected;
+
UIEdit(BaseGame *inGame);
virtual ~UIEdit();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
@@ -65,8 +59,19 @@ public:
virtual bool scSetProperty(const char *name, ScValue *value) override;
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
virtual const char *scToString() override;
+private:
+ uint32 _cursorBlinkRate;
+ uint32 _lastBlinkTime;
+ int32 _selEnd;
+ int32 _selStart;
+ int32 _scrollOffset;
+ int32 _frameWidth;
+ BaseFont *_fontSelected;
+ int32 _maxLength;
+ bool _cursorVisible;
+ char *_cursorChar;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_entity.cpp b/engines/wintermute/ui/ui_entity.cpp
index 1872400cdd..0dbf8df00b 100644
--- a/engines/wintermute/ui/ui_entity.cpp
+++ b/engines/wintermute/ui/ui_entity.cpp
@@ -58,7 +58,7 @@ UIEntity::~UIEntity() {
//////////////////////////////////////////////////////////////////////////
bool UIEntity::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UIEntity::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -92,7 +92,7 @@ TOKEN_DEF(SCRIPT)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UIEntity::loadBuffer(byte *buffer, bool complete) {
+bool UIEntity::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(ENTITY_CONTAINER)
TOKEN_TABLE(TEMPLATE)
@@ -106,54 +106,54 @@ bool UIEntity::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_ENTITY_CONTAINER) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_ENTITY_CONTAINER) {
_gameRef->LOG(0, "'ENTITY_CONTAINER' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_DISABLED:
- parser.scanStr((char *)params, "%b", &_disable);
+ parser.scanStr(params, "%b", &_disable);
break;
case TOKEN_VISIBLE:
- parser.scanStr((char *)params, "%b", &_visible);
+ parser.scanStr(params, "%b", &_visible);
break;
case TOKEN_ENTITY:
- if (DID_FAIL(setEntity((char *)params))) {
+ if (DID_FAIL(setEntity(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -363,4 +363,4 @@ bool UIEntity::persist(BasePersistenceManager *persistMgr) {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_entity.h b/engines/wintermute/ui/ui_entity.h
index 3bd3ec9888..63f0026412 100644
--- a/engines/wintermute/ui/ui_entity.h
+++ b/engines/wintermute/ui/ui_entity.h
@@ -39,12 +39,11 @@ public:
UIEntity(BaseGame *inGame);
virtual ~UIEntity();
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete);
+ bool loadBuffer(char *buffer, bool complete);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
virtual bool display() override { return display(0, 0); }
virtual bool display(int offsetX, int offsetY) override;
- AdEntity *_entity;
bool setEntity(const char *filename);
// scripting interface
@@ -52,8 +51,11 @@ public:
virtual bool scSetProperty(const char *name, ScValue *value) override;
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
+
+private:
+ AdEntity *_entity;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_object.cpp b/engines/wintermute/ui/ui_object.cpp
index 07efc5e4cb..c04c7cbd28 100644
--- a/engines/wintermute/ui/ui_object.cpp
+++ b/engines/wintermute/ui/ui_object.cpp
@@ -622,23 +622,23 @@ bool UIObject::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_back));
- persistMgr->transfer(TMEMBER(_canFocus));
- persistMgr->transfer(TMEMBER(_disable));
+ persistMgr->transferBool(TMEMBER(_canFocus));
+ persistMgr->transferBool(TMEMBER(_disable));
persistMgr->transferPtr(TMEMBER_PTR(_focusedWidget));
persistMgr->transferPtr(TMEMBER_PTR(_font));
- persistMgr->transfer(TMEMBER(_height));
+ persistMgr->transferSint32(TMEMBER(_height));
persistMgr->transferPtr(TMEMBER_PTR(_image));
persistMgr->transferPtr(TMEMBER_PTR(_listenerObject));
persistMgr->transferPtr(TMEMBER_PTR(_listenerParamObject));
- persistMgr->transfer(TMEMBER(_listenerParamDWORD));
+ persistMgr->transferUint32(TMEMBER(_listenerParamDWORD));
persistMgr->transferPtr(TMEMBER_PTR(_parent));
- persistMgr->transfer(TMEMBER(_parentNotify));
- persistMgr->transfer(TMEMBER(_sharedFonts));
- persistMgr->transfer(TMEMBER(_sharedImages));
- persistMgr->transfer(TMEMBER(_text));
- persistMgr->transfer(TMEMBER_INT(_type));
- persistMgr->transfer(TMEMBER(_visible));
- persistMgr->transfer(TMEMBER(_width));
+ persistMgr->transferBool(TMEMBER(_parentNotify));
+ persistMgr->transferBool(TMEMBER(_sharedFonts));
+ persistMgr->transferBool(TMEMBER(_sharedImages));
+ persistMgr->transferCharPtr(TMEMBER(_text));
+ persistMgr->transferSint32(TMEMBER_INT(_type));
+ persistMgr->transferBool(TMEMBER(_visible));
+ persistMgr->transferSint32(TMEMBER(_width));
return STATUS_OK;
}
@@ -648,4 +648,82 @@ bool UIObject::saveAsText(BaseDynamicBuffer *buffer, int indent) {
return STATUS_FAILED;
}
-} // end of namespace Wintermute
+int32 UIObject::getWidth() const {
+ return _width;
+}
+
+// Has to be non-const to allow the virtual override to work,
+// as other getHeight()-functions currently have the potential
+// of having side-effects.
+int32 UIObject::getHeight() {
+ return _height;
+}
+
+void UIObject::setWidth(int32 width) {
+ assert(width >= 0);
+ _width = width;
+}
+
+void UIObject::setHeight(int32 height) {
+ assert(height >= 0);
+ _height = height;
+}
+
+bool UIObject::isDisabled() const {
+ return _disable;
+}
+
+bool UIObject::isVisible() const {
+ return _visible;
+}
+
+void UIObject::setVisible(bool visible) {
+ _visible = visible;
+}
+
+void UIObject::setDisabled(bool disable) {
+ _disable = disable;
+}
+
+bool UIObject::hasSharedFonts() const {
+ return _sharedFonts;
+}
+
+void UIObject::setSharedFonts(bool shared) {
+ _sharedFonts = shared;
+}
+
+bool UIObject::hasSharedImages() const {
+ return _sharedImages;
+}
+
+void UIObject::setSharedImages(bool shared) {
+ _sharedImages = shared;
+}
+
+BaseSprite *UIObject::getImage() const {
+ return _image;
+}
+
+void UIObject::setImage(BaseSprite *image) {
+ _image = image;
+}
+
+bool UIObject::canFocus() const {
+ return _canFocus;
+}
+
+void UIObject::setFont(BaseFont *font) {
+ _font = font;
+}
+
+BaseFont *UIObject::getFont() {
+ return _font;
+}
+
+BaseScriptHolder *UIObject::getListener() const {
+ return _listenerObject;
+}
+
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_object.h b/engines/wintermute/ui/ui_object.h
index 935c27613c..ecbaebcee6 100644
--- a/engines/wintermute/ui/ui_object.h
+++ b/engines/wintermute/ui/ui_object.h
@@ -41,35 +41,23 @@ class UIObject : public BaseObject {
public:
bool getTotalOffset(int *offsetX, int *offsetY);
- bool _canFocus;
bool focus();
virtual bool handleMouse(TMouseEvent event, TMouseButton button);
bool isFocused();
- bool _parentNotify;
+
DECLARE_PERSISTENT(UIObject, BaseObject)
UIObject *_parent;
virtual bool display() override { return display(0, 0); }
virtual bool display(int offsetX) { return display(offsetX, 0); }
virtual bool display(int offsetX, int offsetY);
virtual void correctSize();
- bool _sharedFonts;
- bool _sharedImages;
void setText(const char *text);
- char *_text;
- BaseFont *_font;
- bool _visible;
- UITiledImage *_back;
- bool _disable;
+
UIObject(BaseGame *inGame = nullptr);
virtual ~UIObject();
- int32 _width;
- int32 _height;
- TUIObjectType _type;
- BaseSprite *_image;
void setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam);
- BaseScriptHolder *_listenerParamObject;
- uint32 _listenerParamDWORD;
- BaseScriptHolder *_listenerObject;
+ BaseScriptHolder *getListener() const;
+
UIObject *_focusedWidget;
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
@@ -78,8 +66,44 @@ public:
virtual bool scSetProperty(const char *name, ScValue *value) override;
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
virtual const char *scToString() override;
+ TUIObjectType _type;
+
+ int32 getWidth() const;
+ int32 getHeight() override;
+ void setHeight(int32 height);
+ void setWidth(int32 width);
+ bool isDisabled() const;
+ void setDisabled(bool disable);
+ bool isVisible() const;
+ void setVisible(bool visible);
+ bool hasSharedFonts() const;
+ void setSharedFonts(bool shared);
+ bool hasSharedImages() const;
+ void setSharedImages(bool shared);
+ BaseSprite *getImage() const;
+ void setImage(BaseSprite *image);
+ void setFont(BaseFont *font);
+ BaseFont *getFont();
+ bool canFocus() const;
+
+protected:
+ BaseScriptHolder *_listenerParamObject;
+ uint32 _listenerParamDWORD;
+ BaseScriptHolder *_listenerObject;
+ BaseSprite *_image;
+ BaseFont *_font;
+ bool _sharedFonts;
+ bool _sharedImages;
+ char *_text;
+ bool _visible;
+ bool _disable;
+ int32 _width;
+ int32 _height;
+ bool _canFocus;
+ bool _parentNotify;
+ UITiledImage *_back;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_text.cpp b/engines/wintermute/ui/ui_text.cpp
index 98d70b770e..b255e6e790 100644
--- a/engines/wintermute/ui/ui_text.cpp
+++ b/engines/wintermute/ui/ui_text.cpp
@@ -103,7 +103,7 @@ bool UIText::display(int offsetX, int offsetY) {
//////////////////////////////////////////////////////////////////////////
bool UIText::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UIText::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -146,7 +146,7 @@ TOKEN_DEF(PARENT_NOTIFY)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UIText::loadBuffer(byte *buffer, bool complete) {
+bool UIText::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(STATIC)
TOKEN_TABLE(TEMPLATE)
@@ -170,38 +170,38 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_STATIC) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_STATIC) {
_gameRef->LOG(0, "'STATIC' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_BACK:
delete _back;
_back = new UITiledImage(_gameRef);
- if (!_back || DID_FAIL(_back->loadFile((char *)params))) {
+ if (!_back || DID_FAIL(_back->loadFile(params))) {
delete _back;
_back = nullptr;
cmd = PARSERR_GENERIC;
@@ -211,7 +211,7 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE:
delete _image;
_image = new BaseSprite(_gameRef);
- if (!_image || DID_FAIL(_image->loadFile((char *)params))) {
+ if (!_image || DID_FAIL(_image->loadFile(params))) {
delete _image;
_image = nullptr;
cmd = PARSERR_GENERIC;
@@ -222,21 +222,21 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
if (_font) {
_gameRef->_fontStorage->removeFont(_font);
}
- _font = _gameRef->_fontStorage->addFont((char *)params);
+ _font = _gameRef->_fontStorage->addFont(params);
if (!_font) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_TEXT:
- setText((char *)params);
+ setText(params);
_gameRef->expandStringByStringTable(&_text);
break;
case TOKEN_TEXT_ALIGN:
- if (scumm_stricmp((char *)params, "left") == 0) {
+ if (scumm_stricmp(params, "left") == 0) {
_textAlign = TAL_LEFT;
- } else if (scumm_stricmp((char *)params, "right") == 0) {
+ } else if (scumm_stricmp(params, "right") == 0) {
_textAlign = TAL_RIGHT;
} else {
_textAlign = TAL_CENTER;
@@ -244,9 +244,9 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_VERTICAL_ALIGN:
- if (scumm_stricmp((char *)params, "top") == 0) {
+ if (scumm_stricmp(params, "top") == 0) {
_verticalAlign = VAL_TOP;
- } else if (scumm_stricmp((char *)params, "bottom") == 0) {
+ } else if (scumm_stricmp(params, "bottom") == 0) {
_verticalAlign = VAL_BOTTOM;
} else {
_verticalAlign = VAL_CENTER;
@@ -254,25 +254,25 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_WIDTH:
- parser.scanStr((char *)params, "%d", &_width);
+ parser.scanStr(params, "%d", &_width);
break;
case TOKEN_HEIGHT:
- parser.scanStr((char *)params, "%d", &_height);
+ parser.scanStr(params, "%d", &_height);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -280,19 +280,19 @@ bool UIText::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PARENT_NOTIFY:
- parser.scanStr((char *)params, "%b", &_parentNotify);
+ parser.scanStr(params, "%b", &_parentNotify);
break;
case TOKEN_DISABLED:
- parser.scanStr((char *)params, "%b", &_disable);
+ parser.scanStr(params, "%b", &_disable);
break;
case TOKEN_VISIBLE:
- parser.scanStr((char *)params, "%b", &_visible);
+ parser.scanStr(params, "%b", &_visible);
break;
case TOKEN_EDITOR_PROPERTY:
@@ -503,8 +503,8 @@ const char *UIText::scToString() {
bool UIText::persist(BasePersistenceManager *persistMgr) {
UIObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER_INT(_textAlign));
- persistMgr->transfer(TMEMBER_INT(_verticalAlign));
+ persistMgr->transferSint32(TMEMBER_INT(_textAlign));
+ persistMgr->transferSint32(TMEMBER_INT(_verticalAlign));
return STATUS_OK;
}
@@ -519,4 +519,4 @@ bool UIText::sizeToFit() {
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_text.h b/engines/wintermute/ui/ui_text.h
index be074755ba..c39260b228 100644
--- a/engines/wintermute/ui/ui_text.h
+++ b/engines/wintermute/ui/ui_text.h
@@ -37,15 +37,15 @@ namespace Wintermute {
class UIText : public UIObject {
private:
bool sizeToFit();
+ TTextAlign _textAlign;
+ TVerticalAlign _verticalAlign;
public:
virtual bool display(int offsetX, int offsetY);
DECLARE_PERSISTENT(UIText, UIObject)
UIText(BaseGame *inGame = nullptr);
virtual ~UIText();
- TTextAlign _textAlign;
- TVerticalAlign _verticalAlign;
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
// scripting interface
@@ -55,6 +55,6 @@ public:
virtual const char *scToString() override;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp
index abccdd6c39..e895477a36 100644
--- a/engines/wintermute/ui/ui_tiled_image.cpp
+++ b/engines/wintermute/ui/ui_tiled_image.cpp
@@ -44,15 +44,15 @@ IMPLEMENT_PERSISTENT(UITiledImage, false)
UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) {
_image = nullptr;
- BasePlatform::setRectEmpty(&_upLeft);
- BasePlatform::setRectEmpty(&_upMiddle);
- BasePlatform::setRectEmpty(&_upRight);
- BasePlatform::setRectEmpty(&_middleLeft);
- BasePlatform::setRectEmpty(&_middleMiddle);
- BasePlatform::setRectEmpty(&_middleRight);
- BasePlatform::setRectEmpty(&_downLeft);
- BasePlatform::setRectEmpty(&_downMiddle);
- BasePlatform::setRectEmpty(&_downRight);
+ _upLeft.setEmpty();
+ _upMiddle.setEmpty();
+ _upRight.setEmpty();
+ _middleLeft.setEmpty();
+ _middleMiddle.setEmpty();
+ _middleRight.setEmpty();
+ _downLeft.setEmpty();
+ _downMiddle.setEmpty();
+ _downRight.setEmpty();
}
@@ -75,8 +75,6 @@ bool UITiledImage::display(int x, int y, int width, int height) {
int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth;
int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight;
- int col, row;
-
_gameRef->_renderer->startSpriteBatch();
// top left/right
@@ -88,27 +86,24 @@ bool UITiledImage::display(int x, int y, int width, int height) {
_image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downRight);
// left/right
- int yyy = y + (_upMiddle.bottom - _upMiddle.top);
- for (row = 0; row < nuRows; row++) {
- _image->_surface->displayTrans(x, yyy, _middleLeft);
- _image->_surface->displayTrans(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight);
- yyy += tileWidth;
+ if (nuRows > 0) {
+ int yyy = y + (_upMiddle.bottom - _upMiddle.top);
+ _image->_surface->displayTiled(x, yyy, _middleLeft, 1, nuRows);
+ _image->_surface->displayTiled(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight, 1, nuRows);
}
// top/bottom
- int xxx = x + (_upLeft.right - _upLeft.left);
- for (col = 0; col < nuColumns; col++) {
- _image->_surface->displayTrans(xxx, y, _upMiddle);
- _image->_surface->displayTrans(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle);
- xxx += tileWidth;
+ if (nuColumns > 0) {
+ int xxx = x + (_upLeft.right - _upLeft.left);
+ _image->_surface->displayTiled(xxx, y, _upMiddle, nuColumns, 1);
+ _image->_surface->displayTiled(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle, nuColumns, 1);
}
// tiles
if (nuRows > 0 && nuColumns > 0) {
- yyy = y + (_upMiddle.bottom - _upMiddle.top);
- xxx = x + (_upLeft.right - _upLeft.left);
- _image->_surface->displayTrans(xxx, yyy, _middleMiddle);
- _image->_surface->repeatLastDisplayOp(tileWidth, tileWidth, nuColumns, nuRows);
+ int yyy = y + (_upMiddle.bottom - _upMiddle.top);
+ int xxx = x + (_upLeft.right - _upLeft.left);
+ _image->_surface->displayTiled(xxx, yyy, _middleMiddle, nuColumns, nuRows);
}
_gameRef->_renderer->endSpriteBatch();
@@ -119,7 +114,7 @@ bool UITiledImage::display(int x, int y, int width, int height) {
//////////////////////////////////////////////////////////////////////////
bool UITiledImage::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UITiledImage::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -158,7 +153,7 @@ TOKEN_DEF(HORIZONTAL_TILES)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
+bool UITiledImage::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(TILED_IMAGE)
TOKEN_TABLE(TEMPLATE)
@@ -177,7 +172,7 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd;
BaseParser parser;
bool hTiles = false, vTiles = false;
@@ -185,17 +180,17 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
int v1 = 0, v2 = 0, v3 = 0;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_TILED_IMAGE) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_TILED_IMAGE) {
_gameRef->LOG(0, "'TILED_IMAGE' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ while ((cmd = parser.getCommand(&buffer, commands, &params)) > 0) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
@@ -203,7 +198,7 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE:
delete _image;
_image = new BaseSubFrame(_gameRef);
- if (!_image || DID_FAIL(_image->setSurface((char *)params))) {
+ if (!_image || DID_FAIL(_image->setSurface(params))) {
delete _image;
_image = nullptr;
cmd = PARSERR_GENERIC;
@@ -211,48 +206,48 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_UP_LEFT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom);
break;
case TOKEN_UP_RIGHT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom);
break;
case TOKEN_UP_MIDDLE:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom);
break;
case TOKEN_DOWN_LEFT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom);
break;
case TOKEN_DOWN_RIGHT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom);
break;
case TOKEN_DOWN_MIDDLE:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom);
break;
case TOKEN_MIDDLE_LEFT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom);
break;
case TOKEN_MIDDLE_RIGHT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom);
break;
case TOKEN_MIDDLE_MIDDLE:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom);
break;
case TOKEN_HORIZONTAL_TILES:
- parser.scanStr((char *)params, "%d,%d,%d", &h1, &h2, &h3);
+ parser.scanStr(params, "%d,%d,%d", &h1, &h2, &h3);
hTiles = true;
break;
case TOKEN_VERTICAL_TILES:
- parser.scanStr((char *)params, "%d,%d,%d", &v1, &v2, &v3);
+ parser.scanStr(params, "%d,%d,%d", &v1, &v2, &v3);
vTiles = true;
break;
@@ -272,19 +267,19 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
if (vTiles && hTiles) {
// up row
- BasePlatform::setRect(&_upLeft, 0, 0, h1, v1);
- BasePlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1);
- BasePlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1);
+ _upLeft.setRect(0, 0, h1, v1);
+ _upMiddle.setRect(h1, 0, h1 + h2, v1);
+ _upRight.setRect(h1 + h2, 0, h1 + h2 + h3, v1);
// middle row
- BasePlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2);
- BasePlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2);
- BasePlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2);
+ _middleLeft.setRect(0, v1, h1, v1 + v2);
+ _middleMiddle.setRect(h1, v1, h1 + h2, v1 + v2);
+ _middleRight.setRect(h1 + h2, v1, h1 + h2 + h3, v1 + v2);
// down row
- BasePlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3);
- BasePlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3);
- BasePlatform::setRect(&_downRight, h1 + h2, v1 + v2, h1 + h2 + h3, v1 + v2 + v3);
+ _downLeft.setRect(0, v1 + v2, h1, v1 + v2 + v3);
+ _downMiddle.setRect(h1, v1 + v2, h1 + h2, v1 + v2 + v3);
+ _downRight.setRect(h1 + h2, v1 + v2, h1 + h2 + h3, v1 + v2 + v3);
}
// default
@@ -292,34 +287,34 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) {
int width = _image->_surface->getWidth() / 3;
int height = _image->_surface->getHeight() / 3;
- if (BasePlatform::isRectEmpty(&_upLeft)) {
- BasePlatform::setRect(&_upLeft, 0, 0, width, height);
+ if (_upLeft.isRectEmpty()) {
+ _upLeft.setRect(0, 0, width, height);
}
- if (BasePlatform::isRectEmpty(&_upMiddle)) {
- BasePlatform::setRect(&_upMiddle, width, 0, 2 * width, height);
+ if (_upMiddle.isRectEmpty()) {
+ _upMiddle.setRect(width, 0, 2 * width, height);
}
- if (BasePlatform::isRectEmpty(&_upRight)) {
- BasePlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height);
+ if (_upRight.isRectEmpty()) {
+ _upRight.setRect(2 * width, 0, 3 * width, height);
}
- if (BasePlatform::isRectEmpty(&_middleLeft)) {
- BasePlatform::setRect(&_middleLeft, 0, height, width, 2 * height);
+ if (_middleLeft.isRectEmpty()) {
+ _middleLeft.setRect(0, height, width, 2 * height);
}
- if (BasePlatform::isRectEmpty(&_middleMiddle)) {
- BasePlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height);
+ if (_middleMiddle.isRectEmpty()) {
+ _middleMiddle.setRect(width, height, 2 * width, 2 * height);
}
- if (BasePlatform::isRectEmpty(&_middleRight)) {
- BasePlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height);
+ if (_middleRight.isRectEmpty()) {
+ _middleRight.setRect(2 * width, height, 3 * width, 2 * height);
}
- if (BasePlatform::isRectEmpty(&_downLeft)) {
- BasePlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height);
+ if (_downLeft.isRectEmpty()) {
+ _downLeft.setRect(0, 2 * height, width, 3 * height);
}
- if (BasePlatform::isRectEmpty(&_downMiddle)) {
- BasePlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height);
+ if (_downMiddle.isRectEmpty()) {
+ _downMiddle.setRect(width, 2 * height, 2 * width, 3 * height);
}
- if (BasePlatform::isRectEmpty(&_downRight)) {
- BasePlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height);
+ if (_downRight.isRectEmpty()) {
+ _downRight.setRect(2 * width, 2 * height, 3 * width, 3 * height);
}
}
@@ -374,18 +369,18 @@ void UITiledImage::correctSize(int32 *width, int32 *height) {
bool UITiledImage::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_downLeft));
- persistMgr->transfer(TMEMBER(_downMiddle));
- persistMgr->transfer(TMEMBER(_downRight));
+ persistMgr->transferRect32(TMEMBER(_downLeft));
+ persistMgr->transferRect32(TMEMBER(_downMiddle));
+ persistMgr->transferRect32(TMEMBER(_downRight));
persistMgr->transferPtr(TMEMBER_PTR(_image));
- persistMgr->transfer(TMEMBER(_middleLeft));
- persistMgr->transfer(TMEMBER(_middleMiddle));
- persistMgr->transfer(TMEMBER(_middleRight));
- persistMgr->transfer(TMEMBER(_upLeft));
- persistMgr->transfer(TMEMBER(_upMiddle));
- persistMgr->transfer(TMEMBER(_upRight));
+ persistMgr->transferRect32(TMEMBER(_middleLeft));
+ persistMgr->transferRect32(TMEMBER(_middleMiddle));
+ persistMgr->transferRect32(TMEMBER(_middleRight));
+ persistMgr->transferRect32(TMEMBER(_upLeft));
+ persistMgr->transferRect32(TMEMBER(_upMiddle));
+ persistMgr->transferRect32(TMEMBER(_upRight));
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_tiled_image.h b/engines/wintermute/ui/ui_tiled_image.h
index a6cd22d53d..fa92c46781 100644
--- a/engines/wintermute/ui/ui_tiled_image.h
+++ b/engines/wintermute/ui/ui_tiled_image.h
@@ -36,11 +36,13 @@
namespace Wintermute {
class BaseSubFrame;
class UITiledImage : public BaseObject {
+ using Wintermute::BaseObject::display;
+
public:
DECLARE_PERSISTENT(UITiledImage, BaseObject)
void correctSize(int32 *width, int32 *height);
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
+ bool loadBuffer(char *buffer, bool complete = true);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
bool display(int x, int y, int width, int height);
@@ -59,6 +61,6 @@ private:
Rect32 _downRight;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp
index 2ce9f68605..842bf700b5 100644
--- a/engines/wintermute/ui/ui_window.cpp
+++ b/engines/wintermute/ui/ui_window.cpp
@@ -54,8 +54,8 @@ IMPLEMENT_PERSISTENT(UIWindow, false)
//////////////////////////////////////////////////////////////////////////
UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) {
- BasePlatform::setRectEmpty(&_titleRect);
- BasePlatform::setRectEmpty(&_dragRect);
+ _titleRect.setEmpty();
+ _dragRect.setEmpty();
_titleAlign = TAL_LEFT;
_transparent = false;
@@ -141,8 +141,8 @@ bool UIWindow::display(int offsetX, int offsetY) {
}
if (_shieldButton) {
_shieldButton->_posX = _shieldButton->_posY = 0;
- _shieldButton->_width = _gameRef->_renderer->getWidth();
- _shieldButton->_height = _gameRef->_renderer->getHeight();
+ _shieldButton->setWidth(_gameRef->_renderer->getWidth());
+ _shieldButton->setHeight(_gameRef->_renderer->getHeight());
_shieldButton->display();
}
@@ -170,7 +170,7 @@ bool UIWindow::display(int offsetX, int offsetY) {
_dragFrom.y = _gameRef->_mousePos.y;
}
- if (!_focusedWidget || (!_focusedWidget->_canFocus || _focusedWidget->_disable || !_focusedWidget->_visible)) {
+ if (!_focusedWidget || (!_focusedWidget->canFocus() || _focusedWidget->isDisabled() || !_focusedWidget->isVisible())) {
moveFocus();
}
@@ -213,7 +213,7 @@ bool UIWindow::display(int offsetX, int offsetY) {
image->draw(_posX + offsetX, _posY + offsetY, _transparent ? nullptr : this);
}
- if (!BasePlatform::isRectEmpty(&_titleRect) && font && _text) {
+ if (!_titleRect.isRectEmpty() && font && _text) {
font->drawText((byte *)_text, _posX + offsetX + _titleRect.left, _posY + offsetY + _titleRect.top, _titleRect.right - _titleRect.left, _titleAlign, _titleRect.bottom - _titleRect.top);
}
@@ -239,7 +239,7 @@ bool UIWindow::display(int offsetX, int offsetY) {
//////////////////////////////////////////////////////////////////////////
bool UIWindow::loadFile(const char *filename) {
- byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == nullptr) {
_gameRef->LOG(0, "UIWindow::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
@@ -298,7 +298,7 @@ TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF(EDIT)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
-bool UIWindow::loadBuffer(byte *buffer, bool complete) {
+bool UIWindow::loadBuffer(char *buffer, bool complete) {
TOKEN_TABLE_START(commands)
TOKEN_TABLE(WINDOW)
TOKEN_TABLE(ALPHA_COLOR)
@@ -338,7 +338,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(EDIT)
TOKEN_TABLE_END
- byte *params;
+ char *params;
int cmd = 2;
BaseParser parser;
@@ -346,33 +346,33 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
int ar = 0, ag = 0, ab = 0, alpha = 0;
if (complete) {
- if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_WINDOW) {
+ if (parser.getCommand(&buffer, commands, &params) != TOKEN_WINDOW) {
_gameRef->LOG(0, "'WINDOW' keyword expected.");
return STATUS_FAILED;
}
buffer = params;
}
- while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) >= PARSERR_TOKENNOTFOUND) {
+ while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.getCommand(&buffer, commands, &params)) >= PARSERR_TOKENNOTFOUND) {
switch (cmd) {
case TOKEN_TEMPLATE:
- if (DID_FAIL(loadFile((char *)params))) {
+ if (DID_FAIL(loadFile(params))) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_NAME:
- setName((char *)params);
+ setName(params);
break;
case TOKEN_CAPTION:
- setCaption((char *)params);
+ setCaption(params);
break;
case TOKEN_BACK:
delete _back;
_back = new UITiledImage(_gameRef);
- if (!_back || DID_FAIL(_back->loadFile((char *)params))) {
+ if (!_back || DID_FAIL(_back->loadFile(params))) {
delete _back;
_back = nullptr;
cmd = PARSERR_GENERIC;
@@ -382,7 +382,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
case TOKEN_BACK_INACTIVE:
delete _backInactive;
_backInactive = new UITiledImage(_gameRef);
- if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) {
+ if (!_backInactive || DID_FAIL(_backInactive->loadFile(params))) {
delete _backInactive;
_backInactive = nullptr;
cmd = PARSERR_GENERIC;
@@ -392,7 +392,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
case TOKEN_IMAGE:
delete _image;
_image = new BaseSprite(_gameRef);
- if (!_image || DID_FAIL(_image->loadFile((char *)params))) {
+ if (!_image || DID_FAIL(_image->loadFile(params))) {
delete _image;
_image = nullptr;
cmd = PARSERR_GENERIC;
@@ -400,9 +400,9 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_IMAGE_INACTIVE:
- delete _imageInactive,
- _imageInactive = new BaseSprite(_gameRef);
- if (!_imageInactive || DID_FAIL(_imageInactive->loadFile((char *)params))) {
+ delete _imageInactive;
+ _imageInactive = new BaseSprite(_gameRef);
+ if (!_imageInactive || DID_FAIL(_imageInactive->loadFile(params))) {
delete _imageInactive;
_imageInactive = nullptr;
cmd = PARSERR_GENERIC;
@@ -413,7 +413,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
if (_font) {
_gameRef->_fontStorage->removeFont(_font);
}
- _font = _gameRef->_fontStorage->addFont((char *)params);
+ _font = _gameRef->_fontStorage->addFont(params);
if (!_font) {
cmd = PARSERR_GENERIC;
}
@@ -423,21 +423,21 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
if (_fontInactive) {
_gameRef->_fontStorage->removeFont(_fontInactive);
}
- _fontInactive = _gameRef->_fontStorage->addFont((char *)params);
+ _fontInactive = _gameRef->_fontStorage->addFont(params);
if (!_fontInactive) {
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_TITLE:
- setText((char *)params);
+ setText(params);
_gameRef->expandStringByStringTable(&_text);
break;
case TOKEN_TITLE_ALIGN:
- if (scumm_stricmp((char *)params, "left") == 0) {
+ if (scumm_stricmp(params, "left") == 0) {
_titleAlign = TAL_LEFT;
- } else if (scumm_stricmp((char *)params, "right") == 0) {
+ } else if (scumm_stricmp(params, "right") == 0) {
_titleAlign = TAL_RIGHT;
} else {
_titleAlign = TAL_CENTER;
@@ -445,33 +445,33 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_TITLE_RECT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_titleRect.left, &_titleRect.top, &_titleRect.right, &_titleRect.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_titleRect.left, &_titleRect.top, &_titleRect.right, &_titleRect.bottom);
break;
case TOKEN_DRAG_RECT:
- parser.scanStr((char *)params, "%d,%d,%d,%d", &_dragRect.left, &_dragRect.top, &_dragRect.right, &_dragRect.bottom);
+ parser.scanStr(params, "%d,%d,%d,%d", &_dragRect.left, &_dragRect.top, &_dragRect.right, &_dragRect.bottom);
break;
case TOKEN_X:
- parser.scanStr((char *)params, "%d", &_posX);
+ parser.scanStr(params, "%d", &_posX);
break;
case TOKEN_Y:
- parser.scanStr((char *)params, "%d", &_posY);
+ parser.scanStr(params, "%d", &_posY);
break;
case TOKEN_WIDTH:
- parser.scanStr((char *)params, "%d", &_width);
+ parser.scanStr(params, "%d", &_width);
break;
case TOKEN_HEIGHT:
- parser.scanStr((char *)params, "%d", &_height);
+ parser.scanStr(params, "%d", &_height);
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
- if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
delete _cursor;
_cursor = nullptr;
cmd = PARSERR_GENERIC;
@@ -532,48 +532,48 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
case TOKEN_TRANSPARENT:
- parser.scanStr((char *)params, "%b", &_transparent);
+ parser.scanStr(params, "%b", &_transparent);
break;
case TOKEN_SCRIPT:
- addScript((char *)params);
+ addScript(params);
break;
case TOKEN_PARENT_NOTIFY:
- parser.scanStr((char *)params, "%b", &_parentNotify);
+ parser.scanStr(params, "%b", &_parentNotify);
break;
case TOKEN_PAUSE_MUSIC:
- parser.scanStr((char *)params, "%b", &_pauseMusic);
+ parser.scanStr(params, "%b", &_pauseMusic);
break;
case TOKEN_DISABLED:
- parser.scanStr((char *)params, "%b", &_disable);
+ parser.scanStr(params, "%b", &_disable);
break;
case TOKEN_VISIBLE:
- parser.scanStr((char *)params, "%b", &_visible);
+ parser.scanStr(params, "%b", &_visible);
break;
case TOKEN_MENU:
- parser.scanStr((char *)params, "%b", &_isMenu);
+ parser.scanStr(params, "%b", &_isMenu);
break;
case TOKEN_IN_GAME:
- parser.scanStr((char *)params, "%b", &_inGame);
+ parser.scanStr(params, "%b", &_inGame);
break;
case TOKEN_CLIP_CONTENTS:
- parser.scanStr((char *)params, "%b", &_clipContents);
+ parser.scanStr(params, "%b", &_clipContents);
break;
case TOKEN_FADE_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &fadeR, &fadeG, &fadeB);
+ parser.scanStr(params, "%d,%d,%d", &fadeR, &fadeG, &fadeB);
_fadeBackground = true;
break;
case TOKEN_FADE_ALPHA:
- parser.scanStr((char *)params, "%d", &fadeA);
+ parser.scanStr(params, "%d", &fadeA);
_fadeBackground = true;
break;
@@ -582,16 +582,16 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) {
break;
case TOKEN_ALPHA_COLOR:
- parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
break;
case TOKEN_ALPHA:
- parser.scanStr((char *)params, "%d", &alpha);
+ parser.scanStr(params, "%d", &alpha);
break;
default:
- if (DID_FAIL(_gameRef->windowLoadHook(this, (char **)&buffer, (char **)params))) {
+ if (DID_FAIL(_gameRef->windowLoadHook(this, &buffer, &params))) {
cmd = PARSERR_GENERIC;
}
}
@@ -676,11 +676,11 @@ bool UIWindow::saveAsText(BaseDynamicBuffer *buffer, int indent) {
error("UIWindow::SaveAsText - Unhandled enum-value NUM_TEXT_ALIGN");
}
- if (!BasePlatform::isRectEmpty(&_titleRect)) {
+ if (!_titleRect.isRectEmpty()) {
buffer->putTextIndent(indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom);
}
- if (!BasePlatform::isRectEmpty(&_dragRect)) {
+ if (!_dragRect.isRectEmpty()) {
buffer->putTextIndent(indent + 2, "DRAG_RECT { %d, %d, %d, %d }\n", _dragRect.left, _dragRect.top, _dragRect.right, _dragRect.bottom);
}
@@ -737,7 +737,7 @@ bool UIWindow::saveAsText(BaseDynamicBuffer *buffer, int indent) {
bool UIWindow::enableWidget(const char *name, bool enable) {
for (uint32 i = 0; i < _widgets.size(); i++) {
if (scumm_stricmp(_widgets[i]->getName(), name) == 0) {
- _widgets[i]->_disable = !enable;
+ _widgets[i]->setDisabled(!enable);
}
}
return STATUS_OK;
@@ -748,7 +748,7 @@ bool UIWindow::enableWidget(const char *name, bool enable) {
bool UIWindow::showWidget(const char *name, bool visible) {
for (uint32 i = 0; i < _widgets.size(); i++) {
if (scumm_stricmp(_widgets[i]->getName(), name) == 0) {
- _widgets[i]->_visible = visible;
+ _widgets[i]->setVisible(visible);
}
}
return STATUS_OK;
@@ -1227,7 +1227,7 @@ bool UIWindow::handleMouse(TMouseEvent event, TMouseButton button) {
bool res = UIObject::handleMouse(event, button);
// handle window dragging
- if (!BasePlatform::isRectEmpty(&_dragRect)) {
+ if (!_dragRect.isRectEmpty()) {
// start drag
if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) {
Rect32 dragRect = _dragRect;
@@ -1258,24 +1258,24 @@ bool UIWindow::persist(BasePersistenceManager *persistMgr) {
UIObject::persist(persistMgr);
persistMgr->transferPtr(TMEMBER_PTR(_backInactive));
- persistMgr->transfer(TMEMBER(_clipContents));
- persistMgr->transfer(TMEMBER(_dragFrom));
- persistMgr->transfer(TMEMBER(_dragging));
- persistMgr->transfer(TMEMBER(_dragRect));
- persistMgr->transfer(TMEMBER(_fadeBackground));
- persistMgr->transfer(TMEMBER(_fadeColor));
+ persistMgr->transferBool(TMEMBER(_clipContents));
+ persistMgr->transferPoint32(TMEMBER(_dragFrom));
+ persistMgr->transferBool(TMEMBER(_dragging));
+ persistMgr->transferRect32(TMEMBER(_dragRect));
+ persistMgr->transferBool(TMEMBER(_fadeBackground));
+ persistMgr->transferUint32(TMEMBER(_fadeColor));
persistMgr->transferPtr(TMEMBER_PTR(_fontInactive));
persistMgr->transferPtr(TMEMBER_PTR(_imageInactive));
- persistMgr->transfer(TMEMBER(_inGame));
- persistMgr->transfer(TMEMBER(_isMenu));
- persistMgr->transfer(TMEMBER_INT(_mode));
+ persistMgr->transferBool(TMEMBER(_inGame));
+ persistMgr->transferBool(TMEMBER(_isMenu));
+ persistMgr->transferSint32(TMEMBER_INT(_mode));
persistMgr->transferPtr(TMEMBER_PTR(_shieldButton));
persistMgr->transferPtr(TMEMBER_PTR(_shieldWindow));
- persistMgr->transfer(TMEMBER_INT(_titleAlign));
- persistMgr->transfer(TMEMBER(_titleRect));
- persistMgr->transfer(TMEMBER(_transparent));
+ persistMgr->transferSint32(TMEMBER_INT(_titleAlign));
+ persistMgr->transferRect32(TMEMBER(_titleRect));
+ persistMgr->transferBool(TMEMBER(_transparent));
persistMgr->transferPtr(TMEMBER_PTR(_viewport));
- persistMgr->transfer(TMEMBER(_pauseMusic));
+ persistMgr->transferBool(TMEMBER(_pauseMusic));
_widgets.persist(persistMgr);
@@ -1309,7 +1309,7 @@ bool UIWindow::moveFocus(bool forward) {
bool done = false;
while (numTries <= (int32)_widgets.size()) {
- if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) {
+ if (_widgets[i] != _focusedWidget && _widgets[i]->canFocus() && _widgets[i]->isVisible() && !_widgets[i]->isDisabled()) {
_focusedWidget = _widgets[i];
done = true;
break;
@@ -1419,7 +1419,7 @@ void UIWindow::makeFreezable(bool freezable) {
bool UIWindow::getWindowObjects(BaseArray<UIObject *> &objects, bool interactiveOnly) {
for (uint32 i = 0; i < _widgets.size(); i++) {
UIObject *control = _widgets[i];
- if (control->_disable && interactiveOnly) {
+ if (control->isDisabled() && interactiveOnly) {
continue;
}
@@ -1442,4 +1442,14 @@ bool UIWindow::getWindowObjects(BaseArray<UIObject *> &objects, bool interactive
return STATUS_OK;
}
-} // end of namespace Wintermute
+bool UIWindow::getInGame() const {
+ return _inGame;
+}
+
+TWindowMode UIWindow::getMode() const {
+ return _mode;
+}
+
+
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/ui/ui_window.h b/engines/wintermute/ui/ui_window.h
index 70799cea25..6b4d970581 100644
--- a/engines/wintermute/ui/ui_window.h
+++ b/engines/wintermute/ui/ui_window.h
@@ -38,47 +38,32 @@ namespace Wintermute {
class UIButton;
class BaseViewport;
class UIWindow : public UIObject {
- uint32 _fadeColor;
public:
bool getWindowObjects(BaseArray<UIObject *> &Objects, bool InteractiveOnly);
- bool _pauseMusic;
void cleanup();
virtual void makeFreezable(bool freezable);
- BaseViewport *_viewport;
- bool _clipContents;
- bool _inGame;
- bool _isMenu;
- bool _fadeBackground;
virtual bool handleMouseWheel(int delta);
- UIWindow *_shieldWindow;
- UIButton *_shieldButton;
+
bool close();
bool goSystemExclusive();
bool goExclusive();
- TWindowMode _mode;
bool moveFocus(bool forward = true);
virtual bool handleMouse(TMouseEvent Event, TMouseButton Button);
- Point32 _dragFrom;
- bool _dragging;
DECLARE_PERSISTENT(UIWindow, UIObject)
- bool _transparent;
bool showWidget(const char *name, bool visible = true);
bool enableWidget(const char *name, bool enable = true);
- Rect32 _titleRect;
- Rect32 _dragRect;
+
virtual bool display(int offsetX = 0, int offsetY = 0) override;
UIWindow(BaseGame *inGame);
virtual ~UIWindow();
virtual bool handleKeypress(Common::Event *event, bool printable = false) override;
BaseArray<UIObject *> _widgets;
- TTextAlign _titleAlign;
+
bool loadFile(const char *filename);
- bool loadBuffer(byte *buffer, bool complete = true);
- UITiledImage *_backInactive;
- BaseFont *_fontInactive;
- BaseSprite *_imageInactive;
+ bool loadBuffer(char *buffer, bool complete = true);
+
virtual bool listen(BaseScriptHolder *param1, uint32 param2);
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
@@ -87,8 +72,32 @@ public:
virtual bool scSetProperty(const char *name, ScValue *value) override;
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
virtual const char *scToString();
+
+ bool getInGame() const;
+ TWindowMode getMode() const;
+
+private:
+ bool _pauseMusic;
+ BaseViewport *_viewport;
+ bool _clipContents;
+ bool _inGame;
+ bool _isMenu;
+ bool _fadeBackground;
+ TWindowMode _mode;
+ Point32 _dragFrom;
+ bool _dragging;
+ bool _transparent;
+ uint32 _fadeColor;
+ UIWindow *_shieldWindow;
+ UIButton *_shieldButton;
+ Rect32 _titleRect;
+ Rect32 _dragRect;
+ UITiledImage *_backInactive;
+ BaseFont *_fontInactive;
+ BaseSprite *_imageInactive;
+ TTextAlign _titleAlign;
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/utils/crc.cpp b/engines/wintermute/utils/crc.cpp
index e7ec45511b..a9781500fa 100644
--- a/engines/wintermute/utils/crc.cpp
+++ b/engines/wintermute/utils/crc.cpp
@@ -234,4 +234,4 @@ crc crc_finalize(crc remainder) {
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/utils/path_util.cpp b/engines/wintermute/utils/path_util.cpp
index 298f0c268f..ee8b298562 100644
--- a/engines/wintermute/utils/path_util.cpp
+++ b/engines/wintermute/utils/path_util.cpp
@@ -98,4 +98,4 @@ AnsiString PathUtil::getExtension(const AnsiString &path) {
return Common::lastPathComponent(path, '.');
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/utils/path_util.h b/engines/wintermute/utils/path_util.h
index 7358c2aba0..2c7dfa99d1 100644
--- a/engines/wintermute/utils/path_util.h
+++ b/engines/wintermute/utils/path_util.h
@@ -44,6 +44,6 @@ public:
static AnsiString getExtension(const AnsiString &path);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp
index 9fffad85cd..702dd04c27 100644
--- a/engines/wintermute/utils/string_util.cpp
+++ b/engines/wintermute/utils/string_util.cpp
@@ -50,147 +50,94 @@ bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) {
//////////////////////////////////////////////////////////////////////////
WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) {
- error("StringUtil::Utf8ToWide - WideString not supported yet");
- /* size_t WideSize = Utf8Str.size();
-
- if (sizeof(wchar_t) == 2) {
- wchar_t *WideStringNative = new wchar_t[WideSize + 1];
-
- const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
- const UTF8 *SourceEnd = SourceStart + WideSize;
-
- UTF16 *TargetStart = reinterpret_cast<UTF16 *>(WideStringNative);
- UTF16 *TargetEnd = TargetStart + WideSize + 1;
-
- ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
- if (res != conversionOK) {
- delete[] WideStringNative;
- return L"";
- }
- *TargetStart = 0;
- WideString ResultString(WideStringNative);
- delete[] WideStringNative;
-
- return ResultString;
- } else if (sizeof(wchar_t) == 4) {
- wchar_t *WideStringNative = new wchar_t[WideSize + 1];
-
- const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
- const UTF8 *SourceEnd = SourceStart + WideSize;
-
- UTF32 *TargetStart = reinterpret_cast<UTF32 *>(WideStringNative);
- UTF32 *TargetEnd = TargetStart + WideSize;
-
- ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
- if (res != conversionOK) {
- delete[] WideStringNative;
- return L"";
- }
- *TargetStart = 0;
- WideString ResultString(WideStringNative);
- delete[] WideStringNative;
-
- return ResultString;
- } else {
- return L"";
- }*/
- return "";
+ size_t wideSize = Utf8Str.size();
+
+ uint32 *wideStringNative = new uint32[wideSize + 1];
+
+ const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
+ const UTF8 *sourceEnd = sourceStart + wideSize;
+
+ UTF32 *targetStart = reinterpret_cast<UTF32 *>(wideStringNative);
+ UTF32 *targetEnd = targetStart + wideSize;
+
+ ConversionResult res = ConvertUTF8toUTF32(&sourceStart, sourceEnd, &targetStart, targetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete[] wideStringNative;
+ return WideString();
+ }
+ *targetStart = 0;
+ WideString resultString(wideStringNative);
+ delete[] wideStringNative;
+ return resultString;
}
//////////////////////////////////////////////////////////////////////////
Utf8String StringUtil::wideToUtf8(const WideString &WideStr) {
- error("StringUtil::wideToUtf8 - Widestring not supported yet");
- /* size_t WideSize = WideStr.length();
-
- if (sizeof(wchar_t) == 2) {
- size_t utf8Size = 3 * WideSize + 1;
- char *utf8StringNative = new char[Utf8Size];
-
- const UTF16 *SourceStart = reinterpret_cast<const UTF16 *>(WideStr.c_str());
- const UTF16 *SourceEnd = SourceStart + WideSize;
-
- UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
- UTF8 *TargetEnd = TargetStart + Utf8Size;
-
- ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
- if (res != conversionOK) {
- delete[] Utf8StringNative;
- return (Utf8String)"";
- }
- *TargetStart = 0;
- Utf8String ResultString(Utf8StringNative);
- delete[] Utf8StringNative;
- return ResultString;
- } else if (sizeof(wchar_t) == 4) {
- size_t utf8Size = 4 * WideSize + 1;
- char *utf8StringNative = new char[Utf8Size];
-
- const UTF32 *SourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
- const UTF32 *SourceEnd = SourceStart + WideSize;
-
- UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
- UTF8 *TargetEnd = TargetStart + Utf8Size;
-
- ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
- if (res != conversionOK) {
- delete[] Utf8StringNative;
- return (Utf8String)"";
- }
- *TargetStart = 0;
- Utf8String ResultString(Utf8StringNative);
- delete[] Utf8StringNative;
- return ResultString;
- } else {
- return (Utf8String)"";
- }*/
- return "";
-}
+ size_t wideSize = WideStr.size();
-// Currently this only does Ansi->ISO 8859, and only for carets.
-char simpleAnsiToWide(const AnsiString &str, uint32 &offset) {
- byte c = str[offset];
+ size_t utf8Size = 4 * wideSize + 1;
+ char *utf8StringNative = new char[utf8Size];
- if (c == 146) {
- offset++;
- return 39; // Replace right-quote with apostrophe
- } else {
- offset++;
- return c;
+ const UTF32 *sourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
+ const UTF32 *sourceEnd = sourceStart + wideSize;
+
+ UTF8 *targetStart = reinterpret_cast<UTF8 *>(utf8StringNative);
+ UTF8 *targetEnd = targetStart + utf8Size;
+
+ ConversionResult res = ConvertUTF32toUTF8(&sourceStart, sourceEnd, &targetStart, targetEnd, strictConversion);
+ if (res != conversionOK) {
+ delete[] utf8StringNative;
+ return Utf8String();
}
+ *targetStart = 0;
+ Utf8String resultString(utf8StringNative);
+ delete[] utf8StringNative;
+ return resultString;
}
//////////////////////////////////////////////////////////////////////////
WideString StringUtil::ansiToWide(const AnsiString &str) {
- // TODO: This function gets called a lot, so warnings like these drown out the usefull information
- Common::String converted = "";
- uint32 index = 0;
- while (index != str.size()) {
- converted += simpleAnsiToWide(str, index);
+ WideString result;
+ for (AnsiString::const_iterator i = str.begin(), end = str.end(); i != end; ++i) {
+ const byte c = *i;
+ if (c < 0x80 || c >= 0xA0) {
+ result += c;
+ } else {
+ uint32 utf32 = _ansiToUTF32[c - 0x80];
+ if (utf32) {
+ result += utf32;
+ } else {
+ // It's an invalid CP1252 character...
+ }
+ }
}
- // using default os locale!
-
- /* setlocale(LC_CTYPE, "");
- size_t wideSize = mbstowcs(NULL, str.c_str(), 0) + 1;
- wchar_t *wstr = new wchar_t[WideSize];
- mbstowcs(wstr, str.c_str(), WideSize);
- WideString ResultString(wstr);
- delete[] wstr;
- return ResultString;*/
- return WideString(converted);
+ return result;
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::wideToAnsi(const WideString &wstr) {
- // using default os locale!
- // TODO: This function gets called a lot, so warnings like these drown out the usefull information
- /* setlocale(LC_CTYPE, "");
- size_t wideSize = wcstombs(NULL, wstr.c_str(), 0) + 1;
- char *str = new char[WideSize];
- wcstombs(str, wstr.c_str(), WideSize);
- AnsiString ResultString(str);
- delete[] str;
- return ResultString;*/
- return AnsiString(wstr);
+ AnsiString result;
+ for (WideString::const_iterator i = wstr.begin(), end = wstr.end(); i != end; ++i) {
+ const uint32 c = *i;
+ if (c < 0x80 || (c >= 0xA0 && c <= 0xFF)) {
+ result += c;
+ } else {
+ uint32 ansi = 0xFFFFFFFF;
+ for (uint j = 0; j < ARRAYSIZE(_ansiToUTF32); ++j) {
+ if (_ansiToUTF32[j] == c) {
+ ansi = j + 0x80;
+ break;
+ }
+ }
+
+ if (ansi != 0xFFFFFFFF) {
+ result += ansi;
+ } else {
+ // There's no valid CP1252 code for this character...
+ }
+ }
+ }
+ return result;
}
//////////////////////////////////////////////////////////////////////////
@@ -204,12 +151,7 @@ bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) {
//////////////////////////////////////////////////////////////////////////
int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
- const char *index = strstr(str.c_str(), toFind.c_str());
- if (index == nullptr) {
- return -1;
- } else {
- return index - str.c_str();
- }
+ return str.find(toFind, startFrom);
}
Common::String StringUtil::encodeSetting(const Common::String &str) {
@@ -230,5 +172,10 @@ AnsiString StringUtil::toString(int val) {
return Common::String::format("%d", val);
}
+// Mapping of CP1252 characters 0x80...0x9F into UTF-32
+uint32 StringUtil::_ansiToUTF32[32] = {
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178
+};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h
index e419e2bca8..14c40fcb2b 100644
--- a/engines/wintermute/utils/string_util.h
+++ b/engines/wintermute/utils/string_util.h
@@ -49,8 +49,11 @@ public:
static Common::String decodeSetting(const Common::String &str);
static AnsiString toString(int val);
+
+private:
+ static uint32 _ansiToUTF32[32];
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp
index 6e0d69edbe..8fa6313ba6 100644
--- a/engines/wintermute/utils/utils.cpp
+++ b/engines/wintermute/utils/utils.cpp
@@ -258,4 +258,4 @@ float BaseUtils::Hue2RGB(float v1, float v2, float vH) {
return (v1);
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h
index d6a603ec72..6c804ff01e 100644
--- a/engines/wintermute/utils/utils.h
+++ b/engines/wintermute/utils/utils.h
@@ -59,6 +59,6 @@ private:
static float Hue2RGB(float v1, float v2, float vH);
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/video/video_player.cpp b/engines/wintermute/video/video_player.cpp
index 42857b5c1b..f18311c3e1 100644
--- a/engines/wintermute/video/video_player.cpp
+++ b/engines/wintermute/video/video_player.cpp
@@ -106,4 +106,4 @@ bool VideoPlayer::loadSubtitles(const char *filename, const char *subtitleFile)
return STATUS_OK;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/video/video_player.h b/engines/wintermute/video/video_player.h
index 033ab50dfa..51c6bf41d3 100644
--- a/engines/wintermute/video/video_player.h
+++ b/engines/wintermute/video/video_player.h
@@ -85,6 +85,6 @@ public:
BaseArray<CVidSubtitle *, CVidSubtitle *> _subtitles;*/
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index 8f9db8392f..44eecf93a8 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -34,7 +34,6 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/sound/base_sound_manager.h"
-#include "engines/wintermute/platform_osystem.h"
#include "video/theora_decoder.h"
#include "engines/wintermute/wintermute.h"
#include "common/system.h"
@@ -163,14 +162,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;
}
@@ -369,14 +368,14 @@ void VideoTheoraPlayer::writeAlpha() {
if (_alphaImage && _surface.w == _alphaImage->getSurface()->w && _surface.h == _alphaImage->getSurface()->h) {
assert(_alphaImage->getSurface()->format.bytesPerPixel == 4);
assert(_surface.format.bytesPerPixel == 4);
- const byte *alphaData = (const byte *)_alphaImage->getSurface()->getBasePtr(0, 0);
+ const byte *alphaData = (const byte *)_alphaImage->getSurface()->getPixels();
#ifdef SCUMM_LITTLE_ENDIAN
int alphaPlace = (_alphaImage->getSurface()->format.aShift / 8);
#else
int alphaPlace = 3 - (_alphaImage->getSurface()->format.aShift / 8);
#endif
alphaData += alphaPlace;
- byte *imgData = (byte *)_surface.getBasePtr(0, 0);
+ byte *imgData = (byte *)_surface.getPixels();
#ifdef SCUMM_LITTLE_ENDIAN
imgData += (_surface.format.aShift / 8);
#else
@@ -396,7 +395,7 @@ bool VideoTheoraPlayer::display(uint32 alpha) {
bool res;
if (_texture && _videoFrameReady) {
- BasePlatform::setRect(&rc, 0, 0, _texture->getWidth(), _texture->getHeight());
+ rc.setRect(0, 0, _texture->getWidth(), _texture->getHeight());
if (_playZoom == 100.0f) {
res = _texture->displayTrans(_posX, _posY, rc, alpha);
} else {
@@ -417,7 +416,7 @@ bool VideoTheoraPlayer::display(uint32 alpha) {
bool VideoTheoraPlayer::setAlphaImage(const Common::String &filename) {
delete _alphaImage;
_alphaImage = new BaseImage();
- if (!_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) {
+ if (filename == "" || !_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) {
delete _alphaImage;
_alphaImage = nullptr;
_alphaFilename = "";
@@ -492,16 +491,16 @@ bool VideoTheoraPlayer::persist(BasePersistenceManager *persistMgr) {
}
persistMgr->transferPtr(TMEMBER_PTR(_gameRef));
- persistMgr->transfer(TMEMBER(_savedPos));
- persistMgr->transfer(TMEMBER(_savedState));
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_alphaFilename));
- persistMgr->transfer(TMEMBER(_posX));
- persistMgr->transfer(TMEMBER(_posY));
- persistMgr->transfer(TMEMBER(_playZoom));
- persistMgr->transfer(TMEMBER_INT(_playbackType));
- persistMgr->transfer(TMEMBER(_looping));
- persistMgr->transfer(TMEMBER(_volume));
+ persistMgr->transferUint32(TMEMBER(_savedPos));
+ persistMgr->transferSint32(TMEMBER(_savedState));
+ persistMgr->transferString(TMEMBER(_filename));
+ persistMgr->transferString(TMEMBER(_alphaFilename));
+ persistMgr->transferSint32(TMEMBER(_posX));
+ persistMgr->transferSint32(TMEMBER(_posY));
+ persistMgr->transferFloat(TMEMBER(_playZoom));
+ persistMgr->transferSint32(TMEMBER_INT(_playbackType));
+ persistMgr->transferBool(TMEMBER(_looping));
+ persistMgr->transferSint32(TMEMBER(_volume));
if (!persistMgr->getIsSaving() && (_savedState != THEORA_STATE_NONE)) {
initializeSimple();
@@ -529,4 +528,4 @@ BaseSurface *VideoTheoraPlayer::getTexture() const {
return _texture;
}
-} // end of namespace Wintermute
+} // End of namespace Wintermute
diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h
index 364509a080..7b28a71e17 100644
--- a/engines/wintermute/video/video_theora_player.h
+++ b/engines/wintermute/video/video_theora_player.h
@@ -62,7 +62,7 @@ public:
//CVidSubtitler *_subtitler;
// control methods
- bool initialize(const Common::String &filename, const Common::String &subtitleFile = nullptr);
+ bool initialize(const Common::String &filename, const Common::String &subtitleFile = Common::String());
bool initializeSimple();
bool update();
bool play(TVideoPlayback type = VID_PLAY_CENTER, int x = 0, int y = 0, bool freezeGame = false, bool freezeMusic = true, bool looping = false, uint32 startTime = 0, float forceZoom = -1.0f, int volume = -1);
@@ -90,7 +90,7 @@ public:
BaseImage *_alphaImage;
Common::String _alphaFilename;
bool setAlphaImage(const Common::String &filename);
- __inline byte getAlphaAt(int x, int y) const;
+ byte getAlphaAt(int x, int y) const;
void writeAlpha();
bool seekToTime(uint32 Time);
@@ -101,7 +101,7 @@ public:
// video properties
int32 _posX;
int32 _posY;
-
+
bool _dontDropFrames;
private:
int32 _state;
@@ -142,6 +142,6 @@ private:
};
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 89a6f1b3e0..0a6be4caf8 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"
@@ -106,7 +105,7 @@ bool WintermuteEngine::hasFeature(EngineFeature f) const {
Common::Error WintermuteEngine::run() {
// Initialize graphics using following:
- Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
initGraphics(800, 600, true, &format);
if (g_system->getScreenFormat() != format) {
error("Wintermute currently REQUIRES 32bpp");
@@ -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/engines/wintermute/wintypes.h b/engines/wintermute/wintypes.h
index c7723808ea..1288ac1a65 100644
--- a/engines/wintermute/wintypes.h
+++ b/engines/wintermute/wintypes.h
@@ -48,6 +48,6 @@ namespace Wintermute {
#define MAX_PATH_LENGTH 512
-} // end of namespace Wintermute
+} // End of namespace Wintermute
#endif
diff --git a/engines/zvision/animation/rlf_animation.cpp b/engines/zvision/animation/rlf_animation.cpp
new file mode 100644
index 0000000000..c7307265c0
--- /dev/null
+++ b/engines/zvision/animation/rlf_animation.cpp
@@ -0,0 +1,331 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/animation/rlf_animation.h"
+
+#include "common/str.h"
+#include "common/file.h"
+#include "common/textconsole.h"
+#include "common/debug.h"
+#include "common/endian.h"
+
+#include "graphics/colormasks.h"
+
+
+namespace ZVision {
+
+RlfAnimation::RlfAnimation(const Common::String &fileName, bool stream)
+ : _stream(stream),
+ _lastFrameRead(0),
+ _frameCount(0),
+ _width(0),
+ _height(0),
+ _frameTime(0),
+ _frames(0),
+ _currentFrame(-1),
+ _frameBufferByteSize(0) {
+ if (!_file.open(fileName)) {
+ warning("RLF animation file %s could not be opened", fileName.c_str());
+ return;
+ }
+
+ if (!readHeader()) {
+ warning("%s is not a RLF animation file. Wrong magic number", fileName.c_str());
+ return;
+ }
+
+ _currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>());
+ _frameBufferByteSize = _width * _height * sizeof(uint16);
+
+ if (!stream) {
+ _frames = new Frame[_frameCount];
+
+ // Read in each frame
+ for (uint i = 0; i < _frameCount; ++i) {
+ _frames[i] = readNextFrame();
+ }
+ }
+}
+
+RlfAnimation::~RlfAnimation() {
+ for (uint i = 0; i < _frameCount; ++i) {
+ delete[] _frames[i].encodedData;
+ }
+ delete[] _frames;
+ _currentFrameBuffer.free();
+}
+
+bool RlfAnimation::readHeader() {
+ if (_file.readUint32BE() != MKTAG('F', 'E', 'L', 'R')) {
+ return false;
+ }
+
+ // Read the header
+ _file.readUint32LE(); // Size1
+ _file.readUint32LE(); // Unknown1
+ _file.readUint32LE(); // Unknown2
+ _frameCount = _file.readUint32LE(); // Frame count
+
+ // Since we don't need any of the data, we can just seek right to the
+ // entries we need rather than read in all the individual entries.
+ _file.seek(136, SEEK_CUR);
+
+ //// Read CIN header
+ //_file.readUint32BE(); // Magic number FNIC
+ //_file.readUint32LE(); // Size2
+ //_file.readUint32LE(); // Unknown3
+ //_file.readUint32LE(); // Unknown4
+ //_file.readUint32LE(); // Unknown5
+ //_file.seek(0x18, SEEK_CUR); // VRLE
+ //_file.readUint32LE(); // LRVD
+ //_file.readUint32LE(); // Unknown6
+ //_file.seek(0x18, SEEK_CUR); // HRLE
+ //_file.readUint32LE(); // ELHD
+ //_file.readUint32LE(); // Unknown7
+ //_file.seek(0x18, SEEK_CUR); // HKEY
+ //_file.readUint32LE(); // ELRH
+
+ //// Read MIN info header
+ //_file.readUint32BE(); // Magic number FNIM
+ //_file.readUint32LE(); // Size3
+ //_file.readUint32LE(); // OEDV
+ //_file.readUint32LE(); // Unknown8
+ //_file.readUint32LE(); // Unknown9
+ //_file.readUint32LE(); // Unknown10
+ _width = _file.readUint32LE(); // Width
+ _height = _file.readUint32LE(); // Height
+
+ // Read time header
+ _file.readUint32BE(); // Magic number EMIT
+ _file.readUint32LE(); // Size4
+ _file.readUint32LE(); // Unknown11
+ _frameTime = _file.readUint32LE() / 10; // Frame time in microseconds
+
+ return true;
+}
+
+RlfAnimation::Frame RlfAnimation::readNextFrame() {
+ RlfAnimation::Frame frame;
+
+ _file.readUint32BE(); // Magic number MARF
+ uint32 size = _file.readUint32LE(); // Size
+ _file.readUint32LE(); // Unknown1
+ _file.readUint32LE(); // Unknown2
+ uint32 type = _file.readUint32BE(); // Either ELHD or ELRH
+ uint32 headerSize = _file.readUint32LE(); // Offset from the beginning of this frame to the frame data. Should always be 28
+ _file.readUint32LE(); // Unknown3
+
+ frame.encodedSize = size - headerSize;
+ frame.encodedData = new int8[frame.encodedSize];
+ _file.read(frame.encodedData, frame.encodedSize);
+
+ if (type == MKTAG('E', 'L', 'H', 'D')) {
+ frame.type = Masked;
+ } else if (type == MKTAG('E', 'L', 'R', 'H')) {
+ frame.type = Simple;
+ _completeFrames.push_back(_lastFrameRead);
+ } else {
+ warning("Frame %u doesn't have type that can be decoded", _lastFrameRead);
+ }
+
+ _lastFrameRead++;
+ return frame;
+}
+
+void RlfAnimation::seekToFrame(int frameNumber) {
+ assert(!_stream);
+ assert(frameNumber < (int)_frameCount || frameNumber >= -1);
+
+ if (frameNumber == -1) {
+ _currentFrame = -1;
+ return;
+ }
+
+ int closestFrame = _currentFrame;
+ int distance = (int)frameNumber - _currentFrame;
+ for (uint i = 0; i < _completeFrames.size(); ++i) {
+ int newDistance = (int)frameNumber - (int)(_completeFrames[i]);
+ if (newDistance > 0 && (closestFrame == -1 || newDistance < distance)) {
+ closestFrame = _completeFrames[i];
+ distance = newDistance;
+ }
+ }
+
+ for (int i = closestFrame; i <= frameNumber; ++i) {
+ applyFrameToCurrent(i);
+ }
+
+ _currentFrame = frameNumber;
+}
+
+const Graphics::Surface *RlfAnimation::getFrameData(uint frameNumber) {
+ assert(!_stream);
+ assert(frameNumber < _frameCount);
+
+ // Since this method is so expensive, first check to see if we can use
+ // getNextFrame() it's cheap.
+ if ((int)frameNumber == _currentFrame) {
+ return &_currentFrameBuffer;
+ } else if (_currentFrame + 1 == (int)frameNumber) {
+ return getNextFrame();
+ }
+
+ seekToFrame(frameNumber);
+ return &_currentFrameBuffer;
+}
+
+const Graphics::Surface *RlfAnimation::getNextFrame() {
+ assert(_currentFrame + 1 < (int)_frameCount);
+
+ if (_stream) {
+ applyFrameToCurrent(readNextFrame());
+ } else {
+ applyFrameToCurrent(_currentFrame + 1);
+ }
+
+ _currentFrame++;
+ return &_currentFrameBuffer;
+}
+
+void RlfAnimation::applyFrameToCurrent(uint frameNumber) {
+ if (_frames[frameNumber].type == Masked) {
+ decodeMaskedRunLengthEncoding(_frames[frameNumber].encodedData, (int8 *)_currentFrameBuffer.getPixels(), _frames[frameNumber].encodedSize, _frameBufferByteSize);
+ } else if (_frames[frameNumber].type == Simple) {
+ decodeSimpleRunLengthEncoding(_frames[frameNumber].encodedData, (int8 *)_currentFrameBuffer.getPixels(), _frames[frameNumber].encodedSize, _frameBufferByteSize);
+ }
+}
+
+void RlfAnimation::applyFrameToCurrent(const RlfAnimation::Frame &frame) {
+ if (frame.type == Masked) {
+ decodeMaskedRunLengthEncoding(frame.encodedData, (int8 *)_currentFrameBuffer.getPixels(), frame.encodedSize, _frameBufferByteSize);
+ } else if (frame.type == Simple) {
+ decodeSimpleRunLengthEncoding(frame.encodedData, (int8 *)_currentFrameBuffer.getPixels(), frame.encodedSize, _frameBufferByteSize);
+ }
+}
+
+void RlfAnimation::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
+ uint32 sourceOffset = 0;
+ uint32 destOffset = 0;
+
+ while (sourceOffset < sourceSize) {
+ int8 numberOfSamples = source[sourceOffset];
+ sourceOffset++;
+
+ // If numberOfSamples is negative, the next abs(numberOfSamples) samples should
+ // be copied directly from source to dest
+ if (numberOfSamples < 0) {
+ numberOfSamples = ABS(numberOfSamples);
+
+ while (numberOfSamples > 0) {
+ if (sourceOffset + 1 >= sourceSize) {
+ return;
+ } else if (destOffset + 1 >= destSize) {
+ debug(2, "Frame decoding overflow\n\tsourceOffset=%u\tsourceSize=%u\n\tdestOffset=%u\tdestSize=%u", sourceOffset, sourceSize, destOffset, destSize);
+ return;
+ }
+
+ byte r, g, b;
+ Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b);
+ uint16 destColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
+ WRITE_UINT16(dest + destOffset, destColor);
+
+ sourceOffset += 2;
+ destOffset += 2;
+ numberOfSamples--;
+ }
+
+ // If numberOfSamples is >= 0, move destOffset forward ((numberOfSamples * 2) + 2)
+ // This function assumes the dest buffer has been memset with 0's.
+ } else {
+ if (sourceOffset + 1 >= sourceSize) {
+ return;
+ } else if (destOffset + 1 >= destSize) {
+ debug(2, "Frame decoding overflow\n\tsourceOffset=%u\tsourceSize=%u\n\tdestOffset=%u\tdestSize=%u", sourceOffset, sourceSize, destOffset, destSize);
+ return;
+ }
+
+ destOffset += (numberOfSamples * 2) + 2;
+ }
+ }
+}
+
+void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
+ uint32 sourceOffset = 0;
+ uint32 destOffset = 0;
+
+ while (sourceOffset < sourceSize) {
+ int8 numberOfSamples = source[sourceOffset];
+ sourceOffset++;
+
+ // If numberOfSamples is negative, the next abs(numberOfSamples) samples should
+ // be copied directly from source to dest
+ if (numberOfSamples < 0) {
+ numberOfSamples = ABS(numberOfSamples);
+
+ while (numberOfSamples > 0) {
+ if (sourceOffset + 1 >= sourceSize) {
+ return;
+ } else if (destOffset + 1 >= destSize) {
+ debug(2, "Frame decoding overflow\n\tsourceOffset=%u\tsourceSize=%u\n\tdestOffset=%u\tdestSize=%u", sourceOffset, sourceSize, destOffset, destSize);
+ return;
+ }
+
+ byte r, g, b;
+ Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b);
+ uint16 destColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
+ WRITE_UINT16(dest + destOffset, destColor);
+
+ sourceOffset += 2;
+ destOffset += 2;
+ numberOfSamples--;
+ }
+
+ // If numberOfSamples is >= 0, copy one sample from source to the
+ // next (numberOfSamples + 2) dest spots
+ } else {
+ if (sourceOffset + 1 >= sourceSize) {
+ return;
+ }
+
+ byte r, g, b;
+ Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b);
+ uint16 sampleColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
+ sourceOffset += 2;
+
+ numberOfSamples += 2;
+ while (numberOfSamples > 0) {
+ if (destOffset + 1 >= destSize) {
+ debug(2, "Frame decoding overflow\n\tsourceOffset=%u\tsourceSize=%u\n\tdestOffset=%u\tdestSize=%u", sourceOffset, sourceSize, destOffset, destSize);
+ return;
+ }
+
+ WRITE_UINT16(dest + destOffset, sampleColor);
+ destOffset += 2;
+ numberOfSamples--;
+ }
+ }
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/animation/rlf_animation.h b/engines/zvision/animation/rlf_animation.h
new file mode 100644
index 0000000000..fe5b0d68b4
--- /dev/null
+++ b/engines/zvision/animation/rlf_animation.h
@@ -0,0 +1,163 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_RLF_ANIMATION_H
+#define ZVISION_RLF_ANIMATION_H
+
+#include "common/file.h"
+
+#include "graphics/surface.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+class RlfAnimation {
+public:
+ RlfAnimation(const Common::String &fileName, bool stream = true);
+ ~RlfAnimation();
+
+private:
+ enum EncodingType {
+ Masked,
+ Simple
+ };
+
+ struct Frame {
+ EncodingType type;
+ int8 *encodedData;
+ uint32 encodedSize;
+ };
+
+private:
+ Common::File _file;
+ bool _stream;
+ uint _lastFrameRead;
+
+ uint _frameCount;
+ uint _width;
+ uint _height;
+ uint32 _frameTime; // In milliseconds
+ Frame *_frames;
+ Common::Array<uint> _completeFrames;
+
+ int _currentFrame;
+ Graphics::Surface _currentFrameBuffer;
+ uint32 _frameBufferByteSize;
+
+public:
+ uint frameCount() { return _frameCount; }
+ uint width() { return _width; }
+ uint height() { return _height; }
+ uint32 frameTime() { return _frameTime; }
+
+ /**
+ * Seeks to the frameNumber and updates the internal Surface with
+ * the new frame data. If frameNumber == -1, it only sets _currentFrame,
+ * the internal Surface is unchanged. This function requires _stream = false
+ *
+ * @param frameNumber The frame number to seek to
+ */
+ void seekToFrame(int frameNumber);
+
+ /**
+ * Returns the pixel data of the frame specified. It will try to use
+ * getNextFrame() if possible. If not, it uses seekToFrame() to
+ * update the internal Surface and then returns a pointer to it.
+ * This function requires _stream = false
+ *
+ * @param frameNumber The frame number to get data for
+ * @return A pointer to the pixel data. Do NOT delete this.
+ */
+ const Graphics::Surface *getFrameData(uint frameNumber);
+ /**
+ * Returns the pixel data of the next frame. It is up to the user to
+ * check if the next frame is valid before calling this.
+ * IE. Use endOfAnimation()
+ *
+ * @return A pointer to the pixel data. Do NOT delete this.
+ */
+ const Graphics::Surface *getNextFrame();
+
+ /**
+ * @return Is the currentFrame is the last frame in the animation?
+ */
+ bool endOfAnimation() { return _currentFrame == (int)_frameCount - 1; }
+
+private:
+ /**
+ * Reads in the header of the RLF file
+ *
+ * @return Will return false if the header magic number is wrong
+ */
+ bool readHeader();
+ /**
+ * Reads the next frame from the RLF file, stores the data in
+ * a Frame object, then returns the object
+ *
+ * @return A Frame object representing the frame data
+ */
+ Frame readNextFrame();
+
+ /**
+ * Applies the frame corresponding to frameNumber on top of _currentFrameBuffer.
+ * This function requires _stream = false so it can look up the Frame object
+ * referenced by frameNumber.
+ *
+ * @param frameNumber The frame number to apply to _currentFrameBuffer
+ */
+ void applyFrameToCurrent(uint frameNumber);
+ /**
+ * Applies the data from a Frame object on top of a _currentFrameBuffer.
+ *
+ * @param frame A Frame object to apply to _currentFrameBuffer
+ */
+ void applyFrameToCurrent(const RlfAnimation::Frame &frame);
+
+ /**
+ * Decode frame data that uses masked run length encoding. This is the encoding
+ * used by P-frames.
+ *
+ * @param source The source pixel data
+ * @param dest The destination buffer
+ * @param sourceSize The size of the source pixel data
+ * @param destSize The size of the destination buffer
+ */
+ void decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
+ /**
+ * Decode frame data that uses simple run length encoding. This is the encoding
+ * used by I-frames.
+ *
+ * @param source The source pixel data
+ * @param dest The destination buffer
+ * @param sourceSize The size of the source pixel data
+ * @param destSize The size of the destination buffer
+ */
+ void decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/archives/zfs_archive.cpp b/engines/zvision/archives/zfs_archive.cpp
new file mode 100644
index 0000000000..b8175b4903
--- /dev/null
+++ b/engines/zvision/archives/zfs_archive.cpp
@@ -0,0 +1,157 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/archives/zfs_archive.h"
+
+#include "common/memstream.h"
+#include "common/debug.h"
+#include "common/file.h"
+
+namespace ZVision {
+
+ZfsArchive::ZfsArchive(const Common::String &fileName) : _fileName(fileName) {
+ Common::File zfsFile;
+
+ if (!zfsFile.open(_fileName)) {
+ warning("ZFSArchive::ZFSArchive(): Could not find the archive file");
+ return;
+ }
+
+ readHeaders(&zfsFile);
+
+ debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.c_str(), _entryHeaders.size());
+}
+
+ZfsArchive::ZfsArchive(const Common::String &fileName, Common::SeekableReadStream *stream) : _fileName(fileName) {
+ readHeaders(stream);
+
+ debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.c_str(), _entryHeaders.size());
+}
+
+ZfsArchive::~ZfsArchive() {
+ debug(1, "ZfsArchive Destructor Called");
+ ZfsEntryHeaderMap::iterator it = _entryHeaders.begin();
+ for ( ; it != _entryHeaders.end(); ++it) {
+ delete it->_value;
+ }
+}
+
+void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) {
+ // Don't do a straight struct cast since we can't guarantee endianness
+ _header.magic = stream->readUint32LE();
+ _header.unknown1 = stream->readUint32LE();
+ _header.maxNameLength = stream->readUint32LE();
+ _header.filesPerBlock = stream->readUint32LE();
+ _header.fileCount = stream->readUint32LE();
+ _header.xorKey[0] = stream->readByte();
+ _header.xorKey[1] = stream->readByte();
+ _header.xorKey[2] = stream->readByte();
+ _header.xorKey[3] = stream->readByte();
+ _header.fileSectionOffset = stream->readUint32LE();
+
+ uint32 nextOffset;
+
+ do {
+ // Read the offset to the next block
+ nextOffset = stream->readUint32LE();
+
+ // Read in each entry header
+ for (uint32 i = 0; i < _header.filesPerBlock; ++i) {
+ ZfsEntryHeader entryHeader;
+
+ entryHeader.name = readEntryName(stream);
+ entryHeader.offset = stream->readUint32LE();
+ entryHeader.id = stream->readUint32LE();
+ entryHeader.size = stream->readUint32LE();
+ entryHeader.time = stream->readUint32LE();
+ entryHeader.unknown = stream->readUint32LE();
+
+ if (entryHeader.size != 0)
+ _entryHeaders[entryHeader.name] = new ZfsEntryHeader(entryHeader);
+ }
+
+ // Seek to the next block of headers
+ stream->seek(nextOffset);
+ } while (nextOffset != 0);
+}
+
+Common::String ZfsArchive::readEntryName(Common::SeekableReadStream *stream) const {
+ // Entry Names are at most 16 bytes and are null padded
+ char buffer[16];
+ stream->read(buffer, 16);
+
+ return Common::String(buffer);
+}
+
+bool ZfsArchive::hasFile(const Common::String &name) const {
+ return _entryHeaders.contains(name);
+}
+
+int ZfsArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int matches = 0;
+
+ for (ZfsEntryHeaderMap::const_iterator it = _entryHeaders.begin(); it != _entryHeaders.end(); ++it) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(it->_value->name, this)));
+ matches++;
+ }
+
+ return matches;
+}
+
+const Common::ArchiveMemberPtr ZfsArchive::getMember(const Common::String &name) const {
+ if (!_entryHeaders.contains(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *ZfsArchive::createReadStreamForMember(const Common::String &name) const {
+ if (!_entryHeaders.contains(name)) {
+ return 0;
+ }
+
+ ZfsEntryHeader *entryHeader = _entryHeaders[name];
+
+ Common::File zfsArchive;
+ zfsArchive.open(_fileName);
+ zfsArchive.seek(entryHeader->offset);
+
+ // This *HAS* to be malloc (not new[]) because MemoryReadStream uses free() to free the memory
+ byte* buffer = (byte *)malloc(entryHeader->size);
+ zfsArchive.read(buffer, entryHeader->size);
+ // Decrypt the data in place
+ if (_header.xorKey != 0)
+ unXor(buffer, entryHeader->size, _header.xorKey);
+
+ return new Common::MemoryReadStream(buffer, entryHeader->size, DisposeAfterUse::YES);
+}
+
+void ZfsArchive::unXor(byte *buffer, uint32 length, const byte *xorKey) const {
+ for (uint32 i = 0; i < length; ++i)
+ buffer[i] ^= xorKey[i % 4];
+}
+
+} // End of namespace ZVision
+
+
diff --git a/engines/zvision/archives/zfs_archive.h b/engines/zvision/archives/zfs_archive.h
new file mode 100644
index 0000000000..d7b45e4b47
--- /dev/null
+++ b/engines/zvision/archives/zfs_archive.h
@@ -0,0 +1,126 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_ZFS_ARCHIVE_H
+#define ZVISION_ZFS_ARCHIVE_H
+
+#include "common/archive.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+struct ZfsHeader {
+ uint32 magic;
+ uint32 unknown1;
+ uint32 maxNameLength;
+ uint32 filesPerBlock;
+ uint32 fileCount;
+ byte xorKey[4];
+ uint32 fileSectionOffset;
+};
+
+struct ZfsEntryHeader {
+ Common::String name;
+ uint32 offset;
+ uint32 id;
+ uint32 size;
+ uint32 time;
+ uint32 unknown;
+};
+
+typedef Common::HashMap<Common::String, ZfsEntryHeader*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ZfsEntryHeaderMap;
+
+class ZfsArchive : public Common::Archive {
+public:
+ ZfsArchive(const Common::String &fileName);
+ ZfsArchive(const Common::String &fileName, Common::SeekableReadStream *stream);
+ ~ZfsArchive();
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ bool hasFile(const Common::String &fileName) const;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return The number of names added to list
+ */
+ int listMembers(Common::ArchiveMemberList &list) const;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ *
+ * @return The newly created input stream
+ */
+ Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+
+private:
+ const Common::String _fileName;
+ ZfsHeader _header;
+ ZfsEntryHeaderMap _entryHeaders;
+
+ /**
+ * Parses the zfs file into file entry headers that can be used later
+ * to get the entry data.
+ *
+ * @param stream The contents of the zfs file
+ */
+ void readHeaders(Common::SeekableReadStream *stream);
+
+ /**
+ * Entry names are contained within a 16 byte block. This reads the block
+ * and converts it the name to a Common::String
+ *
+ * @param stream The zfs file stream
+ * @return The entry file name
+ */
+ Common::String readEntryName(Common::SeekableReadStream *stream) const;
+
+ /**
+ * ZFS file entries can be encrypted using XOR encoding. This method
+ * decodes the buffer in place using the supplied xorKey.
+ *
+ * @param buffer The data to decode
+ * @param length Length of buffer
+ */
+ void unXor(byte *buffer, uint32 length, const byte *xorKey) const;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/configure.engine b/engines/zvision/configure.engine
new file mode 100644
index 0000000000..02e31943af
--- /dev/null
+++ b/engines/zvision/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine zvision "ZVision" no "" "" "freetype2 16bit"
diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp
new file mode 100644
index 0000000000..0d325ef7f7
--- /dev/null
+++ b/engines/zvision/core/console.cpp
@@ -0,0 +1,218 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/core/console.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/strings/string_manager.h"
+#include "zvision/video/zork_avi_decoder.h"
+#include "zvision/sound/zork_raw.h"
+#include "zvision/utility/utility.h"
+#include "zvision/cursors/cursor.h"
+
+#include "common/system.h"
+#include "common/file.h"
+#include "common/bufferedstream.h"
+
+#include "gui/debugger.h"
+
+#include "audio/mixer.h"
+
+
+namespace ZVision {
+
+Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) {
+ DCmd_Register("loadimage", WRAP_METHOD(Console, cmdLoadImage));
+ DCmd_Register("loadvideo", WRAP_METHOD(Console, cmdLoadVideo));
+ DCmd_Register("loadsound", WRAP_METHOD(Console, cmdLoadSound));
+ DCmd_Register("raw2wav", WRAP_METHOD(Console, cmdRawToWav));
+ DCmd_Register("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState));
+ DCmd_Register("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable));
+ DCmd_Register("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV));
+ DCmd_Register("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale));
+ DCmd_Register("changelocation", WRAP_METHOD(Console, cmdChangeLocation));
+ DCmd_Register("dumpfile", WRAP_METHOD(Console, cmdDumpFile));
+ DCmd_Register("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles));
+ DCmd_Register("rendertext", WRAP_METHOD(Console, cmdRenderText));
+}
+
+bool Console::cmdLoadImage(int argc, const char **argv) {
+ if (argc == 4)
+ _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3]));
+ else {
+ DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n");
+ return true;
+ }
+
+ return true;
+}
+
+bool Console::cmdLoadVideo(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Use loadvideo <fileName> to load a video to the screen\n");
+ return true;
+ }
+
+ ZorkAVIDecoder videoDecoder;
+ if (videoDecoder.loadFile(argv[1])) {
+ _engine->playVideo(videoDecoder);
+ }
+
+ return true;
+}
+
+bool Console::cmdLoadSound(int argc, const char **argv) {
+ if (!Common::File::exists(argv[1])) {
+ DebugPrintf("File does not exist\n");
+ return true;
+ }
+
+ if (argc == 2) {
+ Audio::AudioStream *soundStream = makeRawZorkStream(argv[1], _engine);
+ Audio::SoundHandle handle;
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false);
+
+ } else if (argc == 4) {
+ int isStereo = atoi(argv[3]);
+
+ Common::File *file = new Common::File();
+ file->open(argv[1]);
+
+ Audio::AudioStream *soundStream = makeRawZorkStream(file, atoi(argv[2]), isStereo == 0 ? false : true);
+ Audio::SoundHandle handle;
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false);
+ } else {
+ DebugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n");
+ return true;
+ }
+
+ return true;
+}
+
+bool Console::cmdRawToWav(int argc, const char **argv) {
+ if (argc != 3) {
+ DebugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n");
+ return true;
+ }
+
+ convertRawToWav(argv[1], _engine, argv[2]);
+ return true;
+}
+
+bool Console::cmdSetRenderState(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
+ return true;
+ }
+
+ Common::String renderState(argv[1]);
+
+ if (renderState.matchString("panorama", true))
+ _engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::PANORAMA);
+ else if (renderState.matchString("tilt", true))
+ _engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::TILT);
+ else if (renderState.matchString("flat", true))
+ _engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT);
+ else
+ DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
+
+ return true;
+}
+
+bool Console::cmdGenerateRenderTable(int argc, const char **argv) {
+ _engine->getRenderManager()->getRenderTable()->generateRenderTable();
+
+ return true;
+}
+
+bool Console::cmdSetPanoramaFoV(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n");
+ return true;
+ }
+
+ _engine->getRenderManager()->getRenderTable()->setPanoramaFoV(atof(argv[1]));
+
+ return true;
+}
+
+bool Console::cmdSetPanoramaScale(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n");
+ return true;
+ }
+
+ _engine->getRenderManager()->getRenderTable()->setPanoramaScale(atof(argv[1]));
+
+ return true;
+}
+
+bool Console::cmdChangeLocation(int argc, const char **argv) {
+ if (argc != 6) {
+ DebugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n");
+ return true;
+ }
+
+ _engine->getScriptManager()->changeLocation(*(argv[1]), *(argv[2]), *(argv[3]), *(argv[4]), atoi(argv[5]));
+
+ return true;
+}
+
+bool Console::cmdDumpFile(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Use dumpfile <fileName> to dump a file\n");
+ return true;
+ }
+
+ writeFileContentsToFile(argv[1], argv[1]);
+
+ return true;
+}
+
+bool Console::cmdParseAllScrFiles(int argc, const char **argv) {
+ Common::ArchiveMemberList list;
+ SearchMan.listMatchingMembers(list, "*.scr");
+
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ _engine->getScriptManager()->parseScrFile((*iter)->getName());
+ }
+
+ return true;
+}
+
+bool Console::cmdRenderText(int argc, const char **argv) {
+ if (argc != 7) {
+ DebugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n");
+ return true;
+ }
+
+ StringManager::TextStyle style = _engine->getStringManager()->getTextStyle(atoi(argv[2]));
+ _engine->getRenderManager()->renderTextToWorkingWindow(333, Common::String(argv[1]), style.font, atoi(argv[3]), atoi(argv[4]), style.color, atoi(argv[5]), -1, Graphics::kTextAlignLeft, atoi(argv[6]) == 0 ? false : true);
+
+ return true;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h
new file mode 100644
index 0000000000..0ca1b8cc70
--- /dev/null
+++ b/engines/zvision/core/console.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef ZVISION_CONSOLE_H
+#define ZVISION_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class Console : public GUI::Debugger {
+public:
+ Console(ZVision *engine);
+ virtual ~Console() {}
+
+private:
+ ZVision *_engine;
+
+ bool cmdLoadImage(int argc, const char **argv);
+ bool cmdLoadVideo(int argc, const char **argv);
+ bool cmdLoadSound(int argc, const char **argv);
+ bool cmdRawToWav(int argc, const char **argv);
+ bool cmdSetRenderState(int argc, const char **argv);
+ bool cmdGenerateRenderTable(int argc, const char **argv);
+ bool cmdSetPanoramaFoV(int argc, const char **argv);
+ bool cmdSetPanoramaScale(int argc, const char **argv);
+ bool cmdChangeLocation(int argc, const char **argv);
+ bool cmdDumpFile(int argc, const char **argv);
+ bool cmdParseAllScrFiles(int argc, const char **argv);
+ bool cmdRenderText(int argc, const char **argv);
+};
+
+} // End of namespace ZVision
+#endif
diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp
new file mode 100644
index 0000000000..40bfb879b1
--- /dev/null
+++ b/engines/zvision/core/events.cpp
@@ -0,0 +1,186 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/zvision.h"
+
+#include "zvision/core/console.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/animation/rlf_animation.h"
+
+#include "common/events.h"
+#include "common/system.h"
+#include "common/rational.h"
+
+#include "engines/util.h"
+
+
+namespace ZVision {
+
+void ZVision::processEvents() {
+ while (_eventMan->pollEvent(_event)) {
+ switch (_event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ onMouseDown(_event.mouse);
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ onMouseUp(_event.mouse);
+ break;
+
+ case Common::EVENT_RBUTTONDOWN:
+ // TODO: Inventory logic
+ break;
+
+ case Common::EVENT_MOUSEMOVE:
+ onMouseMove(_event.mouse);
+ break;
+
+ case Common::EVENT_KEYDOWN:
+ switch (_event.kbd.keycode) {
+ case Common::KEYCODE_d:
+ if (_event.kbd.hasFlags(Common::KBD_CTRL)) {
+ // Start the debugger
+ _console->attach();
+ _console->onFrame();
+ }
+ break;
+ case Common::KEYCODE_q:
+ if (_event.kbd.hasFlags(Common::KBD_CTRL))
+ quitGame();
+ break;
+ default:
+ break;
+ }
+
+ _scriptManager->onKeyDown(_event.kbd);
+ break;
+ case Common::EVENT_KEYUP:
+ _scriptManager->onKeyUp(_event.kbd);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void ZVision::onMouseDown(const Common::Point &pos) {
+ _cursorManager->cursorDown(true);
+
+ Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
+ _scriptManager->onMouseDown(pos, imageCoord);
+}
+
+void ZVision::onMouseUp(const Common::Point &pos) {
+ _cursorManager->cursorDown(false);
+
+ Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
+ _scriptManager->onMouseUp(pos, imageCoord);
+}
+
+void ZVision::onMouseMove(const Common::Point &pos) {
+ Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
+
+ bool cursorWasChanged = _scriptManager->onMouseMove(pos, imageCoord);
+
+ // Graph of the function governing rotation velocity:
+ //
+ // |---------------- working window ------------------|
+ // ^ |---------|
+ // | |
+ // +Max velocity | rotation screen edge offset
+ // | /|
+ // | / |
+ // | / |
+ // | / |
+ // | / |
+ // | / |
+ // | / |
+ // | / |
+ // | / |
+ // Zero velocity |______________________________ ______________________________/_________|__________________________>
+ // | Position -> | /
+ // | | /
+ // | | /
+ // | | /
+ // | | /
+ // | | /
+ // | | /
+ // | | /
+ // | | /
+ // -Max velocity | |/
+ // |
+ // |
+ // ^
+
+ if (_workingWindow.contains(pos)) {
+ RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState();
+ if (renderState == RenderTable::PANORAMA) {
+ if (pos.x >= _workingWindow.left && pos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) {
+ // Linear function of distance to the left edge (y = -mx + b)
+ // We use fixed point math to get better accuracy
+ Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.left)) - MAX_ROTATION_SPEED;
+ _renderManager->setBackgroundVelocity(velocity.toInt());
+ _cursorManager->setLeftCursor();
+ cursorWasChanged = true;
+ } else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) {
+ // Linear function of distance to the right edge (y = mx)
+ // We use fixed point math to get better accuracy
+ Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET);
+ _renderManager->setBackgroundVelocity(velocity.toInt());
+ _cursorManager->setRightCursor();
+ cursorWasChanged = true;
+ } else {
+ _renderManager->setBackgroundVelocity(0);
+ }
+ } else if (renderState == RenderTable::TILT) {
+ if (pos.y >= _workingWindow.top && pos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) {
+ // Linear function of distance to top edge
+ // We use fixed point math to get better accuracy
+ Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - MAX_ROTATION_SPEED;
+ _renderManager->setBackgroundVelocity(velocity.toInt());
+ _cursorManager->setUpCursor();
+ cursorWasChanged = true;
+ } else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) {
+ // Linear function of distance to the bottom edge (y = mx)
+ // We use fixed point math to get better accuracy
+ Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET);
+ _renderManager->setBackgroundVelocity(velocity.toInt());
+ _cursorManager->setDownCursor();
+ cursorWasChanged = true;
+ } else {
+ _renderManager->setBackgroundVelocity(0);
+ }
+ }
+ } else {
+ _renderManager->setBackgroundVelocity(0);
+ }
+
+ if (!cursorWasChanged) {
+ _cursorManager->revertToIdle();
+ }
+}
+
+} // End of namespace ZVision
diff --git a/backends/graphics/opengl/glerrorcheck.h b/engines/zvision/core/menu.h
index 2d5491bdfd..affc69abd5 100644
--- a/backends/graphics/opengl/glerrorcheck.h
+++ b/engines/zvision/core/menu.h
@@ -11,7 +11,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
@@ -20,16 +20,9 @@
*
*/
-#if !defined(DEBUG)
+#ifndef ZVISION_MENU_H
+#define ZVISION_MENU_H
-// If not in debug, do nothing
-#define CHECK_GL_ERROR() do {} while (false)
-
-#else
-
-// If in debug, check for an error after a GL call
-#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
-
-void checkGlError(const char *file, int line);
+// TODO: Implement MenuHandler
#endif
diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp
new file mode 100644
index 0000000000..b91f8eacad
--- /dev/null
+++ b/engines/zvision/core/save_manager.cpp
@@ -0,0 +1,206 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/core/save_manager.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+
+#include "common/system.h"
+
+#include "graphics/surface.h"
+#include "graphics/thumbnail.h"
+
+#include "gui/message.h"
+
+
+namespace ZVision {
+
+const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G');
+
+void SaveManager::saveGame(uint slot, const Common::String &saveName) {
+ // The games only support 20 slots
+ assert(slot <= 1 && slot <= 20);
+
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
+
+ // Write out the savegame header
+ file->writeUint32BE(SAVEGAME_ID);
+
+ // Write version
+ file->writeByte(SAVE_VERSION);
+
+ // Write savegame name
+ file->writeString(saveName);
+ file->writeByte(0);
+
+ // We can't call writeGameSaveData because the save menu is actually
+ // a room, so writeGameSaveData would save us in the save menu.
+ // However, an auto save is performed before each room change, so we
+ // can copy the data from there. We can guarantee that an auto save file will
+ // exist before this is called because the save menu can only be accessed
+ // after the first room (the main menu) has loaded.
+ Common::InSaveFile *autoSaveFile = saveFileManager->openForLoading(_engine->generateAutoSaveFileName());
+
+ // Skip over the header info
+ autoSaveFile->readSint32BE(); // SAVEGAME_ID
+ autoSaveFile->readByte(); // Version
+ autoSaveFile->seek(5, SEEK_CUR); // The string "auto" with terminating NULL
+
+ // Read the rest to a buffer
+ uint32 size = autoSaveFile->size() - autoSaveFile->pos();
+ byte *buffer = new byte[size];
+ autoSaveFile->read(buffer, size);
+
+ // Then write the buffer to the new file
+ file->write(buffer, size);
+
+ // Cleanup
+ delete[] buffer;
+ file->finalize();
+ delete file;
+}
+
+void SaveManager::autoSave() {
+ Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName());
+
+ // Write out the savegame header
+ file->writeUint32BE(SAVEGAME_ID);
+
+ // Version
+ file->writeByte(SAVE_VERSION);
+
+ file->writeString("auto");
+ file->writeByte(0);
+
+ writeSaveGameData(file);
+
+ // Cleanup
+ file->finalize();
+ delete file;
+}
+
+void SaveManager::writeSaveGameData(Common::OutSaveFile *file) {
+ // Create a thumbnail and save it
+ Graphics::saveThumbnail(*file);
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ file->writeSint16LE(td.tm_year + 1900);
+ file->writeSint16LE(td.tm_mon + 1);
+ file->writeSint16LE(td.tm_mday);
+ file->writeSint16LE(td.tm_hour);
+ file->writeSint16LE(td.tm_min);
+
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Write out the current location
+ Location currentLocation = scriptManager->getCurrentLocation();
+ file->writeByte(currentLocation.world);
+ file->writeByte(currentLocation.room);
+ file->writeByte(currentLocation.node);
+ file->writeByte(currentLocation.view);
+ file->writeUint32LE(currentLocation.offset);
+
+ // Write out the current state table values
+ scriptManager->serializeStateTable(file);
+
+ // Write out any controls needing to save state
+ scriptManager->serializeControls(file);
+}
+
+Common::Error SaveManager::loadGame(uint slot) {
+ // The games only support 20 slots
+ assert(slot <= 1 && slot <= 20);
+
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ if (saveFile == 0) {
+ return Common::kPathDoesNotExist;
+ }
+
+ // Read the header
+ SaveGameHeader header;
+ if (!readSaveGameHeader(saveFile, header)) {
+ return Common::kUnknownError;
+ }
+
+ char world = (char)saveFile->readByte();
+ char room = (char)saveFile->readByte();
+ char node = (char)saveFile->readByte();
+ char view = (char)saveFile->readByte();
+ uint32 offset = (char)saveFile->readUint32LE();
+
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Update the state table values
+ scriptManager->deserializeStateTable(saveFile);
+
+ // Load the room
+ scriptManager->changeLocation(world, room, node, view, offset);
+
+ // Update the controls
+ scriptManager->deserializeControls(saveFile);
+
+ return Common::kNoError;
+}
+
+bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
+ if (in->readUint32BE() != SAVEGAME_ID) {
+ warning("File is not a ZVision save file. Aborting load");
+ return false;
+ }
+
+ // Read in the version
+ header.version = in->readByte();
+
+ // Check that the save version isn't newer than this binary
+ if (header.version > SAVE_VERSION) {
+ uint tempVersion = header.version;
+ GUI::MessageDialog dialog(Common::String::format("This save file uses version %u, but this engine only supports up to version %d. You will need an updated version of the engine to use this save file.", tempVersion, SAVE_VERSION), "OK");
+ dialog.runModal();
+ }
+
+ // 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;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/core/save_manager.h b/engines/zvision/core/save_manager.h
new file mode 100644
index 0000000000..b4770e68b2
--- /dev/null
+++ b/engines/zvision/core/save_manager.h
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_SAVE_MANAGER_H
+#define ZVISION_SAVE_MANAGER_H
+
+#include "common/savefile.h"
+
+namespace Common {
+class String;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+struct SaveGameHeader {
+ byte version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+};
+
+class SaveManager {
+public:
+ SaveManager(ZVision *engine) : _engine(engine) {}
+
+private:
+ ZVision *_engine;
+ static const uint32 SAVEGAME_ID;
+
+ enum {
+ SAVE_VERSION = 1
+ };
+
+public:
+ /**
+ * Called every room change. Saves the state of the room just before
+ * we switched rooms. Uses ZVision::generateAutoSaveFileName() to
+ * create the save file name.
+ */
+ void autoSave();
+ /**
+ * Copies the data from the last auto-save into a new save file. We
+ * can't use the current state data because the save menu *IS* a room.
+ * The file is named using ZVision::generateSaveFileName(slot)
+ *
+ * @param slot The save slot this save pertains to. Must be [1, 20]
+ * @param saveName The internal name for this save. This is NOT the name of the actual save file.
+ */
+ void saveGame(uint slot, const Common::String &saveName);
+ /**
+ * Loads the state data from the save file that slot references. Uses
+ * ZVision::generateSaveFileName(slot) to get the save file name.
+ *
+ * @param slot The save slot to load. Must be [1, 20]
+ */
+ Common::Error loadGame(uint slot);
+
+private:
+ void writeSaveGameData(Common::OutSaveFile *file);
+ bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/cursors/cursor.cpp b/engines/zvision/cursors/cursor.cpp
new file mode 100644
index 0000000000..be80f6585b
--- /dev/null
+++ b/engines/zvision/cursors/cursor.cpp
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/cursors/cursor.h"
+
+#include "common/str.h"
+#include "common/file.h"
+
+
+namespace ZVision {
+
+ZorkCursor::ZorkCursor()
+ : _width(0),
+ _height(0),
+ _hotspotX(0),
+ _hotspotY(0) {
+}
+
+ZorkCursor::ZorkCursor(const Common::String &fileName)
+ : _width(0),
+ _height(0),
+ _hotspotX(0),
+ _hotspotY(0) {
+ Common::File file;
+ if (!file.open(fileName))
+ return;
+
+ uint32 magic = file.readUint32BE();
+ if (magic != MKTAG('Z', 'C', 'R', '1')) {
+ warning("%s is not a Zork Cursor file", fileName.c_str());
+ return;
+ }
+
+ _hotspotX = file.readUint16LE();
+ _hotspotY = file.readUint16LE();
+ _width = file.readUint16LE();
+ _height = file.readUint16LE();
+
+ uint dataSize = _width * _height * sizeof(uint16);
+ _surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+ uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
+ assert(bytesRead == dataSize);
+
+ // Convert to RGB 565
+ _surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+}
+
+ZorkCursor::ZorkCursor(const ZorkCursor &other) {
+ _width = other._width;
+ _height = other._height;
+ _hotspotX = other._hotspotX;
+ _hotspotY = other._hotspotY;
+
+ _surface.copyFrom(other._surface);
+}
+
+ZorkCursor &ZorkCursor::operator=(const ZorkCursor &other) {
+ _width = other._width;
+ _height = other._height;
+ _hotspotX = other._hotspotX;
+ _hotspotY = other._hotspotY;
+
+ _surface.free();
+ _surface.copyFrom(other._surface);
+
+ return *this;
+}
+
+ZorkCursor::~ZorkCursor() {
+ _surface.free();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/cursors/cursor.h b/engines/zvision/cursors/cursor.h
new file mode 100644
index 0000000000..18ac28ce8b
--- /dev/null
+++ b/engines/zvision/cursors/cursor.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 ZVISION_CURSOR_H
+#define ZVISION_CURSOR_H
+
+#include "graphics/surface.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+/**
+ * Utility class to parse and hold cursor data
+ * Modeled off Graphics::Cursor
+ */
+class ZorkCursor {
+public:
+ ZorkCursor();
+ ZorkCursor(const Common::String &fileName);
+ ZorkCursor(const ZorkCursor &other);
+ ~ZorkCursor();
+
+private:
+ uint16 _width;
+ uint16 _height;
+ uint16 _hotspotX;
+ uint16 _hotspotY;
+ Graphics::Surface _surface;
+
+public:
+ ZorkCursor &operator=(const ZorkCursor &other);
+
+ uint16 getWidth() const { return _width; }
+ uint16 getHeight() const { return _height; }
+ uint16 getHotspotX() const { return _hotspotX; }
+ uint16 getHotspotY() const { return _hotspotY; }
+ byte getKeyColor() const { return 0; }
+ const byte *getSurface() const { return (const byte *)_surface.getPixels(); }
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/cursors/cursor_manager.cpp b/engines/zvision/cursors/cursor_manager.cpp
new file mode 100644
index 0000000000..671f26ba2d
--- /dev/null
+++ b/engines/zvision/cursors/cursor_manager.cpp
@@ -0,0 +1,152 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/cursors/cursor_manager.h"
+
+#include "zvision/zvision.h"
+
+#include "common/system.h"
+
+#include "graphics/pixelformat.h"
+#include "graphics/cursorman.h"
+
+
+namespace ZVision {
+
+const char *CursorManager::_cursorNames[NUM_CURSORS] = { "active", "arrow", "backward", "downarrow", "forward", "handpt", "handpu", "hdown", "hleft",
+ "hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow" };
+
+const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac001.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr",
+ "g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr" };
+
+const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow", "back", "down", "forw", "handpt", "handpu", "hdown", "hleft",
+ "hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up" };
+
+
+CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat)
+ : _engine(engine),
+ _pixelFormat(pixelFormat),
+ _cursorIsPushed(false) {
+ // WARNING: The index IDLE_CURSOR_INDEX is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
+ if (_engine->getGameId() == GID_NEMESIS) {
+ Common::String name(Common::String::format("%sa.zcr", _zNemCursorFileNames[IDLE_CURSOR_INDEX]));
+ _idleCursor = ZorkCursor(name);
+ } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ _idleCursor = ZorkCursor(_zgiCursorFileNames[IDLE_CURSOR_INDEX]);
+ }
+}
+
+void CursorManager::initialize() {
+ revertToIdle();
+ CursorMan.showMouse(true);
+}
+
+void CursorManager::changeCursor(const Common::String &cursorName) {
+ changeCursor(cursorName, _cursorIsPushed);
+}
+
+void CursorManager::changeCursor(const Common::String &cursorName, bool pushed) {
+ if (_currentCursor.equals(cursorName) && _cursorIsPushed == pushed)
+ return;
+
+ if (_cursorIsPushed != pushed)
+ _cursorIsPushed = pushed;
+
+ if (cursorName == "idle" && !pushed) {
+ CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
+ return;
+ }
+
+ for (int i = 0; i < NUM_CURSORS; ++i) {
+ if (_engine->getGameId() == GID_NEMESIS) {
+ if (cursorName.equals(_cursorNames[i])) {
+ _currentCursor = cursorName;
+
+ // ZNem uses a/b at the end of the file to signify not pushed/pushed respectively
+ Common::String pushedFlag = pushed ? "b" : "a";
+ Common::String name = Common::String::format("%s%s.zcr", _zNemCursorFileNames[i], pushedFlag.c_str());
+
+ changeCursor(ZorkCursor(name));
+ return;
+ }
+ } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ if (cursorName.equals(_cursorNames[i])) {
+ _currentCursor = cursorName;
+
+ if (!pushed) {
+ changeCursor(ZorkCursor(_zgiCursorFileNames[i]));
+ } else {
+ // ZGI flips not pushed/pushed between a/c and b/d
+ // It flips the 4th character of the name
+ char buffer[25];
+ strcpy(buffer, _zgiCursorFileNames[i]);
+ buffer[3] += 2;
+ changeCursor(ZorkCursor(buffer));
+ }
+ return;
+ }
+ }
+ }
+
+ // If we get here, something went wrong
+ warning("No cursor found for identifier %s", cursorName.c_str());
+}
+
+void CursorManager::changeCursor(const ZorkCursor &cursor) {
+ CursorMan.replaceCursor(cursor.getSurface(), cursor.getWidth(), cursor.getHeight(), cursor.getHotspotX(), cursor.getHotspotY(), cursor.getKeyColor(), false, _pixelFormat);
+}
+
+void CursorManager::cursorDown(bool pushed) {
+ if (_cursorIsPushed == pushed)
+ return;
+
+ _cursorIsPushed = pushed;
+ changeCursor(_currentCursor, pushed);
+}
+
+void CursorManager::setLeftCursor() {
+ changeCursor("leftarrow");
+}
+
+void CursorManager::setRightCursor() {
+ changeCursor("rightarrow");
+}
+
+void CursorManager::setUpCursor() {
+ changeCursor("zuparrow");
+}
+
+void CursorManager::setDownCursor() {
+ changeCursor("downarrow");
+}
+
+void CursorManager::revertToIdle() {
+ _currentCursor = "idle";
+ if (!_cursorIsPushed)
+ CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
+ else
+ changeCursor(_currentCursor, _cursorIsPushed);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/cursors/cursor_manager.h b/engines/zvision/cursors/cursor_manager.h
new file mode 100644
index 0000000000..e982a40188
--- /dev/null
+++ b/engines/zvision/cursors/cursor_manager.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_CURSOR_MANAGER_H
+#define ZVISION_CURSOR_MANAGER_H
+
+#include "zvision/cursors/cursor.h"
+
+#include "common/str.h"
+
+
+namespace Graphics {
+struct PixelFormat;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+/**
+ * Class to manage cursor changes. The actual changes have to be done
+ * through CursorMan. Otherwise the cursor will disappear after GMM
+ * or debug console.
+ * TODO: Figure out a way to get rid of the extraneous data copying due to having to use CursorMan
+ */
+class CursorManager {
+public:
+ CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat);
+
+private:
+ enum {
+ NUM_CURSORS = 18,
+ // WARNING: The index 11 is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
+ IDLE_CURSOR_INDEX = 11
+ };
+
+ ZVision *_engine;
+ const Graphics::PixelFormat *_pixelFormat;
+ ZorkCursor _idleCursor;
+ Common::String _currentCursor;
+ bool _cursorIsPushed;
+
+ static const char *_cursorNames[];
+ static const char *_zgiCursorFileNames[];
+ static const char *_zNemCursorFileNames[];
+
+public:
+ /** Creates the idle cursor and shows it */
+ void initialize();
+
+ /**
+ * Parses a cursor name into a cursor file then creates and shows that cursor.
+ * It will use the current _isCursorPushed state to choose the correct cursor
+ *
+ * @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
+ */
+ void changeCursor(const Common::String &cursorName);
+ /**
+ * Parses a cursor name into a cursor file then creates and shows that cursor.
+ *
+ * @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
+ * @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
+ */
+ void changeCursor(const Common::String &cursorName, bool pushed);
+ /**
+ * Change the cursor to a certain push state. If the cursor is already in the specified push state, nothing will happen.
+ *
+ * @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
+ */
+ void cursorDown(bool pushed);
+
+ /** Set the cursor to 'Left Arrow'. It will retain the current _isCursorPushed state */
+ void setLeftCursor();
+ /** Set the cursor to 'Right Arrow'. It will retain the current _isCursorPushed state */
+ void setRightCursor();
+ /** Set the cursor to 'Up Arrow'. It will retain the current _isCursorPushed state */
+ void setUpCursor();
+ /** Set the cursor to 'Down Arrow'. It will retain the current _isCursorPushed state */
+ void setDownCursor();
+
+ /** Set the cursor to 'Idle'. It will retain the current _isCursorPushed state */
+ void revertToIdle();
+
+private:
+ /**
+ * Calls CursorMan.replaceCursor() using the data in cursor
+ *
+ * @param cursor The cursor to show
+ */
+ void changeCursor(const ZorkCursor &cursor);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp
new file mode 100644
index 0000000000..49664935e1
--- /dev/null
+++ b/engines/zvision/detection.cpp
@@ -0,0 +1,272 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "base/plugins.h"
+
+#include "zvision/zvision.h"
+#include "zvision/detection.h"
+
+#include "common/translation.h"
+#include "common/savefile.h"
+#include "common/str-array.h"
+#include "common/system.h"
+
+
+namespace ZVision {
+
+uint32 ZVision::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language ZVision::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+} // End of namespace ZVision
+
+
+static const PlainGameDescriptor zVisionGames[] = {
+ {"zvision", "ZVision Game"},
+ {"znemesis", "Zork Nemesis: The Forbidden Lands"},
+ {"zgi", "Zork: Grand Inquisitor"},
+ {0, 0}
+};
+
+
+namespace ZVision {
+
+static const ZVisionGameDescription gameDescriptions[] = {
+
+ {
+ // Zork Nemesis English version
+ {
+ "znemesis",
+ 0,
+ AD_ENTRY1s("CSCR.ZFS", "88226e51a205d2e50c67a5237f3bd5f2", 2397741),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GID_NEMESIS
+ },
+
+ {
+ // Zork Grand Inquisitor English version
+ {
+ "zgi",
+ 0,
+ AD_ENTRY1s("SCRIPTS.ZFS", "81efd40ecc3d22531e211368b779f17f", 8336944),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GID_GRANDINQUISITOR
+ },
+
+ {
+ AD_TABLE_END_MARKER,
+ GID_NONE
+ }
+};
+
+} // End of namespace ZVision
+
+static const char *directoryGlobs[] = {
+ "znemscr",
+ 0
+};
+
+static const ExtraGuiOption ZVisionExtraGuiOption = {
+ _s("Use original save/load screens"),
+ _s("Use the original save/load screens, instead of the ScummVM ones"),
+ "originalsaveload",
+ false
+};
+
+class ZVisionMetaEngine : public AdvancedMetaEngine {
+public:
+ ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), zVisionGames) {
+ _maxScanDepth = 2;
+ _directoryGlobs = directoryGlobs;
+ _singleid = "zvision";
+ }
+
+ virtual const char *getName() const {
+ return "ZVision";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "ZVision Activision (C) 1996";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
+ SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const;
+ void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+ /*
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime);
+ */
+}
+
+/*bool ZVision::ZVision::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}*/
+
+bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc;
+ if (gd) {
+ *engine = new ZVision::ZVision(syst, gd);
+ }
+ return gd != 0;
+}
+
+const ExtraGuiOptions ZVisionMetaEngine::getExtraGuiOptions(const Common::String &target) const {
+ ExtraGuiOptions options;
+ options.push_back(ZVisionExtraGuiOption);
+ return options;
+}
+
+SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
+ //Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ /*ZVision::ZVision::SaveHeader header;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ Common::StringArray filenames;
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
+
+ SaveStateList saveList;
+/* for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ if (ZVision::ZVision::readSaveHeader(in, false, header) == ZVision::ZVision::kRSHENoError) {
+ saveList.push_back(SaveStateDescriptor(slotNum, header.description));
+ }
+ delete in;
+ }
+ }
+ }*/
+
+ return saveList;
+}
+
+int ZVisionMetaEngine::getMaximumSaveSlot() const {
+ return 999;
+}
+
+void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
+ /*
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot);
+
+ saveFileMan->removeSavefile(filename.c_str());
+
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ // Rename every slot greater than the deleted slot,
+ if (slotNum > slot) {
+ saveFileMan->renameSavefile(file->c_str(), filename.c_str());
+ filename = ZVision::ZVision::getSavegameFilename(target, ++slot);
+ }
+ }
+ */
+}
+
+SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ /*
+ Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot);
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
+
+ if (in) {
+ ZVision::ZVision::SaveHeader header;
+ ZVision::ZVision::kReadSaveHeaderError error;
+
+ error = ZVision::ZVision::readSaveHeader(in, true, header);
+ delete in;
+
+ if (error == ZVision::ZVision::kRSHENoError) {
+ SaveStateDescriptor desc(slot, header.description);
+
+ desc.setThumbnail(header.thumbnail);
+
+ if (header.version > 0) {
+ int day = (header.saveDate >> 24) & 0xFF;
+ int month = (header.saveDate >> 16) & 0xFF;
+ int year = header.saveDate & 0xFFFF;
+
+ desc.setSaveDate(year, month, day);
+
+ int hour = (header.saveTime >> 16) & 0xFF;
+ int minutes = (header.saveTime >> 8) & 0xFF;
+
+ desc.setSaveTime(hour, minutes);
+
+ desc.setPlayTime(header.playTime * 1000);
+ }
+
+ return desc;
+ }
+ }
+ */
+
+ return SaveStateDescriptor();
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(ZVISION)
+ REGISTER_PLUGIN_DYNAMIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
+#endif
diff --git a/engines/zvision/detection.h b/engines/zvision/detection.h
new file mode 100644
index 0000000000..34417601e8
--- /dev/null
+++ b/engines/zvision/detection.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef ZVISION_DETECTION_H
+#define ZVISION_DETECTION_H
+
+#include "engines/advancedDetector.h"
+
+
+namespace ZVision {
+
+enum ZVisionGameId {
+ GID_NONE = 0,
+ GID_NEMESIS = 1,
+ GID_GRANDINQUISITOR = 2
+};
+
+struct ZVisionGameDescription {
+ ADGameDescription desc;
+ ZVisionGameId gameId;
+};
+
+}
+
+#endif
diff --git a/engines/zvision/fonts/truetype_font.cpp b/engines/zvision/fonts/truetype_font.cpp
new file mode 100644
index 0000000000..f8910bfe06
--- /dev/null
+++ b/engines/zvision/fonts/truetype_font.cpp
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/fonts/truetype_font.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "graphics/font.h"
+#include "graphics/fonts/ttf.h"
+#include "graphics/surface.h"
+
+
+namespace ZVision {
+
+TruetypeFont::TruetypeFont(ZVision *engine, int32 fontHeight)
+ : _engine(engine),
+ _fontHeight(fontHeight),
+ _font(0),
+ _lineHeight(0),
+ _maxCharWidth(0),
+ _maxCharHeight(0) {
+}
+
+TruetypeFont::~TruetypeFont(void) {
+ delete _font;
+}
+
+bool TruetypeFont::loadFile(const Common::String &filename) {
+ Common::File file;
+
+ bool fileOpened = false;
+ if (!Common::File::exists(filename)) {
+ debug("TTF font file %s was not found. Reverting to arial.ttf", filename.c_str());
+ fileOpened = file.open("arial.ttf");
+ } else {
+ fileOpened = file.open(filename);
+ }
+
+ if (!fileOpened) {
+ debug("TTF file could not be opened");
+ return false;
+ }
+
+ _font = Graphics::loadTTFFont(file, _fontHeight);
+ _lineHeight = _font->getFontHeight();
+
+ return true;
+}
+
+Graphics::Surface *TruetypeFont::drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
+ if (text.equals("")) {
+ return nullptr;
+ }
+
+ Graphics::Surface *surface = new Graphics::Surface();
+
+ if (!wrap) {
+ int width = MIN(_font->getStringWidth(text), maxWidth);
+ surface->create(width, _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ // TODO: Add better alpha support by getting the pixels from the backbuffer.
+ // However doing that requires some kind of caching system so future text doesn't try to use this text as it's alpha background.
+ surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
+
+ _font->drawString(surface, text, 0, 0, maxWidth, textColor, align);
+ return surface;
+ }
+
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text, maxWidth, lines);
+
+ while (maxHeight > 0 && (int)lines.size() * _lineHeight > maxHeight) {
+ lines.pop_back();
+ }
+ if (lines.size() == 0) {
+ return nullptr;
+ }
+
+ surface->create(maxWidth, lines.size() * _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
+
+ int heightOffset = 0;
+ for (Common::Array<Common::String>::iterator it = lines.begin(); it != lines.end(); it++) {
+ _font->drawString(surface, *it, 0, 0 + heightOffset, maxWidth, textColor, align);
+ heightOffset += _lineHeight;
+ }
+
+ return surface;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/fonts/truetype_font.h b/engines/zvision/fonts/truetype_font.h
new file mode 100644
index 0000000000..33f016cffd
--- /dev/null
+++ b/engines/zvision/fonts/truetype_font.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.
+ *
+ */
+
+// This file is based on engines/wintermute/base/fonts/base_font_truetype.h/.cpp
+
+#ifndef ZVISION_TRUETYPE_FONT_H
+#define ZVISION_TRUETYPE_FONT_H
+
+#include "graphics/font.h"
+#include "graphics/pixelformat.h"
+
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+class TruetypeFont {
+public:
+ TruetypeFont(ZVision *engine, int32 fontHeight);
+ ~TruetypeFont();
+
+private:
+ ZVision *_engine;
+ Graphics::Font *_font;
+ int _lineHeight;
+
+ size_t _maxCharWidth;
+ size_t _maxCharHeight;
+
+public:
+ int32 _fontHeight;
+
+public:
+ /**
+ * Loads a .ttf file into memory. This must be called
+ * before any calls to drawTextToSurface
+ *
+ * @param filename The file name of the .ttf file to load
+ */
+ bool loadFile(const Common::String &filename);
+ /**
+ * Renders the supplied text to a Surface using 0x0 as the
+ * background color.
+ *
+ * @param text The to render
+ * @param textColor The color to render the text with
+ * @param maxWidth The max width the text should take up.
+ * @param maxHeight The max height the text should take up.
+ * @param align The alignment of the text within the bounds of maxWidth
+ * @param wrap If true, any words extending past maxWidth will wrap to a new line. If false, ellipses will be rendered to show that the text didn't fit
+ * @return A Surface containing the rendered text
+ */
+ Graphics::Surface *drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp
new file mode 100644
index 0000000000..f19df88935
--- /dev/null
+++ b/engines/zvision/graphics/render_manager.cpp
@@ -0,0 +1,526 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/graphics/render_manager.h"
+
+#include "zvision/utility/lzss_read_stream.h"
+
+#include "common/file.h"
+#include "common/system.h"
+#include "common/stream.h"
+
+#include "engines/util.h"
+
+#include "graphics/decoders/tga.h"
+
+
+namespace ZVision {
+
+RenderManager::RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat)
+ : _system(system),
+ _workingWidth(workingWindow.width()),
+ _workingHeight(workingWindow.height()),
+ _screenCenterX(_workingWidth / 2),
+ _screenCenterY(_workingHeight / 2),
+ _workingWindow(workingWindow),
+ _pixelFormat(pixelFormat),
+ _backgroundWidth(0),
+ _backgroundHeight(0),
+ _backgroundInverseVelocity(0),
+ _backgroundOffset(0, 0),
+ _accumulatedVelocityMilliseconds(0),
+ _renderTable(_workingWidth, _workingHeight) {
+
+ _workingWindowBuffer.create(_workingWidth, _workingHeight, _pixelFormat);
+ _backBuffer.create(windowWidth, windowHeight, pixelFormat);
+}
+
+RenderManager::~RenderManager() {
+ _workingWindowBuffer.free();
+ _currentBackground.free();
+ _backBuffer.free();
+
+ for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
+ iter->_value.data->free();
+ delete iter->_value.data;
+ }
+}
+
+void RenderManager::update(uint deltaTimeInMillis) {
+ // An inverse velocity of 0 would be infinitely fast, so we'll let 0 mean no velocity.
+ if (_backgroundInverseVelocity != 0) {
+ _accumulatedVelocityMilliseconds += deltaTimeInMillis;
+
+ uint absVelocity = uint(abs(_backgroundInverseVelocity));
+
+ int numberOfSteps = 0;
+ while (_accumulatedVelocityMilliseconds >= absVelocity) {
+ _accumulatedVelocityMilliseconds -= absVelocity;
+ numberOfSteps++;
+ }
+
+ // Choose the direction of movement using the sign of the velocity
+ moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps);
+ }
+}
+
+void RenderManager::renderBackbufferToScreen() {
+ if (!_workingWindowDirtyRect.isEmpty()) {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ _renderTable.mutateImage((uint16 *)_workingWindowBuffer.getPixels(), (uint16 *)_backBuffer.getBasePtr(_workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top), _backBuffer.w, _workingWindowDirtyRect);
+ } else {
+ _backBuffer.copyRectToSurface(_workingWindowBuffer.getBasePtr(_workingWindowDirtyRect.left, _workingWindowDirtyRect.top), _workingWindowBuffer.pitch, _workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top, _workingWindowDirtyRect.width(), _workingWindowDirtyRect.height());
+ }
+
+ // Translate the working window dirty rect to screen coords
+ _workingWindowDirtyRect.translate(_workingWindow.left, _workingWindow.top);
+ // Then extend the backbuffer dirty rect to contain it
+ if (_backBufferDirtyRect.isEmpty()) {
+ _backBufferDirtyRect = _workingWindowDirtyRect;
+ } else {
+ _backBufferDirtyRect.extend(_workingWindowDirtyRect);
+ }
+
+ // Clear the dirty rect
+ _workingWindowDirtyRect = Common::Rect();
+ }
+
+ // TODO: Add menu rendering
+
+ // Render alpha entries
+ processAlphaEntries();
+
+ if (!_backBufferDirtyRect.isEmpty()) {
+ _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height());
+ _backBufferDirtyRect = Common::Rect();
+ }
+}
+
+void RenderManager::processAlphaEntries() {
+ // TODO: Add dirty rectangling support. AKA only draw an entry if the _backbufferDirtyRect intersects/contains the entry Rect
+
+ for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
+ uint32 destOffset = 0;
+ uint32 sourceOffset = 0;
+ uint16 *backbufferPtr = (uint16 *)_backBuffer.getBasePtr(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top);
+ uint16 *entryPtr = (uint16 *)iter->_value.data->getPixels();
+
+ for (int32 y = 0; y < iter->_value.height; ++y) {
+ for (int32 x = 0; x < iter->_value.width; ++x) {
+ uint16 color = entryPtr[sourceOffset + x];
+ if (color != iter->_value.alphaColor) {
+ backbufferPtr[destOffset + x] = color;
+ }
+ }
+
+ destOffset += _backBuffer.w;
+ sourceOffset += iter->_value.width;
+ }
+
+ if (_backBufferDirtyRect.isEmpty()) {
+ _backBufferDirtyRect = Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height);
+ } else {
+ _backBufferDirtyRect.extend(Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height));
+ }
+ }
+}
+
+void RenderManager::clearWorkingWindowTo555Color(uint16 color) {
+ uint32 workingWindowSize = _workingWidth * _workingHeight;
+ byte r, g, b;
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b);
+ uint16 colorIn565 = _pixelFormat.RGBToColor(r, g, b);
+ uint16 *bufferPtr = (uint16 *)_workingWindowBuffer.getPixels();
+
+ for (uint32 i = 0; i < workingWindowSize; ++i) {
+ bufferPtr[i] = colorIn565;
+ }
+}
+
+void RenderManager::renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
+ int16 subRectX = 0;
+ int16 subRectY = 0;
+
+ // Take care of negative destinations
+ if (destinationX < 0) {
+ subRectX = -destinationX;
+ destinationX = 0;
+ } else if (destinationX >= surface.w) {
+ // Take care of extreme positive destinations
+ destinationX -= surface.w;
+ }
+
+ // Take care of negative destinations
+ if (destinationY < 0) {
+ subRectY = -destinationY;
+ destinationY = 0;
+ } else if (destinationY >= surface.h) {
+ // Take care of extreme positive destinations
+ destinationY -= surface.h;
+ }
+
+ if (wrap) {
+ _backgroundWidth = surface.w;
+ _backgroundHeight = surface.h;
+
+ if (destinationX > 0) {
+ // Move destinationX to 0
+ subRectX = surface.w - destinationX;
+ destinationX = 0;
+ }
+
+ if (destinationY > 0) {
+ // Move destinationY to 0
+ subRectY = surface.h - destinationY;
+ destinationY = 0;
+ }
+ }
+
+ // Clip subRect to working window bounds
+ Common::Rect subRect(subRectX, subRectY, subRectX + _workingWidth, subRectY + _workingHeight);
+
+ if (!wrap) {
+ // Clip to image bounds
+ subRect.clip(surface.w, surface.h);
+ }
+
+ // Check destRect for validity
+ if (!subRect.isValidRect() || subRect.isEmpty())
+ return;
+
+ copyRectToWorkingWindow((const uint16 *)surface.getBasePtr(subRect.left, subRect.top), destinationX, destinationY, surface.w, subRect.width(), subRect.height());
+}
+
+void RenderManager::renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
+
+ renderSubRectToScreen(surface, destinationX, destinationY, wrap);
+}
+
+void RenderManager::renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
+ renderSubRectToScreen(surface, destinationX, destinationY, wrap);
+}
+
+void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+ Common::File file;
+
+ if (!file.open(fileName)) {
+ warning("Could not open file %s", fileName.c_str());
+ return;
+ }
+
+ // Read the magic number
+ // Some files are true TGA, while others are TGZ
+ uint32 fileType = file.readUint32BE();
+
+ uint32 imageWidth;
+ uint32 imageHeight;
+ Graphics::TGADecoder tga;
+ uint16 *buffer;
+ bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
+ // All ZVision images are in RGB 555
+ Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ destination.format = pixelFormat555;
+
+ bool isTGZ;
+
+ // Check for TGZ files
+ if (fileType == MKTAG('T', 'G', 'Z', '\0')) {
+ isTGZ = true;
+
+ // TGZ files have a header and then Bitmap data that is compressed with LZSS
+ uint32 decompressedSize = file.readSint32LE();
+ imageWidth = file.readSint32LE();
+ imageHeight = file.readSint32LE();
+
+ LzssReadStream lzssStream(&file);
+ buffer = (uint16 *)(new uint16[decompressedSize]);
+ lzssStream.read(buffer, decompressedSize);
+ } else {
+ isTGZ = false;
+
+ // Reset the cursor
+ file.seek(0);
+
+ // Decode
+ if (!tga.loadStream(file)) {
+ warning("Error while reading TGA image");
+ return;
+ }
+
+ Graphics::Surface tgaSurface = *(tga.getSurface());
+ imageWidth = tgaSurface.w;
+ imageHeight = tgaSurface.h;
+
+ buffer = (uint16 *)tgaSurface.getPixels();
+ }
+
+ // Flip the width and height if transposed
+ if (isTransposed) {
+ uint16 temp = imageHeight;
+ imageHeight = imageWidth;
+ imageWidth = temp;
+ }
+
+ // If the destination internal buffer is the same size as what we're copying into it,
+ // there is no need to free() and re-create
+ if (imageWidth != destination.w || imageHeight != destination.h) {
+ destination.create(imageWidth, imageHeight, pixelFormat555);
+ }
+
+ // If transposed, 'un-transpose' the data while copying it to the destination
+ // Otherwise, just do a simple copy
+ if (isTransposed) {
+ uint16 *dest = (uint16 *)destination.getPixels();
+
+ for (uint32 y = 0; y < imageHeight; ++y) {
+ uint32 columnIndex = y * imageWidth;
+
+ for (uint32 x = 0; x < imageWidth; ++x) {
+ dest[columnIndex + x] = buffer[x * imageHeight + y];
+ }
+ }
+ } else {
+ memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel);
+ }
+
+ // Cleanup
+ if (isTGZ) {
+ delete[] buffer;
+ } else {
+ tga.destroy();
+ }
+
+ // Convert in place to RGB 565 from RGB 555
+ destination.convertToInPlace(_pixelFormat);
+}
+
+void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height) {
+ uint32 destOffset = 0;
+ uint32 sourceOffset = 0;
+ uint16 *workingWindowBufferPtr = (uint16 *)_workingWindowBuffer.getBasePtr(destX, destY);
+
+ for (int32 y = 0; y < height; ++y) {
+ for (int32 x = 0; x < width; ++x) {
+ workingWindowBufferPtr[destOffset + x] = buffer[sourceOffset + x];
+ }
+
+ destOffset += _workingWidth;
+ sourceOffset += imageWidth;
+ }
+
+ if (_workingWindowDirtyRect.isEmpty()) {
+ _workingWindowDirtyRect = Common::Rect(destX, destY, destX + width, destY + height);
+ } else {
+ _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height));
+ }
+
+ // TODO: Remove this from release. It's here to make sure code that uses this function clips their destinations correctly
+ assert(_workingWindowDirtyRect.width() <= _workingWidth && _workingWindowDirtyRect.height() <= _workingHeight);
+}
+
+void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber) {
+ AlphaDataEntry entry;
+ entry.alphaColor = alphaColor;
+ entry.data = new Graphics::Surface();
+ entry.data->create(width, height, _pixelFormat);
+ entry.destX = destX;
+ entry.destY = destY;
+ entry.width = width;
+ entry.height = height;
+
+ uint32 sourceOffset = 0;
+ uint32 destOffset = 0;
+ uint16 *surfacePtr = (uint16 *)entry.data->getPixels();
+
+ for (int32 y = 0; y < height; ++y) {
+ for (int32 x = 0; x < width; ++x) {
+ surfacePtr[destOffset + x] = buffer[sourceOffset + x];
+ }
+
+ destOffset += width;
+ sourceOffset += imageWidth;
+ }
+
+ _alphaDataEntries[idNumber] = entry;
+}
+
+Common::Rect RenderManager::renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
+ AlphaDataEntry entry;
+ entry.alphaColor = 0;
+ entry.destX = destX;
+ entry.destY = destY;
+
+ // Draw the text to the working window
+ entry.data = font->drawTextToSurface(text, textColor, maxWidth, maxHeight, align, wrap);
+ entry.width = entry.data->w;
+ entry.height = entry.data->h;
+
+ _alphaDataEntries[idNumber] = entry;
+
+ return Common::Rect(destX, destY, destX + entry.width, destY + entry.height);
+}
+
+const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) {
+ // Convert from screen space to working window space
+ Common::Point newPoint(point - Common::Point(_workingWindow.left, _workingWindow.top));
+
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ newPoint = _renderTable.convertWarpedCoordToFlatCoord(newPoint);
+ }
+
+ if (state == RenderTable::PANORAMA) {
+ newPoint -= (Common::Point(_screenCenterX, 0) - _backgroundOffset);
+ } else if (state == RenderTable::TILT) {
+ newPoint -= (Common::Point(0, _screenCenterY) - _backgroundOffset);
+ }
+
+ if (newPoint.x < 0)
+ newPoint.x += _backgroundWidth;
+ else if (newPoint.x >= _backgroundWidth)
+ newPoint.x -= _backgroundWidth;
+ if (newPoint.y < 0)
+ newPoint.y += _backgroundHeight;
+ else if (newPoint.y >= _backgroundHeight)
+ newPoint.y -= _backgroundHeight;
+
+ return newPoint;
+}
+
+const Common::Point RenderManager::imageSpaceToWorkingWindowSpace(const Common::Point &point) {
+ Common::Point newPoint(point);
+
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA) {
+ newPoint += (Common::Point(_screenCenterX, 0) - _backgroundOffset);
+ } else if (state == RenderTable::TILT) {
+ newPoint += (Common::Point(0, _screenCenterY) - _backgroundOffset);
+ }
+
+ return newPoint;
+}
+
+bool RenderManager::clipRectToWorkingWindow(Common::Rect &rect) {
+ if (!_workingWindow.contains(rect)) {
+ return false;
+ }
+
+ // We can't clip against the actual working window rect because it's in screen space
+ // But rect is in working window space
+ rect.clip(_workingWidth, _workingHeight);
+ return true;
+}
+
+RenderTable *RenderManager::getRenderTable() {
+ return &_renderTable;
+}
+
+void RenderManager::setBackgroundImage(const Common::String &fileName) {
+ readImageToSurface(fileName, _currentBackground);
+
+ moveBackground(0);
+}
+
+void RenderManager::setBackgroundPosition(int offset) {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::TILT) {
+ _backgroundOffset.x = 0;
+ _backgroundOffset.y = offset;
+ } else if (state == RenderTable::PANORAMA) {
+ _backgroundOffset.x = offset;
+ _backgroundOffset.y = 0;
+ } else {
+ _backgroundOffset.x = 0;
+ _backgroundOffset.y = 0;
+ }
+}
+
+void RenderManager::setBackgroundVelocity(int velocity) {
+ // setBackgroundVelocity(0) will be called quite often, so make sure
+ // _backgroundInverseVelocity isn't already 0 to prevent an extraneous assignment
+ if (velocity == 0) {
+ if (_backgroundInverseVelocity != 0) {
+ _backgroundInverseVelocity = 0;
+ }
+ } else {
+ _backgroundInverseVelocity = 1000 / velocity;
+ }
+}
+
+void RenderManager::moveBackground(int offset) {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::TILT) {
+ _backgroundOffset += Common::Point(0, offset);
+
+ _backgroundOffset.y = CLIP<int16>(_backgroundOffset.y, _screenCenterY, (int16)_backgroundHeight - _screenCenterY);
+
+ renderImageToScreen(_currentBackground, 0, _screenCenterY - _backgroundOffset.y, true);
+ } else if (state == RenderTable::PANORAMA) {
+ _backgroundOffset += Common::Point(offset, 0);
+
+ if (_backgroundOffset.x <= -_backgroundWidth)
+ _backgroundOffset.x += _backgroundWidth;
+ else if (_backgroundOffset.x >= _backgroundWidth)
+ _backgroundOffset.x -= _backgroundWidth;
+
+ renderImageToScreen(_currentBackground, _screenCenterX - _backgroundOffset.x, 0, true);
+ } else {
+ renderImageToScreen(_currentBackground, 0, 0);
+ }
+}
+
+uint32 RenderManager::getCurrentBackgroundOffset() {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+
+ if (state == RenderTable::PANORAMA) {
+ return _backgroundOffset.x;
+ } else if (state == RenderTable::TILT) {
+ return _backgroundOffset.y;
+ } else {
+ return 0;
+ }
+}
+
+Graphics::Surface *RenderManager::tranposeSurface(const Graphics::Surface *surface) {
+ Graphics::Surface *tranposedSurface = new Graphics::Surface();
+ tranposedSurface->create(surface->h, surface->w, surface->format);
+
+ const uint16 *source = (const uint16 *)surface->getPixels();
+ uint16 *dest = (uint16 *)tranposedSurface->getPixels();
+
+ for (uint32 y = 0; y < tranposedSurface->h; ++y) {
+ uint32 columnIndex = y * tranposedSurface->w;
+
+ for (uint32 x = 0; x < tranposedSurface->w; ++x) {
+ dest[columnIndex + x] = source[x * surface->w + y];
+ }
+ }
+
+ return tranposedSurface;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h
new file mode 100644
index 0000000000..cb71308bc3
--- /dev/null
+++ b/engines/zvision/graphics/render_manager.h
@@ -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.
+ *
+ */
+
+#ifndef ZVISION_RENDER_MANAGER_H
+#define ZVISION_RENDER_MANAGER_H
+
+#include "zvision/graphics/render_table.h"
+#include "zvision/fonts/truetype_font.h"
+
+#include "common/rect.h"
+#include "common/hashmap.h"
+
+#include "graphics/surface.h"
+
+
+class OSystem;
+
+namespace Common {
+class String;
+class SeekableReadStream;
+}
+
+namespace Video {
+class VideoDecoder;
+}
+
+namespace ZVision {
+
+class RenderManager {
+public:
+ RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat);
+ ~RenderManager();
+
+private:
+ struct AlphaDataEntry {
+ Graphics::Surface *data;
+ uint16 alphaColor;
+ uint16 destX;
+ uint16 destY;
+ uint16 width;
+ uint16 height;
+ };
+
+ typedef Common::HashMap<uint32, AlphaDataEntry> AlphaEntryMap;
+
+private:
+ OSystem *_system;
+ const Graphics::PixelFormat _pixelFormat;
+
+ // A buffer the exact same size as the workingWindow
+ // This buffer stores everything un-warped, then does a warp at the end of the frame
+ Graphics::Surface _workingWindowBuffer;
+ // A buffer representing the entire screen. Any graphical updates are first done with this buffer
+ // before actually being blitted to the screen
+ Graphics::Surface _backBuffer;
+ // A list of Alpha Entries that need to be blitted to the backbuffer
+ AlphaEntryMap _alphaDataEntries;
+
+ // A rectangle representing the portion of the working window where the pixels have been changed since last frame
+ Common::Rect _workingWindowDirtyRect;
+ // A rectangle representing the portion of the backbuffer where the pixels have been changed since last frame
+ Common::Rect _backBufferDirtyRect;
+
+ /** Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() */
+ const int _workingWidth;
+ /** Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() */
+ const int _workingHeight;
+ /** Center of the screen in the x direction */
+ const int _screenCenterX;
+ /** Center of the screen in the y direction */
+ const int _screenCenterY;
+
+ /**
+ * A Rectangle centered inside the actual window. All in-game coordinates
+ * are given in this coordinate space. Also, all images are clipped to the
+ * edges of this Rectangle
+ */
+ const Common::Rect _workingWindow;
+ /** Used to warp the background image */
+ RenderTable _renderTable;
+
+ Graphics::Surface _currentBackground;
+ /** The (x1,y1) coordinates of the subRectangle of the background that is currently displayed on the screen */
+ Common::Point _backgroundOffset;
+ /** The width of the current background image */
+ uint16 _backgroundWidth;
+ /** The height of the current background image */
+ uint16 _backgroundHeight;
+
+ /**
+ * The "velocity" at which the background image is panning. We actually store the inverse of velocity (ms/pixel instead of pixels/ms)
+ * because it allows you to accumulate whole pixels 'steps' instead of rounding pixels every frame
+ */
+ int _backgroundInverseVelocity;
+ /** Holds any 'leftover' milliseconds between frames */
+ uint _accumulatedVelocityMilliseconds;
+
+public:
+ void initialize();
+ /**
+ * Rotates the background image in accordance to the current _backgroundInverseVelocity
+ *
+ * @param deltaTimeInMillis The amount of time that has passed since the last frame
+ */
+ void update(uint deltaTimeInMillis);
+
+ /**
+ * Renders the current state of the backbuffer to the screen
+ */
+ void renderBackbufferToScreen();
+
+ /**
+ * Renders all AlphaEntries to the backbuffer
+ */
+ void processAlphaEntries();
+ /**
+ * Clears the AlphaEntry list
+ */
+ void clearAlphaEntries() { _alphaDataEntries.clear(); }
+ /**
+ * Removes a specific AlphaEntry from the list
+ *
+ * @param idNumber The id number identifing the AlphaEntry
+ */
+ void removeAlphaEntry(uint32 idNumber) { _alphaDataEntries.erase(idNumber); }
+
+ /**
+ * Copies a sub-rectangle of a buffer to the working window
+ *
+ * @param buffer The pixel data to copy to the working window
+ * @param destX The X destination in the working window where the subRect of data should be put
+ * @param destY The Y destination in the working window where the subRect of data should be put
+ * @param imageWidth The width of the source image
+ * @param width The width of the sub rectangle
+ * @param height The height of the sub rectangle
+ */
+ void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height);
+ /**
+ * Copies a sub-rectangle of a buffer to the working window with binary alpha support.
+ *
+ * @param buffer The pixel data to copy to the working window
+ * @param destX The X destination in the working window where the subRect of data should be put
+ * @param destY The Y destination in the working window where the subRect of data should be put
+ * @param imageWidth The width of the source image
+ * @param width The width of the sub rectangle
+ * @param height The height of the sub rectangle
+ * @param alphaColor The color to interpret as meaning 'transparent'
+ * @param idNumber A unique identifier for the data being copied over.
+ */
+ void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber);
+
+ /**
+ * Renders the supplied text to the working window
+ *
+ * @param idNumber A unique identifier for the text
+ * @param text The text to be rendered
+ * @param font The font to use to render the text
+ * @param destX The X destination in the working window where the text should be rendered
+ * @param destY The Y destination in the working window where the text should be rendered
+ * @param textColor The color to render the text with (in RBG 565)
+ * @param maxWidth The max width the text should take up.
+ * @param maxHeight The max height the text should take up.
+ * @param align The alignment of the text within the bounds of maxWidth
+ * @param wrap If true, any words extending past maxWidth will wrap to a new line. If false, ellipses will be rendered to show that the text didn't fit
+ * @return A rectangle representing where the text was drawn in the working window
+ */
+ Common::Rect renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight = -1, Graphics::TextAlign align = Graphics::kTextAlignLeft, bool wrap = true);
+
+ /**
+ * Fills the entire workingWindow with the specified color. Internally, the color
+ * will be converted to RGB 565 and then blitted.
+ *
+ * @param color The color to fill the working window with. (In RGB 555)
+ */
+ void clearWorkingWindowTo555Color(uint16 color);
+
+ /**
+ * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame.
+ * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space!
+ *
+ * @param fileName Name of the image file
+ * @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
+ * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
+ */
+ void renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap = false);
+
+ /**
+ * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame.
+ * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space!
+ *
+ * @param stream Surface to read the image data from
+ * @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
+ * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
+ */
+ void renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap = false);
+
+ /**
+ * Sets the current background image to be used by the RenderManager and immediately
+ * blits it to the screen. (It won't show up until the end of the frame)
+ *
+ * @param fileName The name of the image file
+ */
+ void setBackgroundImage(const Common::String &fileName);
+
+ /**
+ * Set the background position (_backgroundOffset). If the current RenderState is PANORAMA, the offset
+ * will be in the horizontal direction. If the current RenderState is TILT, the offset will be in the
+ * vertical direction.
+ *
+ * This method will not render anything on the screen. So if nothing else is called that renders the
+ * background, the change won't be seen until next frame.
+ *
+ * @param offset The amount to offset the background
+ */
+ void setBackgroundPosition(int offset);
+
+ /**
+ * Set the background scroll velocity. Negative velocities correspond to left / up scrolling and
+ * positive velocities correspond to right / down scrolling
+ *
+ * @param velocity Velocity
+ */
+ void setBackgroundVelocity(int velocity);
+
+ /**
+ * Converts a point in screen coordinate space to image coordinate space
+ *
+ * @param point Point in screen coordinate space
+ * @return Point in image coordinate space
+ */
+ const Common::Point screenSpaceToImageSpace(const Common::Point &point);
+ /**
+ * Converts a point in image coordinate space to ***PRE-WARP***
+ * working window coordinate space
+ *
+ * @param point Point in image coordinate space
+ * @return Point in PRE-WARP working window coordinate space
+ */
+ const Common::Point imageSpaceToWorkingWindowSpace(const Common::Point &point);
+
+ /**
+ * Clip a rectangle to the working window. If it returns false, the original rect
+ * is not inside the working window.
+ *
+ * @param rect The rectangle to clip against the working window
+ * @return Is rect at least partially inside the working window (true) or completely outside (false)
+ */
+ bool clipRectToWorkingWindow(Common::Rect &rect);
+
+ RenderTable *getRenderTable();
+ uint32 getCurrentBackgroundOffset();
+ const Graphics::Surface *getBackBuffer() { return &_backBuffer; }
+
+ /**
+ * Creates a copy of surface and transposes the data.
+ *
+ * Note: The user is responsible for calling free() on the returned surface
+ * and then deleting it
+ *
+ * @param surface The data to be transposed
+ * @return A copy of the surface with the data transposed
+ */
+ static Graphics::Surface *tranposeSurface(const Graphics::Surface *surface);
+
+private:
+ /**
+ * Renders a subRectangle of an image to the backbuffer. The destinationRect and SubRect
+ * will be clipped to image bound and to working window bounds
+ *
+ * @param buffer Pointer to (0, 0) of the image data
+ * @param imageWidth The width of the original image (not of the subRectangle)
+ * @param imageHeight The width of the original image (not of the subRectangle)
+ * @param horizontalPitch The horizontal pitch of the original image
+ * @param destinationX The x coordinate (in working window space) of where to put the final image
+ * @param destinationY The y coordinate (in working window space) of where to put the final image
+ * @param subRectangle A rectangle representing the part of the image that should be rendered
+ * @param wrap Should the image wrap (tile) if it doesn't completely fill the screen?
+ */
+ void renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap);
+
+ /**
+ * Reads an image file pixel data into a Surface buffer. In the process
+ * it converts the pixel data from RGB 555 to RGB 565. Also, if the image
+ * is transposed, it will un-transpose the pixel data. The function will
+ * call destination::create() if the dimensions of destination do not match
+ * up with the dimensions of the image.
+ *
+ * @param fileName The name of a .tga file
+ * @param destination A reference to the Surface to store the pixel data in
+ */
+ void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination);
+
+ /**
+ * Move the background image by an offset. If we are currently in Panorama mode,
+ * the offset will correspond to a horizontal motion. If we are currently in Tilt mode,
+ * the offset will correspond to a vertical motion. This function should not be called
+ * if we are in Flat mode.
+ *
+ * The RenderManager will take care of wrapping the image.
+ * Ex: If the image has width 1400px, it is legal to offset 1500px.
+ *
+ * @param offset The amount to move the background
+ */
+ void moveBackground(int offset);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/graphics/render_table.cpp b/engines/zvision/graphics/render_table.cpp
new file mode 100644
index 0000000000..ffd42e6a60
--- /dev/null
+++ b/engines/zvision/graphics/render_table.cpp
@@ -0,0 +1,240 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/graphics/render_table.h"
+
+#include "common/rect.h"
+
+#include "graphics/colormasks.h"
+
+
+namespace ZVision {
+
+RenderTable::RenderTable(uint numColumns, uint numRows)
+ : _numRows(numRows),
+ _numColumns(numColumns),
+ _renderState(FLAT) {
+ assert(numRows != 0 && numColumns != 0);
+
+ _internalBuffer = new Common::Point[numRows * numColumns];
+}
+
+RenderTable::~RenderTable() {
+ delete[] _internalBuffer;
+}
+
+void RenderTable::setRenderState(RenderState newState) {
+ _renderState = newState;
+
+ switch (newState) {
+ case PANORAMA:
+ _panoramaOptions.fieldOfView = 27.0f;
+ _panoramaOptions.linearScale = 0.55f;
+ _panoramaOptions.reverse = false;
+ break;
+ case TILT:
+ _tiltOptions.fieldOfView = 27.0f;
+ _tiltOptions.linearScale = 0.55f;
+ _tiltOptions.reverse = false;
+ break;
+ case FLAT:
+ // Intentionally left empty
+ break;
+ }
+}
+
+const Common::Point RenderTable::convertWarpedCoordToFlatCoord(const Common::Point &point) {
+ // If we're outside the range of the RenderTable, no warping is happening. Return the maximum image coords
+ if (point.x >= (int16)_numColumns || point.y >= (int16)_numRows || point.x < 0 || point.y < 0) {
+ int16 x = CLIP<int16>(point.x, 0, (int16)_numColumns);
+ int16 y = CLIP<int16>(point.y, 0, (int16)_numRows);
+ return Common::Point(x, y);
+ }
+
+ uint32 index = point.y * _numColumns + point.x;
+
+ Common::Point newPoint(point);
+ newPoint.x += _internalBuffer[index].x;
+ newPoint.y += _internalBuffer[index].y;
+
+ return newPoint;
+}
+
+uint16 mixTwoRGB(uint16 colorOne, uint16 colorTwo, float percentColorOne) {
+ assert(percentColorOne < 1.0f);
+
+ float rOne = float((colorOne & Graphics::ColorMasks<555>::kRedMask) >> Graphics::ColorMasks<555>::kRedShift);
+ float rTwo = float((colorTwo & Graphics::ColorMasks<555>::kRedMask) >> Graphics::ColorMasks<555>::kRedShift);
+ float gOne = float((colorOne & Graphics::ColorMasks<555>::kGreenMask) >> Graphics::ColorMasks<555>::kGreenShift);
+ float gTwo = float((colorTwo & Graphics::ColorMasks<555>::kGreenMask) >> Graphics::ColorMasks<555>::kGreenShift);
+ float bOne = float((colorOne & Graphics::ColorMasks<555>::kBlueMask) >> Graphics::ColorMasks<555>::kBlueShift);
+ float bTwo = float((colorTwo & Graphics::ColorMasks<555>::kBlueMask) >> Graphics::ColorMasks<555>::kBlueShift);
+
+ float rFinal = rOne * percentColorOne + rTwo * (1.0f - percentColorOne);
+ float gFinal = gOne * percentColorOne + gTwo * (1.0f - percentColorOne);
+ float bFinal = bOne * percentColorOne + bTwo * (1.0f - percentColorOne);
+
+ uint16 returnColor = (byte(rFinal + 0.5f) << Graphics::ColorMasks<555>::kRedShift) |
+ (byte(gFinal + 0.5f) << Graphics::ColorMasks<555>::kGreenShift) |
+ (byte(bFinal + 0.5f) << Graphics::ColorMasks<555>::kBlueShift);
+
+ return returnColor;
+}
+
+void RenderTable::mutateImage(uint16 *sourceBuffer, uint16* destBuffer, uint32 destWidth, const Common::Rect &subRect) {
+ uint32 destOffset = 0;
+
+ for (int16 y = subRect.top; y < subRect.bottom; ++y) {
+ uint32 sourceOffset = y * _numColumns;
+
+ for (int16 x = subRect.left; x < subRect.right; ++x) {
+ uint32 normalizedX = x - subRect.left;
+ uint32 index = sourceOffset + x;
+
+ // RenderTable only stores offsets from the original coordinates
+ uint32 sourceYIndex = y + _internalBuffer[index].y;
+ uint32 sourceXIndex = x + _internalBuffer[index].x;
+
+ destBuffer[destOffset + normalizedX] = sourceBuffer[sourceYIndex * _numColumns + sourceXIndex];
+ }
+
+ destOffset += destWidth;
+ }
+}
+
+void RenderTable::generateRenderTable() {
+ switch (_renderState) {
+ case ZVision::RenderTable::PANORAMA:
+ generatePanoramaLookupTable();
+ break;
+ case ZVision::RenderTable::TILT:
+ generateTiltLookupTable();
+ break;
+ case ZVision::RenderTable::FLAT:
+ // Intentionally left empty
+ break;
+ }
+}
+
+void RenderTable::generatePanoramaLookupTable() {
+ memset(_internalBuffer, 0, _numRows * _numColumns * sizeof(uint16));
+
+ float halfWidth = (float)_numColumns / 2.0f;
+ float halfHeight = (float)_numRows / 2.0f;
+
+ float fovInRadians = (_panoramaOptions.fieldOfView * M_PI / 180.0f);
+ float cylinderRadius = halfHeight / tan(fovInRadians);
+
+ for (uint x = 0; x < _numColumns; ++x) {
+ // Add an offset of 0.01 to overcome zero tan/atan issue (vertical line on half of screen)
+ // Alpha represents the horizontal angle between the viewer at the center of a cylinder and x
+ float alpha = atan(((float)x - halfWidth + 0.01f) / cylinderRadius);
+
+ // To get x in cylinder coordinates, we just need to calculate the arc length
+ // We also scale it by _panoramaOptions.linearScale
+ int32 xInCylinderCoords = int32(floor((cylinderRadius * _panoramaOptions.linearScale * alpha) + halfWidth));
+
+ float cosAlpha = cos(alpha);
+
+ for (uint y = 0; y < _numRows; ++y) {
+ // To calculate y in cylinder coordinates, we can do similar triangles comparison,
+ // comparing the triangle from the center to the screen and from the center to the edge of the cylinder
+ int32 yInCylinderCoords = int32(floor(halfHeight + ((float)y - halfHeight) * cosAlpha));
+
+ uint32 index = y * _numColumns + x;
+
+ // Only store the (x,y) offsets instead of the absolute positions
+ _internalBuffer[index].x = xInCylinderCoords - x;
+ _internalBuffer[index].y = yInCylinderCoords - y;
+ }
+ }
+}
+
+void RenderTable::generateTiltLookupTable() {
+ float halfWidth = (float)_numColumns / 2.0f;
+ float halfHeight = (float)_numRows / 2.0f;
+
+ float fovInRadians = (_tiltOptions.fieldOfView * M_PI / 180.0f);
+ float cylinderRadius = halfWidth / tan(fovInRadians);
+
+ for (uint y = 0; y < _numRows; ++y) {
+
+ // Add an offset of 0.01 to overcome zero tan/atan issue (horizontal line on half of screen)
+ // Alpha represents the vertical angle between the viewer at the center of a cylinder and y
+ float alpha = atan(((float)y - halfHeight + 0.01f) / cylinderRadius);
+
+ // To get y in cylinder coordinates, we just need to calculate the arc length
+ // We also scale it by _tiltOptions.linearScale
+ int32 yInCylinderCoords = int32(floor((cylinderRadius * _tiltOptions.linearScale * alpha) + halfHeight));
+
+ float cosAlpha = cos(alpha);
+ uint32 columnIndex = y * _numColumns;
+
+ for (uint x = 0; x < _numColumns; ++x) {
+ // To calculate x in cylinder coordinates, we can do similar triangles comparison,
+ // comparing the triangle from the center to the screen and from the center to the edge of the cylinder
+ int32 xInCylinderCoords = int32(floor(halfWidth + ((float)x - halfWidth) * cosAlpha));
+
+ uint32 index = columnIndex + x;
+
+ // Only store the (x,y) offsets instead of the absolute positions
+ _internalBuffer[index].x = xInCylinderCoords - x;
+ _internalBuffer[index].y = yInCylinderCoords - y;
+ }
+ }
+}
+
+void RenderTable::setPanoramaFoV(float fov) {
+ assert(fov > 0.0f);
+
+ _panoramaOptions.fieldOfView = fov;
+}
+
+void RenderTable::setPanoramaScale(float scale) {
+ assert(scale > 0.0f);
+
+ _panoramaOptions.linearScale = scale;
+}
+
+void RenderTable::setPanoramaReverse(bool reverse) {
+ _panoramaOptions.reverse = reverse;
+}
+
+void RenderTable::setTiltFoV(float fov) {
+ assert(fov > 0.0f);
+
+ _tiltOptions.fieldOfView = fov;
+}
+
+void RenderTable::setTiltScale(float scale) {
+ assert(scale > 0.0f);
+
+ _tiltOptions.linearScale = scale;
+}
+
+void RenderTable::setTiltReverse(bool reverse) {
+ _tiltOptions.reverse = reverse;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/render_table.h b/engines/zvision/graphics/render_table.h
new file mode 100644
index 0000000000..898091193a
--- /dev/null
+++ b/engines/zvision/graphics/render_table.h
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_RENDER_TABLE_H
+#define ZVISION_RENDER_TABLE_H
+
+#include "common/rect.h"
+
+
+namespace ZVision {
+
+class RenderTable {
+public:
+ RenderTable(uint numRows, uint numColumns);
+ ~RenderTable();
+
+public:
+ enum RenderState {
+ PANORAMA,
+ TILT,
+ FLAT
+ };
+
+private:
+ uint _numColumns, _numRows;
+ Common::Point *_internalBuffer;
+ RenderState _renderState;
+
+ struct {
+ float fieldOfView;
+ float linearScale;
+ bool reverse;
+ } _panoramaOptions;
+
+ // TODO: See if tilt and panorama need to have separate options
+ struct {
+ float fieldOfView;
+ float linearScale;
+ bool reverse;
+ } _tiltOptions;
+
+public:
+ RenderState getRenderState() { return _renderState; }
+ void setRenderState(RenderState newState);
+
+ const Common::Point convertWarpedCoordToFlatCoord(const Common::Point &point);
+
+ void mutateImage(uint16 *sourceBuffer, uint16* destBuffer, uint32 destWidth, const Common::Rect &subRect);
+ void generateRenderTable();
+
+ void setPanoramaFoV(float fov);
+ void setPanoramaScale(float scale);
+ void setPanoramaReverse(bool reverse);
+
+ void setTiltFoV(float fov);
+ void setTiltScale(float scale);
+ void setTiltReverse(bool reverse);
+
+private:
+ void generatePanoramaLookupTable();
+ void generateTiltLookupTable();
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/inventory/inventory_manager.h b/engines/zvision/inventory/inventory_manager.h
new file mode 100644
index 0000000000..ae6d116b18
--- /dev/null
+++ b/engines/zvision/inventory/inventory_manager.h
@@ -0,0 +1,28 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_INVENTORY_MANAGER_H
+#define ZVISION_INVENTORY_MANAGER_H
+
+// TODO: Implement InventoryManager
+
+#endif
diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk
new file mode 100644
index 0000000000..4cf9c989cd
--- /dev/null
+++ b/engines/zvision/module.mk
@@ -0,0 +1,43 @@
+MODULE := engines/zvision
+
+MODULE_OBJS := \
+ animation/rlf_animation.o \
+ archives/zfs_archive.o \
+ core/console.o \
+ core/events.o \
+ core/save_manager.o \
+ cursors/cursor.o \
+ cursors/cursor_manager.o \
+ detection.o \
+ fonts/truetype_font.o \
+ graphics/render_manager.o \
+ graphics/render_table.o \
+ scripting/actions.o \
+ scripting/control.o \
+ scripting/controls/animation_control.o \
+ scripting/controls/input_control.o \
+ scripting/controls/lever_control.o \
+ scripting/controls/push_toggle_control.o \
+ scripting/controls/timer_node.o \
+ scripting/scr_file_handling.o \
+ scripting/script_manager.o \
+ sound/zork_raw.o \
+ strings/string_manager.o \
+ utility/clock.o \
+ utility/lzss_read_stream.o \
+ utility/single_value_container.o \
+ utility/utility.o \
+ video/video.o \
+ video/zork_avi_decoder.o \
+ zvision.o
+
+MODULE_DIRS += \
+ engines/zvision
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_ZVISION), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
new file mode 100644
index 0000000000..878fa752d5
--- /dev/null
+++ b/engines/zvision/scripting/actions.cpp
@@ -0,0 +1,401 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/actions.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/sound/zork_raw.h"
+#include "zvision/video/zork_avi_decoder.h"
+#include "zvision/scripting/controls/timer_node.h"
+#include "zvision/scripting/controls/animation_control.h"
+
+#include "common/file.h"
+
+#include "audio/decoders/wave.h"
+
+
+namespace ZVision {
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionAdd
+//////////////////////////////////////////////////////////////////////////////
+
+ActionAdd::ActionAdd(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%u,%u)", &_key, &_value);
+}
+
+bool ActionAdd::execute(ZVision *engine) {
+ engine->getScriptManager()->addToStateValue(_key, _value);
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionAssign
+//////////////////////////////////////////////////////////////////////////////
+
+ActionAssign::ActionAssign(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%u, %u)", &_key, &_value);
+}
+
+bool ActionAssign::execute(ZVision *engine) {
+ engine->getScriptManager()->setStateValue(_key, _value);
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionAttenuate
+//////////////////////////////////////////////////////////////////////////////
+
+ActionAttenuate::ActionAttenuate(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%u, %d)", &_key, &_attenuation);
+}
+
+bool ActionAttenuate::execute(ZVision *engine) {
+ // TODO: Implement
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionChangeLocation
+//////////////////////////////////////////////////////////////////////////////
+
+ActionChangeLocation::ActionChangeLocation(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%c,%c,%c%c,%u)", &_world, &_room, &_node, &_view, &_offset);
+}
+
+bool ActionChangeLocation::execute(ZVision *engine) {
+ // We can't directly call ScriptManager::ChangeLocationIntern() because doing so clears all the Puzzles, and thus would corrupt the current puzzle checking
+ engine->getScriptManager()->changeLocation(_world, _room, _node, _view, _offset);
+ // Tell the puzzle system to stop checking any more puzzles
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionCrossfade
+//////////////////////////////////////////////////////////////////////////////
+
+ActionCrossfade::ActionCrossfade(const Common::String &line) {
+ sscanf(line.c_str(),
+ "%*[^(](%u %u %u %u %u %u %u)",
+ &_keyOne, &_keyTwo, &_oneStartVolume, &_twoStartVolume, &_oneEndVolume, &_twoEndVolume, &_timeInMillis);
+}
+
+bool ActionCrossfade::execute(ZVision *engine) {
+ // TODO: Implement
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionDisableControl
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDisableControl::ActionDisableControl(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%u)", &_key);
+}
+
+bool ActionDisableControl::execute(ZVision *engine) {
+ debug("Disabling control %u", _key);
+
+ ScriptManager *scriptManager = engine->getScriptManager();
+ scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) | ScriptManager::DISABLED);
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionEnableControl
+//////////////////////////////////////////////////////////////////////////////
+
+ActionEnableControl::ActionEnableControl(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^(](%u)", &_key);
+}
+
+bool ActionEnableControl::execute(ZVision *engine) {
+ debug("Enabling control %u", _key);
+
+ ScriptManager *scriptManager = engine->getScriptManager();
+ scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) & ~ScriptManager::DISABLED);
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionMusic
+//////////////////////////////////////////////////////////////////////////////
+
+ActionMusic::ActionMusic(const Common::String &line) : _volume(255) {
+ uint type;
+ char fileNameBuffer[25];
+ uint loop;
+ uint volume = 255;
+
+ sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%u %25s %u %u)", &_key, &type, fileNameBuffer, &loop, &volume);
+
+ // type 4 are midi sound effect files
+ if (type == 4) {
+ _soundType = Audio::Mixer::kSFXSoundType;
+ _fileName = Common::String::format("midi/%s/%u.wav", fileNameBuffer, loop);
+ _loop = false;
+ } else {
+ // TODO: See what the other types are so we can specify the correct Mixer::SoundType. In the meantime use kPlainSoundType
+ _soundType = Audio::Mixer::kPlainSoundType;
+ _fileName = Common::String(fileNameBuffer);
+ _loop = loop == 1 ? true : false;
+ }
+
+ // Volume is optional. If it doesn't appear, assume full volume
+ if (volume != 255) {
+ // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255]
+ _volume = volume * 255 / 100;
+ }
+}
+
+bool ActionMusic::execute(ZVision *engine) {
+ Audio::RewindableAudioStream *audioStream;
+
+ if (_fileName.contains(".wav")) {
+ Common::File *file = new Common::File();
+ if (file->open(_fileName)) {
+ audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ } else {
+ warning("Unable to open %s", _fileName.c_str());
+ return false;
+ }
+ } else {
+ audioStream = makeRawZorkStream(_fileName, engine);
+ }
+
+ if (_loop) {
+ Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
+ engine->_mixer->playStream(_soundType, 0, loopingAudioStream, -1, _volume);
+ } else {
+ engine->_mixer->playStream(_soundType, 0, audioStream, -1, _volume);
+ }
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionPreloadAnimation
+//////////////////////////////////////////////////////////////////////////////
+
+ActionPreloadAnimation::ActionPreloadAnimation(const Common::String &line) {
+ char fileName[25];
+
+ // The two %*u are always 0 and dont seem to have a use
+ sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%25s %*u %*u %u %u)", &_key, fileName, &_mask, &_framerate);
+
+ _fileName = Common::String(fileName);
+}
+
+bool ActionPreloadAnimation::execute(ZVision *engine) {
+ // TODO: We ignore the mask and framerate atm. Mask refers to a key color used for binary alpha. We assume the framerate is the default framerate embedded in the videos
+
+ // TODO: Check if the Control already exists
+
+ // Create the control, but disable it until PlayPreload is called
+ ScriptManager *scriptManager = engine->getScriptManager();
+ scriptManager->addControl(new AnimationControl(engine, _key, _fileName));
+ scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) | ScriptManager::DISABLED);
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionPlayAnimation
+//////////////////////////////////////////////////////////////////////////////
+
+ActionPlayAnimation::ActionPlayAnimation(const Common::String &line) {
+ char fileName[25];
+
+ // The two %*u are always 0 and dont seem to have a use
+ sscanf(line.c_str(),
+ "%*[^:]:%*[^:]:%u(%25s %u %u %u %u %u %u %u %*u %*u %u %u)",
+ &_key, fileName, &_x, &_y, &_width, &_height, &_start, &_end, &_loopCount, &_mask, &_framerate);
+
+ _fileName = Common::String(fileName);
+}
+
+bool ActionPlayAnimation::execute(ZVision *engine) {
+ // TODO: Implement
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionPlayPreloadAnimation
+//////////////////////////////////////////////////////////////////////////////
+
+ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(const Common::String &line) {
+ sscanf(line.c_str(),
+ "%*[^:]:%*[^:]:%u(%u %u %u %u %u %u %u %u)",
+ &_animationKey, &_controlKey, &_x1, &_y1, &_x2, &_y2, &_startFrame, &_endFrame, &_loopCount);
+}
+
+bool ActionPlayPreloadAnimation::execute(ZVision *engine) {
+ // Find the control
+ AnimationControl *control = (AnimationControl *)engine->getScriptManager()->getControl(_controlKey);
+
+ // Set the needed values within the control
+ control->setAnimationKey(_animationKey);
+ control->setLoopCount(_loopCount);
+ control->setXPos(_x1);
+ control->setYPost(_y1);
+
+ // Enable the control. ScriptManager will take care of the rest
+ control->enable();
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionQuit
+//////////////////////////////////////////////////////////////////////////////
+
+bool ActionQuit::execute(ZVision *engine) {
+ engine->quitGame();
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionRandom
+//////////////////////////////////////////////////////////////////////////////
+
+ActionRandom::ActionRandom(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^:]:%*[^:]:%u, %u)", &_key, &_max);
+}
+
+bool ActionRandom::execute(ZVision *engine) {
+ uint randNumber = engine->getRandomSource()->getRandomNumber(_max);
+ engine->getScriptManager()->setStateValue(_key, randNumber);
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionSetPartialScreen
+//////////////////////////////////////////////////////////////////////////////
+
+ActionSetPartialScreen::ActionSetPartialScreen(const Common::String &line) {
+ char fileName[25];
+ uint color;
+
+ sscanf(line.c_str(), "%*[^(](%u %u %25s %*u %u)", &_x, &_y, fileName, &color);
+
+ _fileName = Common::String(fileName);
+
+ if (color > 0xFFFF) {
+ warning("Background color for ActionSetPartialScreen is bigger than a uint16");
+ }
+ _backgroundColor = color;
+}
+
+bool ActionSetPartialScreen::execute(ZVision *engine) {
+ RenderManager *renderManager = engine->getRenderManager();
+
+ if (_backgroundColor > 0) {
+ renderManager->clearWorkingWindowTo555Color(_backgroundColor);
+ }
+ renderManager->renderImageToScreen(_fileName, _x, _y);
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionSetScreen
+//////////////////////////////////////////////////////////////////////////////
+
+ActionSetScreen::ActionSetScreen(const Common::String &line) {
+ char fileName[25];
+ sscanf(line.c_str(), "%*[^(](%25[^)])", fileName);
+
+ _fileName = Common::String(fileName);
+}
+
+bool ActionSetScreen::execute(ZVision *engine) {
+ engine->getRenderManager()->setBackgroundImage(_fileName);
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionStreamVideo
+//////////////////////////////////////////////////////////////////////////////
+
+ActionStreamVideo::ActionStreamVideo(const Common::String &line) {
+ char fileName[25];
+ uint skippable;
+
+ sscanf(line.c_str(), "%*[^(](%25s %u %u %u %u %u %u)", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skippable);
+
+ _fileName = Common::String(fileName);
+ _skippable = (skippable == 0) ? false : true;
+}
+
+bool ActionStreamVideo::execute(ZVision *engine) {
+ ZorkAVIDecoder decoder;
+ if (!decoder.loadFile(_fileName)) {
+ return true;
+ }
+
+ Common::Rect destRect;
+ if ((_flags & DIFFERENT_DIMENSIONS) == DIFFERENT_DIMENSIONS) {
+ destRect = Common::Rect(_x1, _y1, _x2, _y2);
+ }
+
+ engine->playVideo(decoder, destRect, _skippable);
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionTimer
+//////////////////////////////////////////////////////////////////////////////
+
+ActionTimer::ActionTimer(const Common::String &line) {
+ sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%u)", &_key, &_time);
+}
+
+bool ActionTimer::execute(ZVision *engine) {
+ engine->getScriptManager()->addControl(new TimerNode(engine, _key, _time));
+ return true;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h
new file mode 100644
index 0000000000..afa3e3a2ac
--- /dev/null
+++ b/engines/zvision/scripting/actions.h
@@ -0,0 +1,346 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_ACTIONS_H
+#define ZVISION_ACTIONS_H
+
+#include "common/str.h"
+
+#include "audio/mixer.h"
+
+
+namespace ZVision {
+
+// Forward declaration of ZVision. This file is included before ZVision is declared
+class ZVision;
+
+/**
+ * The base class that represents any action that a Puzzle can take.
+ * This class is purely virtual.
+ */
+class ResultAction {
+public:
+ virtual ~ResultAction() {}
+ /**
+ * This is called by the script system whenever a Puzzle's criteria are found to be true.
+ * It should execute any necessary actions and return a value indicating whether the script
+ * system should continue to test puzzles. In 99% of cases this will be 'true'.
+ *
+ * @param engine A pointer to the base engine so the ResultAction can access all the necessary methods
+ * @return Should the script system continue to test any remaining puzzles (true) or immediately break and go on to the next frame (false)
+ */
+ virtual bool execute(ZVision *engine) = 0;
+};
+
+
+// The different types of actions
+// DEBUG,
+// DISABLE_CONTROL,
+// DISABLE_VENUS,
+// DISPLAY_MESSAGE,
+// DISSOLVE,
+// DISTORT,
+// ENABLE_CONTROL,
+// FLUSH_MOUSE_EVENTS,
+// INVENTORY,
+// KILL,
+// MENU_BAR_ENABLE,
+// MUSIC,
+// PAN_TRACK,
+// PLAY_PRELOAD,
+// PREFERENCES,
+// QUIT,
+// RANDOM,
+// REGION,
+// RESTORE_GAME,
+// ROTATE_TO,
+// SAVE_GAME,
+// SET_PARTIAL_SCREEN,
+// SET_SCREEN,
+// SET_VENUS,
+// STOP,
+// STREAM_VIDEO,
+// SYNC_SOUND,
+// TTY_TEXT,
+// UNIVERSE_MUSIC,
+
+class ActionAdd : public ResultAction {
+public:
+ ActionAdd(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ uint _value;
+};
+
+class ActionAssign : public ResultAction {
+public:
+ ActionAssign(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ uint _value;
+};
+
+class ActionAttenuate : public ResultAction {
+public:
+ ActionAttenuate(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ int _attenuation;
+};
+
+class ActionChangeLocation : public ResultAction {
+public:
+ ActionChangeLocation(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ char _world;
+ char _room;
+ char _node;
+ char _view;
+ uint32 _offset;
+};
+
+class ActionCrossfade : public ResultAction {
+public:
+ ActionCrossfade(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _keyOne;
+ uint32 _keyTwo;
+ uint _oneStartVolume;
+ uint _twoStartVolume;
+ uint _oneEndVolume;
+ uint _twoEndVolume;
+ uint _timeInMillis;
+};
+
+class ActionDebug : public ResultAction {
+public:
+ ActionDebug(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+};
+
+class ActionDelayRender : public ResultAction {
+public:
+ ActionDelayRender(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ // TODO: Check if this should actually be frames or if it should be milliseconds/seconds
+ uint32 framesToDelay;
+};
+
+class ActionDisableControl : public ResultAction {
+public:
+ ActionDisableControl(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+};
+
+class ActionDisableVenus : public ResultAction {
+public:
+ ActionDisableVenus(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+};
+
+class ActionDisplayMessage : public ResultAction {
+public:
+ ActionDisplayMessage(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+};
+
+class ActionDissolve : public ResultAction {
+public:
+ ActionDissolve();
+ bool execute(ZVision *engine);
+};
+
+class ActionDistort : public ResultAction {
+public:
+ ActionDistort(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+};
+
+class ActionEnableControl : public ResultAction {
+public:
+ ActionEnableControl(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+};
+
+class ActionMusic : public ResultAction {
+public:
+ ActionMusic(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ Audio::Mixer::SoundType _soundType;
+ Common::String _fileName;
+ bool _loop;
+ byte _volume;
+};
+
+class ActionPlayAnimation : public ResultAction {
+public:
+ ActionPlayAnimation(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ Common::String _fileName;
+ uint32 _x;
+ uint32 _y;
+ uint32 _width;
+ uint32 _height;
+ uint32 _start;
+ uint32 _end;
+ uint _mask;
+ uint _framerate;
+ uint _loopCount;
+};
+
+class ActionPlayPreloadAnimation : public ResultAction {
+public:
+ ActionPlayPreloadAnimation(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _animationKey;
+ uint32 _controlKey;
+ uint32 _x1;
+ uint32 _y1;
+ uint32 _x2;
+ uint32 _y2;
+ uint _startFrame;
+ uint _endFrame;
+ uint _loopCount;
+};
+
+class ActionPreloadAnimation : public ResultAction {
+public:
+ ActionPreloadAnimation(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ Common::String _fileName;
+ uint _mask;
+ uint _framerate;
+};
+
+class ActionQuit : public ResultAction {
+public:
+ ActionQuit() {}
+ bool execute(ZVision *engine);
+};
+
+// TODO: See if this exists in ZGI. It doesn't in ZNem
+class ActionUnloadAnimation : public ResultAction {
+public:
+ ActionUnloadAnimation(const Common::String &line);
+ bool execute(ZVision *engine);
+};
+
+class ActionRandom : public ResultAction {
+public:
+ ActionRandom(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ uint _max;
+};
+
+class ActionSetPartialScreen : public ResultAction {
+public:
+ ActionSetPartialScreen(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint _x;
+ uint _y;
+ Common::String _fileName;
+ uint16 _backgroundColor;
+};
+
+class ActionSetScreen : public ResultAction {
+public:
+ ActionSetScreen(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ Common::String _fileName;
+};
+
+class ActionStreamVideo : public ResultAction {
+public:
+ ActionStreamVideo(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ enum {
+ DIFFERENT_DIMENSIONS = 0x1 // 0x1 flags that the destRect dimensions are different from the original video dimensions
+ };
+
+ Common::String _fileName;
+ uint _x1;
+ uint _y1;
+ uint _x2;
+ uint _y2;
+ uint _flags;
+ bool _skippable;
+};
+
+class ActionTimer : public ResultAction {
+public:
+ ActionTimer(const Common::String &line);
+ bool execute(ZVision *engine);
+
+private:
+ uint32 _key;
+ uint _time;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/control.cpp b/engines/zvision/scripting/control.cpp
new file mode 100644
index 0000000000..35c4ea1441
--- /dev/null
+++ b/engines/zvision/scripting/control.cpp
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+
+namespace ZVision {
+
+void Control::enable() {
+ if (!_enabled) {
+ _enabled = true;
+ return;
+ }
+
+ debug("Control %u is already enabled", _key);
+}
+
+void Control::disable() {
+ if (_enabled) {
+ _enabled = false;
+ return;
+ }
+
+ debug("Control %u is already disabled", _key);
+}
+
+void Control::parseFlatControl(ZVision *engine) {
+ engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT);
+}
+
+void Control::parsePanoramaControl(ZVision *engine, Common::SeekableReadStream &stream) {
+ RenderTable *renderTable = engine->getRenderManager()->getRenderTable();
+ renderTable->setRenderState(RenderTable::PANORAMA);
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("angle*", true)) {
+ float fov;
+ sscanf(line.c_str(), "angle(%f)", &fov);
+ renderTable->setPanoramaFoV(fov);
+ } else if (line.matchString("linscale*", true)) {
+ float scale;
+ sscanf(line.c_str(), "linscale(%f)", &scale);
+ renderTable->setPanoramaScale(scale);
+ } else if (line.matchString("reversepana*", true)) {
+ uint reverse;
+ sscanf(line.c_str(), "reversepana(%u)", &reverse);
+ if (reverse == 1) {
+ renderTable->setPanoramaReverse(true);
+ }
+ } else if (line.matchString("zeropoint*", true)) {
+ // TODO: Implement
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ renderTable->generateRenderTable();
+}
+
+void Control::parseTiltControl(ZVision *engine, Common::SeekableReadStream &stream) {
+ RenderTable *renderTable = engine->getRenderManager()->getRenderTable();
+ renderTable->setRenderState(RenderTable::TILT);
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("angle*", true)) {
+ float fov;
+ sscanf(line.c_str(), "angle(%f)", &fov);
+ renderTable->setTiltFoV(fov);
+ } else if (line.matchString("linscale*", true)) {
+ float scale;
+ sscanf(line.c_str(), "linscale(%f)", &scale);
+ renderTable->setTiltScale(scale);
+ } else if (line.matchString("reversepana*", true)) {
+ uint reverse;
+ sscanf(line.c_str(), "reversepana(%u)", &reverse);
+ if (reverse == 1) {
+ renderTable->setTiltReverse(true);
+ }
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ renderTable->generateRenderTable();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/control.h b/engines/zvision/scripting/control.h
new file mode 100644
index 0000000000..770c540a12
--- /dev/null
+++ b/engines/zvision/scripting/control.h
@@ -0,0 +1,146 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_CONTROL_H
+#define ZVISION_CONTROL_H
+
+#include "common/keyboard.h"
+
+
+namespace Common {
+class SeekableReadStream;
+struct Point;
+class WriteStream;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+class Control {
+public:
+ Control() : _engine(0), _key(0), _enabled(false) {}
+ Control(ZVision *engine, uint32 key) : _engine(engine), _key(key), _enabled(false) {}
+ virtual ~Control() {}
+
+ uint32 getKey() { return _key; }
+
+ virtual void enable();
+ virtual void disable();
+ virtual void focus() {}
+ virtual void unfocus() {}
+ /**
+ * Called when LeftMouse is pushed. Default is NOP.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ virtual void onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {}
+ /**
+ * Called when LeftMouse is lifted. Default is NOP.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ virtual void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {}
+ /**
+ * Called on every MouseMove. Default is NOP.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ virtual bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { return false; }
+ /**
+ * Called when a key is pressed. Default is NOP.
+ *
+ * @param keycode The key that was pressed
+ */
+ virtual void onKeyDown(Common::KeyState keyState) {}
+ /**
+ * Called when a key is released. Default is NOP.
+ *
+ * @param keycode The key that was pressed
+ */
+ virtual void onKeyUp(Common::KeyState keyState) {}
+ /**
+ * Processes the node given the deltaTime since last frame. Default is NOP.
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ virtual bool process(uint32 deltaTimeInMillis) { return false; }
+ /**
+ * Serialize a Control for save game use. This should only be used if a Control needs
+ * to save values that would be different from initialization. AKA a TimerNode needs to
+ * store the amount of time left on the timer. Any Controls overriding this *MUST* write
+ * their key as the first data outputted. The default implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override deserialize()
+ * and needsSerialization()
+ *
+ * @param stream Stream to write any needed data to
+ */
+ virtual void serialize(Common::WriteStream *stream) {}
+ /**
+ * De-serialize data from a save game stream. This should only be implemented if the
+ * Control also implements serialize(). The calling method assumes the size of the
+ * data read from the stream exactly equals that written in serialize(). The default
+ * implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override serialize()
+ * and needsSerialization()
+ *
+ * @param stream Save game file stream
+ */
+ virtual void deserialize(Common::SeekableReadStream *stream) {}
+ /**
+ * If a Control overrides serialize() and deserialize(), this should return true
+ *
+ * @return Does the Control need save game serialization?
+ */
+ virtual inline bool needsSerialization() { return false; }
+
+protected:
+ ZVision * _engine;
+ uint32 _key;
+ bool _enabled;
+
+// Static member functions
+public:
+ static void parseFlatControl(ZVision *engine);
+ static void parsePanoramaControl(ZVision *engine, Common::SeekableReadStream &stream);
+ static void parseTiltControl(ZVision *engine, Common::SeekableReadStream &stream);
+};
+
+// TODO: Implement InputControl
+// TODO: Implement SaveControl
+// TODO: Implement SlotControl
+// TODO: Implement SafeControl
+// TODO: Implement FistControl
+// TODO: Implement HotMovieControl
+// TODO: Implement PaintControl
+// TODO: Implement TilterControl
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/animation_control.cpp b/engines/zvision/scripting/controls/animation_control.cpp
new file mode 100644
index 0000000000..ec8f7a9647
--- /dev/null
+++ b/engines/zvision/scripting/controls/animation_control.cpp
@@ -0,0 +1,263 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/animation_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/animation/rlf_animation.h"
+#include "zvision/video/zork_avi_decoder.h"
+
+#include "video/video_decoder.h"
+
+#include "graphics/surface.h"
+
+
+namespace ZVision {
+
+AnimationControl::AnimationControl(ZVision *engine, uint32 controlKey, const Common::String &fileName)
+ : Control(engine, controlKey),
+ _fileType(RLF),
+ _loopCount(1),
+ _currentLoop(0),
+ _accumulatedTime(0),
+ _cachedFrame(0),
+ _cachedFrameNeedsDeletion(false) {
+ if (fileName.hasSuffix(".rlf")) {
+ _fileType = RLF;
+ _animation.rlf = new RlfAnimation(fileName, false);
+ } else if (fileName.hasSuffix(".avi")) {
+ _fileType = AVI;
+ _animation.avi = new ZorkAVIDecoder();
+ _animation.avi->loadFile(fileName);
+ } else {
+ warning("Unrecognized animation file type: %s", fileName.c_str());
+ }
+
+ _cachedFrame = new Graphics::Surface();
+}
+
+AnimationControl::~AnimationControl() {
+ if (_fileType == RLF) {
+ delete _animation.rlf;
+ } else if (_fileType == AVI) {
+ delete _animation.avi;
+ }
+
+ _cachedFrame->free();
+ delete _cachedFrame;
+}
+
+bool AnimationControl::process(uint32 deltaTimeInMillis) {
+ if (!_enabled) {
+ return false;
+ }
+
+ bool finished = false;
+
+ if (_fileType == RLF) {
+ _accumulatedTime += deltaTimeInMillis;
+
+ uint32 frameTime = _animation.rlf->frameTime();
+ if (_accumulatedTime >= frameTime) {
+ while (_accumulatedTime >= frameTime) {
+ _accumulatedTime -= frameTime;
+
+ // Make sure the frame is inside the working window
+ // If it's not, then just return
+
+ RenderManager *renderManager = _engine->getRenderManager();
+ Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
+ Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _animation.rlf->width(), workingWindowPoint.y + _animation.rlf->height());
+
+ // If the clip returns false, it means the animation is outside the working window
+ if (!renderManager->clipRectToWorkingWindow(subRect)) {
+ return false;
+ }
+
+ const Graphics::Surface *frame = _animation.rlf->getNextFrame();
+
+ // Animation frames for PANORAMAs are transposed, so un-transpose them
+ RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
+ if (state == RenderTable::PANORAMA) {
+ Graphics::Surface *tranposedFrame = RenderManager::tranposeSurface(frame);
+
+ renderManager->copyRectToWorkingWindow((uint16 *)tranposedFrame->getBasePtr(tranposedFrame->w - subRect.width(), tranposedFrame->h - subRect.height()), subRect.left, subRect.top, _animation.rlf->width(), subRect.width(), subRect.height());
+
+ // If the background can move, we need to cache the last frame so it can be rendered during background movement
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (_cachedFrameNeedsDeletion) {
+ _cachedFrame->free();
+ delete _cachedFrame;
+ _cachedFrameNeedsDeletion = false;
+ }
+ _cachedFrame = tranposedFrame;
+ _cachedFrameNeedsDeletion = true;
+ } else {
+ // Cleanup
+ tranposedFrame->free();
+ delete tranposedFrame;
+ }
+ } else {
+ renderManager->copyRectToWorkingWindow((const uint16 *)frame->getBasePtr(frame->w - subRect.width(), frame->h - subRect.height()), subRect.left, subRect.top, _animation.rlf->width(), subRect.width(), subRect.height());
+
+ // If the background can move, we need to cache the last frame so it can be rendered during background movement
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (_cachedFrameNeedsDeletion) {
+ _cachedFrame->free();
+ delete _cachedFrame;
+ _cachedFrameNeedsDeletion = false;
+ }
+ _cachedFrame->copyFrom(*frame);
+ }
+ }
+
+ // Check if we should continue looping
+ if (_animation.rlf->endOfAnimation()) {
+ _animation.rlf->seekToFrame(-1);
+ if (_loopCount > 0) {
+ _currentLoop++;
+ if (_currentLoop >= _loopCount) {
+ finished = true;
+ }
+ }
+ }
+ }
+ } else {
+ // If the background can move, we have to keep rendering animation frames, otherwise the animation flickers during background movement
+ RenderManager *renderManager = _engine->getRenderManager();
+ RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
+
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
+ Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _cachedFrame->w, workingWindowPoint.y + _cachedFrame->h);
+
+ // If the clip returns false, it means the animation is outside the working window
+ if (!renderManager->clipRectToWorkingWindow(subRect)) {
+ return false;
+ }
+
+ renderManager->copyRectToWorkingWindow((uint16 *)_cachedFrame->getBasePtr(_cachedFrame->w - subRect.width(), _cachedFrame->h - subRect.height()), subRect.left, subRect.top, _cachedFrame->w, subRect.width(), subRect.height());
+ }
+ }
+ } else if (_fileType == AVI) {
+ if (!_animation.avi->isPlaying()) {
+ _animation.avi->start();
+ }
+
+ if (_animation.avi->needsUpdate()) {
+ const Graphics::Surface *frame = _animation.avi->decodeNextFrame();
+
+ if (frame) {
+ // Make sure the frame is inside the working window
+ // If it's not, then just return
+
+ RenderManager *renderManager = _engine->getRenderManager();
+ Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
+ Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + frame->w, workingWindowPoint.y + frame->h);
+
+ // If the clip returns false, it means the animation is outside the working window
+ if (!renderManager->clipRectToWorkingWindow(subRect)) {
+ return false;
+ }
+
+ // Animation frames for PANORAMAs are transposed, so un-transpose them
+ RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
+ if (state == RenderTable::PANORAMA) {
+ Graphics::Surface *tranposedFrame = RenderManager::tranposeSurface(frame);
+
+ renderManager->copyRectToWorkingWindow((uint16 *)tranposedFrame->getBasePtr(tranposedFrame->w - subRect.width(), tranposedFrame->h - subRect.height()), subRect.left, subRect.top, frame->w, subRect.width(), subRect.height());
+
+ // If the background can move, we need to cache the last frame so it can be rendered during background movement
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (_cachedFrameNeedsDeletion) {
+ _cachedFrame->free();
+ delete _cachedFrame;
+ _cachedFrameNeedsDeletion = false;
+ }
+ _cachedFrame = tranposedFrame;
+ _cachedFrameNeedsDeletion = true;
+ } else {
+ // Cleanup
+ tranposedFrame->free();
+ delete tranposedFrame;
+ }
+ } else {
+ renderManager->copyRectToWorkingWindow((const uint16 *)frame->getBasePtr(frame->w - subRect.width(), frame->h - subRect.height()), subRect.left, subRect.top, frame->w, subRect.width(), subRect.height());
+
+ // If the background can move, we need to cache the last frame so it can be rendered during background movement
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (_cachedFrameNeedsDeletion) {
+ _cachedFrame->free();
+ delete _cachedFrame;
+ _cachedFrameNeedsDeletion = false;
+ }
+ _cachedFrame->copyFrom(*frame);
+ }
+ }
+ } else {
+ // If the background can move, we have to keep rendering animation frames, otherwise the animation flickers during background movement
+ RenderManager *renderManager = _engine->getRenderManager();
+ RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
+
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
+ Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _cachedFrame->w, workingWindowPoint.y + _cachedFrame->h);
+
+ // If the clip returns false, it means the animation is outside the working window
+ if (!renderManager->clipRectToWorkingWindow(subRect)) {
+ return false;
+ }
+
+ renderManager->copyRectToWorkingWindow((uint16 *)_cachedFrame->getBasePtr(_cachedFrame->w - subRect.width(), _cachedFrame->h - subRect.height()), subRect.left, subRect.top, _cachedFrame->w, subRect.width(), subRect.height());
+ }
+ }
+ }
+
+ // Check if we should continue looping
+ if (_animation.avi->endOfVideo()) {
+ _animation.avi->rewind();
+ if (_loopCount > 0) {
+ _currentLoop++;
+ if (_currentLoop >= _loopCount) {
+ _animation.avi->stop();
+ finished = true;
+ }
+ }
+ }
+ }
+
+ // If we're done, set _animation key = 2 (Why 2? I don't know. It's just the value that they used)
+ // Then disable the control. DON'T delete it. It can be re-used
+ if (finished) {
+ _engine->getScriptManager()->setStateValue(_animationKey, 2);
+ disable();
+ _currentLoop = 0;
+ }
+
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/animation_control.h b/engines/zvision/scripting/controls/animation_control.h
new file mode 100644
index 0000000000..77663aaf1e
--- /dev/null
+++ b/engines/zvision/scripting/controls/animation_control.h
@@ -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.
+ *
+ */
+
+#ifndef ZVISION_ANIMATION_CONTROL_H
+#define ZVISION_ANIMATION_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace Video {
+class VideoDecoder;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+class RlfAnimation;
+
+class AnimationControl : public Control {
+public:
+ AnimationControl(ZVision *engine, uint32 controlKey, const Common::String &fileName);
+ ~AnimationControl();
+
+private:
+ enum FileType {
+ RLF = 1,
+ AVI = 2
+ };
+
+private:
+ uint32 _animationKey;
+
+ union {
+ RlfAnimation *rlf;
+ Video::VideoDecoder *avi;
+ } _animation;
+
+ FileType _fileType;
+ uint _loopCount;
+ int32 _x;
+ int32 _y;
+
+ uint _accumulatedTime;
+ uint _currentLoop;
+
+ Graphics::Surface *_cachedFrame;
+ bool _cachedFrameNeedsDeletion;
+
+public:
+ bool process(uint32 deltaTimeInMillis);
+
+ void setAnimationKey(uint32 animationKey) { _animationKey = animationKey; }
+ void setLoopCount(uint loopCount) { _loopCount = loopCount; }
+ void setXPos(int32 x) { _x = x; }
+ void setYPost(int32 y) { _y = y; }
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
new file mode 100644
index 0000000000..2685b01312
--- /dev/null
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -0,0 +1,142 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/input_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/strings/string_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/rect.h"
+
+
+namespace ZVision {
+
+InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key),
+ _nextTabstop(0),
+ _focused(false),
+ _textChanged(false),
+ _cursorOffset(0) {
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("*rectangle*", true)) {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+
+ sscanf(line.c_str(), "%*[^(](%d %d %d %d)", &x1, &y1, &x2, &y2);
+
+ _textRectangle = Common::Rect(x1, y1, x2, y2);
+ } else if (line.matchString("*aux_hotspot*", true)) {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+
+ sscanf(line.c_str(), "%*[^(](%d %d %d %d)", &x1, &y1, &x2, &y2);
+
+ _headerRectangle = Common::Rect(x1, y1, x2, y2);
+ } else if (line.matchString("*string_init*", true)) {
+ uint fontFormatNumber;
+
+ sscanf(line.c_str(), "%*[^(](%u)", &fontFormatNumber);
+
+ _textStyle = _engine->getStringManager()->getTextStyle(fontFormatNumber);
+ } else if (line.matchString("*next_tabstop*", true)) {
+ sscanf(line.c_str(), "%*[^(](%u)", &_nextTabstop);
+ } else if (line.matchString("*cursor_animation*", true)) {
+ char fileName[25];
+
+ sscanf(line.c_str(), "%*[^(](%25s %*u)", fileName);
+
+ _cursorAnimationFileName = Common::String(fileName);
+ } else if (line.matchString("*cursor_dimensions*", true)) {
+ // Ignore, use the dimensions in the animation file
+ } else if (line.matchString("*cursor_animation_frames*", true)) {
+ // Ignore, use the frame count in the animation file
+ } else if (line.matchString("*focus*", true)) {
+ _focused = true;
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+}
+
+void InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ _engine->getScriptManager()->focusControl(_key);
+}
+
+void InputControl::onKeyDown(Common::KeyState keyState) {
+ if (!_focused) {
+ return;
+ }
+
+ if (keyState.keycode == Common::KEYCODE_BACKSPACE) {
+ _currentInputText.deleteLastChar();
+ } else if (keyState.keycode == Common::KEYCODE_TAB) {
+ _focused = false;
+ // Focus the next input control
+ _engine->getScriptManager()->focusControl(_nextTabstop);
+ } else {
+ // Otherwise, append the new character to the end of the current text
+
+ uint16 asciiValue = keyState.ascii;
+ // We only care about text values
+ if (asciiValue >= 32 && asciiValue <= 126) {
+ _currentInputText += (char)asciiValue;
+ _textChanged = true;
+ }
+ }
+}
+
+bool InputControl::process(uint32 deltaTimeInMillis) {
+ if (!_focused) {
+ return false;
+ }
+
+ // First see if we need to render the text
+ if (_textChanged) {
+ // Blit the text using the RenderManager
+ Common::Rect destRect = _engine->getRenderManager()->renderTextToWorkingWindow(_key, _currentInputText, _textStyle.font, _textRectangle.left, _textRectangle.top, _textStyle.color, _textRectangle.width());
+
+ _cursorOffset = destRect.left - _textRectangle.left;
+ }
+
+ // Render the next frame of the animation
+ // TODO: Implement animation handling
+
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h
new file mode 100644
index 0000000000..f0fd8b502d
--- /dev/null
+++ b/engines/zvision/scripting/controls/input_control.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_INPUT_CONTROL_H
+#define ZVISION_INPUT_CONTROL_H
+
+#include "zvision/scripting/control.h"
+#include "zvision/strings/string_manager.h"
+
+#include "common/rect.h"
+
+
+namespace ZVision {
+
+class InputControl : public Control {
+public:
+ InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+
+private:
+ Common::Rect _textRectangle;
+ Common::Rect _headerRectangle;
+ StringManager::TextStyle _textStyle;
+ uint32 _nextTabstop;
+ Common::String _cursorAnimationFileName;
+ bool _focused;
+
+ Common::String _currentInputText;
+ bool _textChanged;
+ uint _cursorOffset;
+
+public:
+ void focus() { _focused = true; }
+ void unfocus() { _focused = false; }
+ void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ void onKeyDown(Common::KeyState keyState);
+ bool process(uint32 deltaTimeInMillis);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
new file mode 100644
index 0000000000..e08fdd10f3
--- /dev/null
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -0,0 +1,402 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/lever_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/animation/rlf_animation.h"
+#include "zvision/video/zork_avi_decoder.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "common/tokenizer.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
+
+namespace ZVision {
+
+LeverControl::LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key),
+ _frameInfo(0),
+ _frameCount(0),
+ _startFrame(0),
+ _currentFrame(0),
+ _lastRenderedFrame(0),
+ _mouseIsCaptured(false),
+ _isReturning(false),
+ _accumulatedTime(0),
+ _returnRoutesCurrentFrame(0) {
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("*descfile*", true)) {
+ char levFileName[25];
+ sscanf(line.c_str(), "%*[^(](%25[^)])", levFileName);
+
+ parseLevFile(levFileName);
+ } else if (line.matchString("*cursor*", true)) {
+ char cursorName[25];
+ sscanf(line.c_str(), "%*[^(](%25[^)])", cursorName);
+
+ _cursorName = Common::String(cursorName);
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ renderFrame(_currentFrame);
+}
+
+LeverControl::~LeverControl() {
+ if (_fileType == AVI) {
+ delete _animation.avi;
+ } else if (_fileType == RLF) {
+ delete _animation.rlf;
+ }
+
+ delete[] _frameInfo;
+}
+
+void LeverControl::parseLevFile(const Common::String &fileName) {
+ Common::File file;
+ if (!file.open(fileName)) {
+ warning("LEV file %s could could be opened", fileName.c_str());
+ return;
+ }
+
+ Common::String line = file.readLine();
+
+ while (!file.eos()) {
+ if (line.matchString("*animation_id*", true)) {
+ // Not used
+ } else if (line.matchString("*filename*", true)) {
+ char fileNameBuffer[25];
+ sscanf(line.c_str(), "%*[^:]:%25[^~]~", fileNameBuffer);
+
+ Common::String animationFileName(fileNameBuffer);
+
+ if (animationFileName.hasSuffix(".avi")) {
+ _animation.avi = new ZorkAVIDecoder();
+ _animation.avi->loadFile(animationFileName);
+ _fileType = AVI;
+ } else if (animationFileName.hasSuffix(".rlf")) {
+ _animation.rlf = new RlfAnimation(animationFileName, false);
+ _fileType = RLF;
+ }
+ } else if (line.matchString("*skipcolor*", true)) {
+ // Not used
+ } else if (line.matchString("*anim_coords*", true)) {
+ int left, top, right, bottom;
+ sscanf(line.c_str(), "%*[^:]:%d %d %d %d~", &left, &top, &right, &bottom);
+
+ _animationCoords.left = left;
+ _animationCoords.top = top;
+ _animationCoords.right = right;
+ _animationCoords.bottom = bottom;
+ } else if (line.matchString("*mirrored*", true)) {
+ uint mirrored;
+ sscanf(line.c_str(), "%*[^:]:%u~", &mirrored);
+
+ _mirrored = mirrored == 0 ? false : true;
+ } else if (line.matchString("*frames*", true)) {
+ sscanf(line.c_str(), "%*[^:]:%u~", &_frameCount);
+
+ _frameInfo = new FrameInfo[_frameCount];
+ } else if (line.matchString("*elsewhere*", true)) {
+ // Not used
+ } else if (line.matchString("*out_of_control*", true)) {
+ // Not used
+ } else if (line.matchString("*start_pos*", true)) {
+ sscanf(line.c_str(), "%*[^:]:%u~", &_startFrame);
+ _currentFrame = _startFrame;
+ } else if (line.matchString("*hotspot_deltas*", true)) {
+ uint x;
+ uint y;
+ sscanf(line.c_str(), "%*[^:]:%u %u~", &x, &y);
+
+ _hotspotDelta.x = x;
+ _hotspotDelta.y = y;
+ } else {
+ uint frameNumber;
+ uint x, y;
+
+ if (sscanf(line.c_str(), "%u:%u %u", &frameNumber, &x, &y) == 3) {
+ _frameInfo[frameNumber].hotspot.left = x;
+ _frameInfo[frameNumber].hotspot.top = y;
+ _frameInfo[frameNumber].hotspot.right = x + _hotspotDelta.x;
+ _frameInfo[frameNumber].hotspot.bottom = y + _hotspotDelta.y;
+ }
+
+ Common::StringTokenizer tokenizer(line, " ^=()");
+ tokenizer.nextToken();
+ tokenizer.nextToken();
+
+ Common::String token = tokenizer.nextToken();
+ while (!tokenizer.empty()) {
+ if (token == "D") {
+ token = tokenizer.nextToken();
+
+ uint angle;
+ uint toFrame;
+ sscanf(token.c_str(), "%u,%u", &toFrame, &angle);
+
+ _frameInfo[frameNumber].directions.push_back(Direction(angle, toFrame));
+ } else if (token.hasPrefix("P")) {
+ // Format: P(<from> to <to>)
+ tokenizer.nextToken();
+ tokenizer.nextToken();
+ token = tokenizer.nextToken();
+ uint to = atoi(token.c_str());
+
+ _frameInfo[frameNumber].returnRoute.push_back(to);
+ }
+
+ token = tokenizer.nextToken();
+ }
+ }
+
+ line = file.readLine();
+ }
+}
+
+void LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (!_enabled) {
+ return;
+ }
+
+ if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
+ _mouseIsCaptured = true;
+ _lastMousePos = backgroundImageSpacePos;
+ }
+}
+
+void LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (!_enabled) {
+ return;
+ }
+
+ if (_mouseIsCaptured) {
+ _mouseIsCaptured = false;
+ _engine->getScriptManager()->setStateValue(_key, _currentFrame);
+
+ _isReturning = true;
+ _returnRoutesCurrentProgress = _frameInfo[_currentFrame].returnRoute.begin();
+ _returnRoutesCurrentFrame = _currentFrame;
+ }
+}
+
+bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (!_enabled) {
+ return false;
+ }
+
+ bool cursorWasChanged = false;
+
+ if (_mouseIsCaptured) {
+ // Make sure the square distance between the last point and the current point is greater than 64
+ // This is a heuristic. This determines how responsive the lever is to mouse movement.
+ // TODO: Fiddle with the heuristic to get a good lever responsiveness 'feel'
+ if (_lastMousePos.sqrDist(backgroundImageSpacePos) >= 64) {
+ int angle = calculateVectorAngle(_lastMousePos, backgroundImageSpacePos);
+ _lastMousePos = backgroundImageSpacePos;
+
+ for (Common::List<Direction>::iterator iter = _frameInfo[_currentFrame].directions.begin(); iter != _frameInfo[_currentFrame].directions.end(); ++iter) {
+ if (angle >= (int)iter->angle - ANGLE_DELTA && angle <= (int)iter->angle + ANGLE_DELTA) {
+ _currentFrame = iter->toFrame;
+ renderFrame(_currentFrame);
+ break;
+ }
+ }
+ }
+ } else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(_cursorName);
+ cursorWasChanged = true;
+ }
+
+ return cursorWasChanged;
+}
+
+bool LeverControl::process(uint32 deltaTimeInMillis) {
+ if (!_enabled) {
+ return false;
+ }
+
+ if (_isReturning) {
+ _accumulatedTime += deltaTimeInMillis;
+ while (_accumulatedTime >= ANIMATION_FRAME_TIME) {
+ _accumulatedTime -= ANIMATION_FRAME_TIME;
+ if (_returnRoutesCurrentFrame == *_returnRoutesCurrentProgress) {
+ _returnRoutesCurrentProgress++;
+ }
+ if (_returnRoutesCurrentProgress == _frameInfo[_currentFrame].returnRoute.end()) {
+ _isReturning = false;
+ _currentFrame = _returnRoutesCurrentFrame;
+ return false;
+ }
+
+ uint toFrame = *_returnRoutesCurrentProgress;
+ if (_returnRoutesCurrentFrame < toFrame) {
+ _returnRoutesCurrentFrame++;
+ } else if (_returnRoutesCurrentFrame > toFrame) {
+ _returnRoutesCurrentFrame--;
+ }
+
+ _engine->getScriptManager()->setStateValue(_key, _returnRoutesCurrentFrame);
+ renderFrame(_returnRoutesCurrentFrame);
+ }
+ }
+
+ return false;
+}
+
+int LeverControl::calculateVectorAngle(const Common::Point &pointOne, const Common::Point &pointTwo) {
+ // Check for the easy angles first
+ if (pointOne.x == pointTwo.x && pointOne.y == pointTwo.y)
+ return -1; // This should never happen
+ else if (pointOne.x == pointTwo.x) {
+ if (pointTwo.y < pointOne.y)
+ return 90;
+ else
+ return 270;
+ } else if (pointOne.y == pointTwo.y) {
+ if (pointTwo.x > pointOne.x)
+ return 0;
+ else
+ return 180;
+ } else {
+ // Calculate the angle with trig
+ int16 xDist = pointTwo.x - pointOne.x;
+ int16 yDist = pointTwo.y - pointOne.y;
+
+ // Calculate the angle using arctan
+ // Then convert to degrees. (180 / 3.14159 = 57.2958)
+ int angle = int(atan((float)yDist / (float)xDist) * 57);
+
+ // Calculate what quadrant pointTwo is in
+ uint quadrant = ((yDist > 0 ? 1 : 0) << 1) | (xDist < 0 ? 1 : 0);
+
+ // Explanation of quadrants:
+ //
+ // yDist > 0 | xDist < 0 | Quadrant number
+ // 0 | 0 | 0
+ // 0 | 1 | 1
+ // 1 | 0 | 2
+ // 1 | 1 | 3
+ //
+ // Note: I know this doesn't line up with traditional mathematical quadrants
+ // but doing it this way allows you can use a switch and is a bit cleaner IMO.
+ //
+ // The graph below shows the 4 quadrants pointTwo can end up in as well
+ // as what the angle as calculated above refers to.
+ // Note: The calculated angle in quadrants 0 and 3 is negative
+ // due to arctan(-x) = -theta
+ //
+ // Origin => (pointOne.x, pointOne.y)
+ // * => (pointTwo.x, pointTwo.y)
+ //
+ // 90 |
+ // ^ |
+ // * | * |
+ // \ | / |
+ // \ | / |
+ // \ | / |
+ // Quadrant 1 \ | / Quadrant 0 |
+ // \ | / |
+ // \ | / |
+ // angle ( \|/ ) -angle |
+ // 180 <----------------------------------------> 0 |
+ // -angle ( /|\ ) angle |
+ // / | \ |
+ // / | \ |
+ // Quadrant 3 / | \ Quadrant 2 |
+ // / | \ |
+ // / | \ |
+ // / | \ |
+ // * | * |
+ // ^ |
+ // 270 |
+
+ // Convert the local angles to unit circle angles
+ switch (quadrant) {
+ case 0:
+ angle = 180 + angle;
+ break;
+ case 1:
+ // Do nothing
+ break;
+ case 2:
+ angle = 180 + angle;
+ break;
+ case 3:
+ angle = 360 + angle;
+ break;
+ }
+
+ return angle;
+ }
+}
+
+void LeverControl::renderFrame(uint frameNumber) {
+ if (frameNumber == 0) {
+ _lastRenderedFrame = frameNumber;
+ } else if (frameNumber < _lastRenderedFrame && _mirrored) {
+ _lastRenderedFrame = frameNumber;
+ frameNumber = (_frameCount * 2) - frameNumber - 1;
+ } else {
+ _lastRenderedFrame = frameNumber;
+ }
+
+ const uint16 *frameData = 0;
+ int x = _animationCoords.left;
+ int y = _animationCoords.top;
+ int width = 0;
+ int height = 0;
+
+ if (_fileType == RLF) {
+ // getFrameData() will automatically optimize to getNextFrame() / getPreviousFrame() if it can
+ frameData = (const uint16 *)_animation.rlf->getFrameData(frameNumber)->getPixels();
+ width = _animation.rlf->width(); // Use the animation width instead of _animationCoords.width()
+ height = _animation.rlf->height(); // Use the animation height instead of _animationCoords.height()
+ } else if (_fileType == AVI) {
+ _animation.avi->seekToFrame(frameNumber);
+ const Graphics::Surface *surface = _animation.avi->decodeNextFrame();
+ frameData = (const uint16 *)surface->getPixels();
+ width = surface->w;
+ height = surface->h;
+ }
+
+ _engine->getRenderManager()->copyRectToWorkingWindow(frameData, x, y, width, width, height);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h
new file mode 100644
index 0000000000..69473cf119
--- /dev/null
+++ b/engines/zvision/scripting/controls/lever_control.h
@@ -0,0 +1,127 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_LEVER_CONTROL_H
+#define ZVISION_LEVER_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/list.h"
+#include "common/rect.h"
+
+
+namespace ZVision {
+
+class ZorkAVIDecoder;
+class RlfAnimation;
+
+class LeverControl : public Control {
+public:
+ LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~LeverControl();
+
+private:
+ enum FileType {
+ RLF = 1,
+ AVI = 2
+ };
+
+ struct Direction {
+ Direction(uint a, uint t) : angle(a), toFrame(t) {}
+
+ uint angle;
+ uint toFrame;
+ };
+
+ struct FrameInfo {
+ Common::Rect hotspot;
+ Common::List<Direction> directions;
+ Common::List<uint> returnRoute;
+ };
+
+ enum {
+ ANGLE_DELTA = 30, // How far off a mouse angle can be and still be considered valid. This is in both directions, so the total buffer zone is (2 * ANGLE_DELTA)
+ ANIMATION_FRAME_TIME = 30 // In millis
+ };
+
+private:
+ union {
+ RlfAnimation *rlf;
+ ZorkAVIDecoder *avi;
+ } _animation;
+ FileType _fileType;
+
+ Common::String _cursorName;
+ Common::Rect _animationCoords;
+ bool _mirrored;
+ uint _frameCount;
+ uint _startFrame;
+ Common::Point _hotspotDelta;
+ FrameInfo *_frameInfo;
+
+ uint _currentFrame;
+ uint _lastRenderedFrame;
+ bool _mouseIsCaptured;
+ bool _isReturning;
+ Common::Point _lastMousePos;
+ Common::List<uint>::iterator _returnRoutesCurrentProgress;
+ uint _returnRoutesCurrentFrame;
+ uint32 _accumulatedTime;
+
+public:
+ void onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ void parseLevFile(const Common::String &fileName);
+ /**
+ * Calculates the angle a vector makes with the negative y-axis
+ *
+ * 90
+ * pointTwo * ^
+ * \ |
+ * \ |
+ * \ |
+ * \ |
+ * angle ( \|pointOne
+ * 180 <-----------*-----------> 0
+ * |
+ * |
+ * |
+ * |
+ * |
+ * ^
+ * 270
+ *
+ * @param pointOne The origin of the vector
+ * @param pointTwo The end of the vector
+ * @return The angle the vector makes with the negative y-axis
+ */
+ static int calculateVectorAngle(const Common::Point &pointOne, const Common::Point &pointTwo);
+ void renderFrame(uint frameNumber);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/push_toggle_control.cpp b/engines/zvision/scripting/controls/push_toggle_control.cpp
new file mode 100644
index 0000000000..11ec4bb73f
--- /dev/null
+++ b/engines/zvision/scripting/controls/push_toggle_control.cpp
@@ -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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/push_toggle_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+
+namespace ZVision {
+
+PushToggleControl::PushToggleControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key) {
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("*_hotspot*", true)) {
+ uint x;
+ uint y;
+ uint width;
+ uint height;
+
+ sscanf(line.c_str(), "%*[^(](%u,%u,%u,%u)", &x, &y, &width, &height);
+
+ _hotspot = Common::Rect(x, y, x + width, y + height);
+ } else if (line.matchString("cursor*", true)) {
+ char nameBuffer[25];
+
+ sscanf(line.c_str(), "%*[^(](%25[^)])", nameBuffer);
+
+ _hoverCursor = Common::String(nameBuffer);
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ if (_hotspot.isEmpty() || _hoverCursor.empty()) {
+ warning("Push_toggle cursor %u was parsed incorrectly", key);
+ }
+}
+
+PushToggleControl::~PushToggleControl() {
+ // Clear the state value back to 0
+ _engine->getScriptManager()->setStateValue(_key, 0);
+}
+
+void PushToggleControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (!_enabled) {
+ return;
+ }
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ _engine->getScriptManager()->setStateValue(_key, 1);
+ }
+}
+
+bool PushToggleControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (!_enabled) {
+ return false;
+ }
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(_hoverCursor);
+ return true;
+ }
+
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/push_toggle_control.h b/engines/zvision/scripting/controls/push_toggle_control.h
new file mode 100644
index 0000000000..13dc54a65f
--- /dev/null
+++ b/engines/zvision/scripting/controls/push_toggle_control.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_PUSH_TOGGLE_CONTROL_H
+#define ZVISION_PUSH_TOGGLE_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/rect.h"
+
+
+namespace ZVision {
+
+class PushToggleControl : public Control {
+public:
+ PushToggleControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~PushToggleControl();
+
+ /**
+ * Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
+ *
+ * @param engine The base engine
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+
+private:
+ /**
+ * The area that will trigger the event
+ * This is in image space coordinates, NOT screen space
+ */
+ Common::Rect _hotspot;
+ /** The cursor to use when hovering over _hotspot */
+ Common::String _hoverCursor;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/timer_node.cpp b/engines/zvision/scripting/controls/timer_node.cpp
new file mode 100644
index 0000000000..3b691be275
--- /dev/null
+++ b/engines/zvision/scripting/controls/timer_node.cpp
@@ -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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/timer_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+
+#include "common/stream.h"
+
+
+namespace ZVision {
+
+TimerNode::TimerNode(ZVision *engine, uint32 key, uint timeInSeconds)
+ : Control(engine, key) {
+ if (_engine->getGameId() == GID_NEMESIS) {
+ _timeLeft = timeInSeconds * 1000;
+ } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ _timeLeft = timeInSeconds * 100;
+ }
+
+ _engine->getScriptManager()->setStateValue(_key, 1);
+}
+
+TimerNode::~TimerNode() {
+ if (_timeLeft <= 0)
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ else
+ _engine->getScriptManager()->setStateValue(_key, _timeLeft); // If timer was stopped by stop or kill
+}
+
+bool TimerNode::process(uint32 deltaTimeInMillis) {
+ _timeLeft -= deltaTimeInMillis;
+
+ if (_timeLeft <= 0) {
+ // Let the destructor reset the state value
+ return true;
+ }
+
+ return false;
+}
+
+void TimerNode::serialize(Common::WriteStream *stream) {
+ stream->writeUint32LE(_key);
+ stream->writeUint32LE(_timeLeft);
+}
+
+void TimerNode::deserialize(Common::SeekableReadStream *stream) {
+ _timeLeft = stream->readUint32LE();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/timer_node.h b/engines/zvision/scripting/controls/timer_node.h
new file mode 100644
index 0000000000..a8e579cbe4
--- /dev/null
+++ b/engines/zvision/scripting/controls/timer_node.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_TIMER_NODE_H
+#define ZVISION_TIMER_NODE_H
+
+#include "zvision/scripting/control.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class TimerNode : public Control {
+public:
+ TimerNode(ZVision *engine, uint32 key, uint timeInSeconds);
+ ~TimerNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+ void serialize(Common::WriteStream *stream);
+ void deserialize(Common::SeekableReadStream *stream);
+ inline bool needsSerialization() { return true; }
+
+private:
+ int32 _timeLeft;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/puzzle.h b/engines/zvision/scripting/puzzle.h
new file mode 100644
index 0000000000..0d717f1fa9
--- /dev/null
+++ b/engines/zvision/scripting/puzzle.h
@@ -0,0 +1,74 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_PUZZLE_H
+#define ZVISION_PUZZLE_H
+
+#include "zvision/scripting/actions.h"
+
+#include "common/list.h"
+#include "common/ptr.h"
+
+
+namespace ZVision {
+
+struct Puzzle {
+ Puzzle() : key(0) {}
+
+ ~Puzzle() {
+ for (Common::List<ResultAction *>::iterator iter = resultActions.begin(); iter != resultActions.end(); ++iter) {
+ delete *iter;
+ }
+ }
+
+ /** How criteria should be decided */
+ enum CriteriaOperator {
+ EQUAL_TO,
+ NOT_EQUAL_TO,
+ GREATER_THAN,
+ LESS_THAN
+ };
+
+ /** Criteria for a Puzzle result to be fired */
+ struct CriteriaEntry {
+ /** The key of a global state */
+ uint32 key;
+ /**
+ * What we're comparing the value of the global state against
+ * This can either be a pure value or it can be the key of another global state
+ */
+ uint32 argument;
+ /** How to do the comparison */
+ CriteriaOperator criteriaOperator;
+ /** Whether 'argument' is the key of a global state (true) or a pure value (false) */
+ bool argumentIsAKey;
+ };
+
+ uint32 key;
+ Common::List<Common::List <CriteriaEntry> > criteriaList;
+ // This has to be list of pointers because ResultAction is abstract
+ Common::List<ResultAction *> resultActions;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp
new file mode 100644
index 0000000000..d93094a3b2
--- /dev/null
+++ b/engines/zvision/scripting/scr_file_handling.cpp
@@ -0,0 +1,302 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/script_manager.h"
+
+#include "zvision/utility/utility.h"
+#include "zvision/scripting/puzzle.h"
+#include "zvision/scripting/actions.h"
+#include "zvision/scripting/controls/push_toggle_control.h"
+#include "zvision/scripting/controls/lever_control.h"
+
+#include "common/textconsole.h"
+#include "common/file.h"
+#include "common/tokenizer.h"
+
+
+namespace ZVision {
+
+void ScriptManager::parseScrFile(const Common::String &fileName, bool isGlobal) {
+ Common::File file;
+ if (!file.open(fileName)) {
+ warning("Script file not found: %s", fileName.c_str());
+ return;
+ }
+
+ while(!file.eos()) {
+ Common::String line = file.readLine();
+ if (file.err()) {
+ warning("Error parsing scr file: %s", fileName.c_str());
+ return;
+ }
+
+ trimCommentsAndWhiteSpace(&line);
+ if (line.empty())
+ continue;
+
+ if (line.matchString("puzzle:*", true)) {
+ Puzzle *puzzle = new Puzzle();
+ sscanf(line.c_str(),"puzzle:%u",&(puzzle->key));
+
+ parsePuzzle(puzzle, file);
+ if (isGlobal) {
+ _globalPuzzles.push_back(puzzle);
+ } else {
+ _activePuzzles.push_back(puzzle);
+ }
+ } else if (line.matchString("control:*", true)) {
+ parseControl(line, file);
+ }
+ }
+}
+
+void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stream) {
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("criteria {", true)) {
+ parseCriteria(stream, puzzle->criteriaList);
+ } else if (line.matchString("results {", true)) {
+ parseResults(stream, puzzle->resultActions);
+ } else if (line.matchString("flags {", true)) {
+ setStateFlags(puzzle->key, parseFlags(stream));
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+}
+
+bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList) const {
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ // Criteria can be empty
+ if (line.contains('}')) {
+ return false;
+ }
+
+ // Create a new List to hold the CriteriaEntries
+ criteriaList.push_back(Common::List<Puzzle::CriteriaEntry>());
+
+ while (!stream.eos() && !line.contains('}')) {
+ Puzzle::CriteriaEntry entry;
+
+ // Split the string into tokens using ' ' as a delimiter
+ Common::StringTokenizer tokenizer(line);
+ Common::String token;
+
+ // Parse the id out of the first token
+ token = tokenizer.nextToken();
+ sscanf(token.c_str(), "[%u]", &(entry.key));
+
+ // Parse the operator out of the second token
+ token = tokenizer.nextToken();
+ if (token.c_str()[0] == '=')
+ entry.criteriaOperator = Puzzle::EQUAL_TO;
+ else if (token.c_str()[0] == '!')
+ entry.criteriaOperator = Puzzle::NOT_EQUAL_TO;
+ else if (token.c_str()[0] == '>')
+ entry.criteriaOperator = Puzzle::GREATER_THAN;
+ else if (token.c_str()[0] == '<')
+ entry.criteriaOperator = Puzzle::LESS_THAN;
+
+ // First determine if the last token is an id or a value
+ // Then parse it into 'argument'
+ token = tokenizer.nextToken();
+ if (token.contains('[')) {
+ sscanf(token.c_str(), "[%u]", &(entry.argument));
+ entry.argumentIsAKey = true;
+ } else {
+ sscanf(token.c_str(), "%u", &(entry.argument));
+ entry.argumentIsAKey = false;
+ }
+
+ criteriaList.back().push_back(entry);
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ return true;
+}
+
+void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::List<ResultAction *> &actionList) const {
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ // TODO: Re-order the if-then statements in order of highest occurrence
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.empty()) {
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ continue;
+ }
+
+ // Parse for the action type
+ if (line.matchString("*:add*", true)) {
+ actionList.push_back(new ActionAdd(line));
+ } else if (line.matchString("*:animplay*", true)) {
+ actionList.push_back(new ActionPlayAnimation(line));
+ } else if (line.matchString("*:animpreload*", true)) {
+ actionList.push_back(new ActionPreloadAnimation(line));
+ } else if (line.matchString("*:animunload*", true)) {
+ //actionList.push_back(new ActionUnloadAnimation(line));
+ } else if (line.matchString("*:attenuate*", true)) {
+ // TODO: Implement ActionAttenuate
+ } else if (line.matchString("*:assign*", true)) {
+ actionList.push_back(new ActionAssign(line));
+ } else if (line.matchString("*:change_location*", true)) {
+ actionList.push_back(new ActionChangeLocation(line));
+ } else if (line.matchString("*:crossfade*", true)) {
+ // TODO: Implement ActionCrossfade
+ } else if (line.matchString("*:debug*", true)) {
+ // TODO: Implement ActionDebug
+ } else if (line.matchString("*:delay_render*", true)) {
+ // TODO: Implement ActionDelayRender
+ } else if (line.matchString("*:disable_control*", true)) {
+ actionList.push_back(new ActionDisableControl(line));
+ } else if (line.matchString("*:disable_venus*", true)) {
+ // TODO: Implement ActionDisableVenus
+ } else if (line.matchString("*:display_message*", true)) {
+ // TODO: Implement ActionDisplayMessage
+ } else if (line.matchString("*:dissolve*", true)) {
+ // TODO: Implement ActionDissolve
+ } else if (line.matchString("*:distort*", true)) {
+ // TODO: Implement ActionDistort
+ } else if (line.matchString("*:enable_control*", true)) {
+ actionList.push_back(new ActionEnableControl(line));
+ } else if (line.matchString("*:flush_mouse_events*", true)) {
+ // TODO: Implement ActionFlushMouseEvents
+ } else if (line.matchString("*:inventory*", true)) {
+ // TODO: Implement ActionInventory
+ } else if (line.matchString("*:kill*", true)) {
+ // TODO: Implement ActionKill
+ } else if (line.matchString("*:menu_bar_enable*", true)) {
+ // TODO: Implement ActionMenuBarEnable
+ } else if (line.matchString("*:music*", true)) {
+ actionList.push_back(new ActionMusic(line));
+ } else if (line.matchString("*:pan_track*", true)) {
+ // TODO: Implement ActionPanTrack
+ } else if (line.matchString("*:playpreload*", true)) {
+ actionList.push_back(new ActionPlayPreloadAnimation(line));
+ } else if (line.matchString("*:preferences*", true)) {
+ // TODO: Implement ActionPreferences
+ } else if (line.matchString("*:quit*", true)) {
+ actionList.push_back(new ActionQuit());
+ } else if (line.matchString("*:random*", true)) {
+ actionList.push_back(new ActionRandom(line));
+ } else if (line.matchString("*:region*", true)) {
+ // TODO: Implement ActionRegion
+ } else if (line.matchString("*:restore_game*", true)) {
+ // TODO: Implement ActionRestoreGame
+ } else if (line.matchString("*:rotate_to*", true)) {
+ // TODO: Implement ActionRotateTo
+ } else if (line.matchString("*:save_game*", true)) {
+ // TODO: Implement ActionSaveGame
+ } else if (line.matchString("*:set_partial_screen*", true)) {
+ actionList.push_back(new ActionSetPartialScreen(line));
+ } else if (line.matchString("*:set_screen*", true)) {
+ actionList.push_back(new ActionSetScreen(line));
+ } else if (line.matchString("*:set_venus*", true)) {
+ // TODO: Implement ActionSetVenus
+ } else if (line.matchString("*:stop*", true)) {
+ // TODO: Implement ActionStop
+ } else if (line.matchString("*:streamvideo*", true)) {
+ actionList.push_back(new ActionStreamVideo(line));
+ } else if (line.matchString("*:syncsound*", true)) {
+ // TODO: Implement ActionSyncSound
+ } else if (line.matchString("*:timer*", true)) {
+ actionList.push_back(new ActionTimer(line));
+ } else if (line.matchString("*:ttytext*", true)) {
+ // TODO: Implement ActionTTYText
+ } else if (line.matchString("*:universe_music*", true)) {
+ // TODO: Implement ActionUniverseMusic
+ } else if (line.matchString("*:copy_file*", true)) {
+ // Not used. Purposely left empty
+ } else {
+ warning("Unhandled result action type: %s", line.c_str());
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ return;
+}
+
+uint ScriptManager::parseFlags(Common::SeekableReadStream &stream) const {
+ uint flags = 0;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (line.matchString("ONCE_PER_INST", true)) {
+ flags |= ONCE_PER_INST;
+ } else if (line.matchString("DO_ME_NOW", true)) {
+ flags |= DO_ME_NOW;
+ } else if (line.matchString("DISABLED", true)) {
+ flags |= DISABLED;
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ return flags;
+}
+
+void ScriptManager::parseControl(Common::String &line, Common::SeekableReadStream &stream) {
+ uint32 key;
+ char controlTypeBuffer[20];
+
+ sscanf(line.c_str(), "control:%u %s {", &key, controlTypeBuffer);
+
+ Common::String controlType(controlTypeBuffer);
+
+ if (controlType.equalsIgnoreCase("push_toggle")) {
+ _activeControls.push_back(new PushToggleControl(_engine, key, stream));
+ return;
+ } else if (controlType.equalsIgnoreCase("flat")) {
+ Control::parseFlatControl(_engine);
+ return;
+ } else if (controlType.equalsIgnoreCase("pana")) {
+ Control::parsePanoramaControl(_engine, stream);
+ return;
+ } else if (controlType.equalsIgnoreCase("tilt")) {
+ Control::parseTiltControl(_engine, stream);
+ return;
+ } else if (controlType.equalsIgnoreCase("lever")) {
+ _activeControls.push_back(new LeverControl(_engine, key, stream));
+ return;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp
new file mode 100644
index 0000000000..adcc5c7545
--- /dev/null
+++ b/engines/zvision/scripting/script_manager.cpp
@@ -0,0 +1,444 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/script_manager.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/core/save_manager.h"
+#include "zvision/scripting/actions.h"
+#include "zvision/utility/utility.h"
+
+#include "common/algorithm.h"
+#include "common/hashmap.h"
+#include "common/debug.h"
+#include "common/stream.h"
+
+
+namespace ZVision {
+
+ScriptManager::ScriptManager(ZVision *engine)
+ : _engine(engine),
+ _currentlyFocusedControl(0) {
+}
+
+ScriptManager::~ScriptManager() {
+ for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
+ delete (*iter);
+ }
+ for (PuzzleList::iterator iter = _globalPuzzles.begin(); iter != _globalPuzzles.end(); ++iter) {
+ delete (*iter);
+ }
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ delete (*iter);
+ }
+}
+
+void ScriptManager::initialize() {
+ parseScrFile("universe.scr", true);
+ changeLocation('g', 'a', 'r', 'y', 0);
+}
+
+void ScriptManager::update(uint deltaTimeMillis) {
+ updateNodes(deltaTimeMillis);
+ checkPuzzleCriteria();
+}
+
+void ScriptManager::createReferenceTable() {
+ // Iterate through each local Puzzle
+ for (PuzzleList::iterator activePuzzleIter = _activePuzzles.begin(); activePuzzleIter != _activePuzzles.end(); ++activePuzzleIter) {
+ Puzzle *puzzlePtr = (*activePuzzleIter);
+
+ // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*activePuzzleIter)->criteriaList.begin(); criteriaIter != (*activePuzzleIter)->criteriaList.end(); ++criteriaIter) {
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
+ _referenceTable[entryIter->key].push_back(puzzlePtr);
+
+ // If the argument is a key, add a reference to it as well
+ if (entryIter->argumentIsAKey) {
+ _referenceTable[entryIter->argument].push_back(puzzlePtr);
+ }
+ }
+ }
+ }
+
+ // Iterate through each global Puzzle
+ for (PuzzleList::iterator globalPuzzleIter = _globalPuzzles.begin(); globalPuzzleIter != _globalPuzzles.end(); ++globalPuzzleIter) {
+ Puzzle *puzzlePtr = (*globalPuzzleIter);
+
+ // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*globalPuzzleIter)->criteriaList.begin(); criteriaIter != (*globalPuzzleIter)->criteriaList.end(); ++criteriaIter) {
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
+ _referenceTable[entryIter->key].push_back(puzzlePtr);
+
+ // If the argument is a key, add a reference to it as well
+ if (entryIter->argumentIsAKey) {
+ _referenceTable[entryIter->argument].push_back(puzzlePtr);
+ }
+ }
+ }
+ }
+
+ // Remove duplicate entries
+ for (PuzzleMap::iterator referenceTableIter = _referenceTable.begin(); referenceTableIter != _referenceTable.end(); ++referenceTableIter) {
+ removeDuplicateEntries(referenceTableIter->_value);
+ }
+}
+
+void ScriptManager::updateNodes(uint deltaTimeMillis) {
+ // If process() returns true, it means the node can be deleted
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end();) {
+ if ((*iter)->process(deltaTimeMillis)) {
+ delete (*iter);
+ // Remove the node
+ iter = _activeControls.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+void ScriptManager::checkPuzzleCriteria() {
+ while (!_puzzlesToCheck.empty()) {
+ Puzzle *puzzle = _puzzlesToCheck.pop();
+
+ // Check if the puzzle is already finished
+ // Also check that the puzzle isn't disabled
+ if (getStateValue(puzzle->key) == 1 && (getStateFlags(puzzle->key) & DISABLED) == 0) {
+ continue;
+ }
+
+ // Check each Criteria
+
+ bool criteriaMet = false;
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = puzzle->criteriaList.begin(); criteriaIter != puzzle->criteriaList.end(); ++criteriaIter) {
+ criteriaMet = false;
+
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
+ // Get the value to compare against
+ uint argumentValue;
+ if (entryIter->argumentIsAKey)
+ argumentValue = getStateValue(entryIter->argument);
+ else
+ argumentValue = entryIter->argument;
+
+ // Do the comparison
+ switch (entryIter->criteriaOperator) {
+ case Puzzle::EQUAL_TO:
+ criteriaMet = getStateValue(entryIter->key) == argumentValue;
+ break;
+ case Puzzle::NOT_EQUAL_TO:
+ criteriaMet = getStateValue(entryIter->key) != argumentValue;
+ break;
+ case Puzzle::GREATER_THAN:
+ criteriaMet = getStateValue(entryIter->key) > argumentValue;
+ break;
+ case Puzzle::LESS_THAN:
+ criteriaMet = getStateValue(entryIter->key) < argumentValue;
+ break;
+ }
+
+ // If one check returns false, don't keep checking
+ if (!criteriaMet) {
+ break;
+ }
+ }
+
+ // If any of the Criteria are *fully* met, then execute the results
+ if (criteriaMet) {
+ break;
+ }
+ }
+
+ // criteriaList can be empty. Aka, the puzzle should be executed immediately
+ if (puzzle->criteriaList.empty() || criteriaMet) {
+ debug(1, "Puzzle %u criteria passed. Executing its ResultActions", puzzle->key);
+
+ // Set the puzzle as completed
+ setStateValue(puzzle->key, 1);
+
+ bool shouldContinue = true;
+ for (Common::List<ResultAction *>::iterator resultIter = puzzle->resultActions.begin(); resultIter != puzzle->resultActions.end(); ++resultIter) {
+ shouldContinue = shouldContinue && (*resultIter)->execute(_engine);
+ if (!shouldContinue) {
+ break;
+ }
+ }
+
+ if (!shouldContinue) {
+ break;
+ }
+ }
+ }
+}
+
+void ScriptManager::cleanStateTable() {
+ for (StateMap::iterator iter = _globalState.begin(); iter != _globalState.end(); ++iter) {
+ // If the value is equal to zero, we can purge it since getStateValue()
+ // will return zero if _globalState doesn't contain a key
+ if (iter->_value == 0) {
+ // Remove the node
+ _globalState.erase(iter);
+ }
+ }
+}
+
+uint ScriptManager::getStateValue(uint32 key) {
+ if (_globalState.contains(key))
+ return _globalState[key];
+ else
+ return 0;
+}
+
+void ScriptManager::setStateValue(uint32 key, uint value) {
+ _globalState[key] = value;
+
+ if (_referenceTable.contains(key)) {
+ for (Common::Array<Puzzle *>::iterator iter = _referenceTable[key].begin(); iter != _referenceTable[key].end(); ++iter) {
+ _puzzlesToCheck.push((*iter));
+ }
+ }
+}
+
+uint ScriptManager::getStateFlags(uint32 key) {
+ if (_globalStateFlags.contains(key))
+ return _globalStateFlags[key];
+ else
+ return 0;
+}
+
+void ScriptManager::setStateFlags(uint32 key, uint flags) {
+ _globalStateFlags[key] = flags;
+
+ if (_referenceTable.contains(key)) {
+ for (Common::Array<Puzzle *>::iterator iter = _referenceTable[key].begin(); iter != _referenceTable[key].end(); ++iter) {
+ _puzzlesToCheck.push((*iter));
+ }
+ }
+}
+
+void ScriptManager::addToStateValue(uint32 key, uint valueToAdd) {
+ _globalState[key] += valueToAdd;
+}
+
+void ScriptManager::addControl(Control *control) {
+ _activeControls.push_back(control);
+}
+
+Control *ScriptManager::getControl(uint32 key) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ return (*iter);
+ }
+ }
+
+ return nullptr;
+}
+
+void ScriptManager::focusControl(uint32 key) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ uint32 controlKey = (*iter)->getKey();
+
+ if (controlKey == key) {
+ (*iter)->focus();
+ } else if (controlKey == _currentlyFocusedControl) {
+ (*iter)->unfocus();
+ }
+ }
+
+ _currentlyFocusedControl = key;
+}
+
+void ScriptManager::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos);
+ }
+}
+
+void ScriptManager::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos);
+ }
+}
+
+bool ScriptManager::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ bool cursorWasChanged = false;
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ cursorWasChanged = cursorWasChanged || (*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos);
+ }
+
+ return cursorWasChanged;
+}
+
+void ScriptManager::onKeyDown(Common::KeyState keyState) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->onKeyDown(keyState);
+ }
+}
+
+void ScriptManager::onKeyUp(Common::KeyState keyState) {
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->onKeyUp(keyState);
+ }
+}
+
+void ScriptManager::changeLocation(char world, char room, char node, char view, uint32 offset) {
+ assert(world != 0);
+ debug(1, "Changing location to: %c %c %c %c %u", world, room, node, view, offset);
+
+ // Auto save
+ _engine->getSaveManager()->autoSave();
+
+ // Clear all the containers
+ _referenceTable.clear();
+ _puzzlesToCheck.clear();
+ for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
+ delete (*iter);
+ }
+ _activePuzzles.clear();
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ delete (*iter);
+ }
+ _activeControls.clear();
+
+ // Revert to the idle cursor
+ _engine->getCursorManager()->revertToIdle();
+
+ // Reset the background velocity
+ _engine->getRenderManager()->setBackgroundVelocity(0);
+
+ // Remove any alphaEntries
+ _engine->getRenderManager()->clearAlphaEntries();
+
+ // Clean the global state table
+ cleanStateTable();
+
+ // Parse into puzzles and controls
+ Common::String fileName = Common::String::format("%c%c%c%c.scr", world, room, node, view);
+ parseScrFile(fileName);
+
+ // Change the background position
+ _engine->getRenderManager()->setBackgroundPosition(offset);
+
+ // Enable all the controls
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->enable();
+ }
+
+ // Add all the local puzzles to the queue to be checked
+ for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
+ // Reset any Puzzles that have the flag ONCE_PER_INST
+ if ((getStateFlags((*iter)->key) & ONCE_PER_INST) == ONCE_PER_INST) {
+ setStateValue((*iter)->key, 0);
+ }
+
+ _puzzlesToCheck.push((*iter));
+ }
+
+ // Add all the global puzzles to the queue to be checked
+ for (PuzzleList::iterator iter = _globalPuzzles.begin(); iter != _globalPuzzles.end(); ++iter) {
+ // Reset any Puzzles that have the flag ONCE_PER_INST
+ if ((getStateFlags((*iter)->key) & ONCE_PER_INST) == ONCE_PER_INST) {
+ setStateValue((*iter)->key, 0);
+ }
+
+ _puzzlesToCheck.push((*iter));
+ }
+
+ // Create the puzzle reference table
+ createReferenceTable();
+
+ // Update _currentLocation
+ _currentLocation.world = world;
+ _currentLocation.room = room;
+ _currentLocation.node = node;
+ _currentLocation.view = view;
+ _currentLocation.offset = offset;
+}
+
+void ScriptManager::serializeStateTable(Common::WriteStream *stream) {
+ // Write the number of state value entries
+ stream->writeUint32LE(_globalState.size());
+
+ for (StateMap::iterator iter = _globalState.begin(); iter != _globalState.end(); ++iter) {
+ // Write out the key/value pair
+ stream->writeUint32LE(iter->_key);
+ stream->writeUint32LE(iter->_value);
+ }
+}
+
+void ScriptManager::deserializeStateTable(Common::SeekableReadStream *stream) {
+ // Clear out the current table values
+ _globalState.clear();
+
+ // Read the number of key/value pairs
+ uint32 numberOfPairs = stream->readUint32LE();
+
+ for (uint32 i = 0; i < numberOfPairs; ++i) {
+ uint32 key = stream->readUint32LE();
+ uint32 value = stream->readUint32LE();
+ // Directly access the state table so we don't trigger Puzzle checks
+ _globalState[key] = value;
+ }
+}
+
+void ScriptManager::serializeControls(Common::WriteStream *stream) {
+ // Count how many controls need to save their data
+ // Because WriteStream isn't seekable
+ uint32 numberOfControlsNeedingSerialization = 0;
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ if ((*iter)->needsSerialization()) {
+ numberOfControlsNeedingSerialization++;
+ }
+ }
+ stream->writeUint32LE(numberOfControlsNeedingSerialization);
+
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ (*iter)->serialize(stream);
+ }
+}
+
+void ScriptManager::deserializeControls(Common::SeekableReadStream *stream) {
+ uint32 numberOfControls = stream->readUint32LE();
+
+ for (uint32 i = 0; i < numberOfControls; ++i) {
+ uint32 key = stream->readUint32LE();
+ for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ (*iter)->deserialize(stream);
+ break;
+ }
+ }
+ }
+}
+
+Location ScriptManager::getCurrentLocation() const {
+ Location location = _currentLocation;
+ location.offset = _engine->getRenderManager()->getCurrentBackgroundOffset();
+
+ return location;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h
new file mode 100644
index 0000000000..ab9b03ed30
--- /dev/null
+++ b/engines/zvision/scripting/script_manager.h
@@ -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.
+ *
+ */
+
+#ifndef ZVISION_SCRIPT_MANAGER_H
+#define ZVISION_SCRIPT_MANAGER_H
+
+#include "zvision/scripting/puzzle.h"
+#include "zvision/scripting/control.h"
+
+#include "common/hashmap.h"
+#include "common/queue.h"
+
+
+namespace Common {
+class String;
+class SeekableReadStream;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+struct Location {
+ Location() : world('g'), room('a'), node('r'), view('y'), offset(0) {}
+
+ char world;
+ char room;
+ char node;
+ char view;
+ uint32 offset;
+};
+
+typedef Common::HashMap<uint32, Common::Array<Puzzle *> > PuzzleMap;
+typedef Common::List<Puzzle *> PuzzleList;
+typedef Common::Queue<Puzzle *> PuzzleQueue;
+typedef Common::List<Control *> ControlList;
+typedef Common::HashMap<uint32, uint32> StateMap;
+typedef Common::HashMap<uint32, uint> StateFlagMap;
+
+class ScriptManager {
+public:
+ ScriptManager(ZVision *engine);
+ ~ScriptManager();
+
+public:
+ enum StateFlags {
+ ONCE_PER_INST = 0x01,
+ DO_ME_NOW = 0x02, // Somewhat useless flag since anything that needs to be done immediately has no criteria
+ DISABLED = 0x04
+ };
+
+private:
+ ZVision *_engine;
+ /**
+ * Holds the global state variable. Do NOT directly modify this. Use the accessors and
+ * mutators getStateValue() and setStateValue(). This ensures that Puzzles that reference a
+ * particular state key are checked after the key is modified.
+ */
+ StateMap _globalState;
+ /**
+ * Holds the flags for the global states. This is used to enable/disable puzzles and/or
+ * controls as well as which puzzles should are allowed to be re-executed
+ */
+ StateFlagMap _globalStateFlags;
+ /** References _globalState keys to Puzzles */
+ PuzzleMap _referenceTable;
+ /** Holds the Puzzles that should be checked this frame */
+ PuzzleQueue _puzzlesToCheck;
+ /** Holds the currently active puzzles */
+ PuzzleList _activePuzzles;
+ /** Holds the global puzzles */
+ PuzzleList _globalPuzzles;
+ /** Holds the currently active controls */
+ ControlList _activeControls;
+
+ Location _currentLocation;
+
+ uint32 _currentlyFocusedControl;
+
+public:
+ void initialize();
+ void update(uint deltaTimeMillis);
+
+ uint getStateValue(uint32 key);
+ void setStateValue(uint32 key, uint value);
+ void addToStateValue(uint32 key, uint valueToAdd);
+
+ uint getStateFlags(uint32 key);
+ void setStateFlags(uint32 key, uint flags);
+
+ void addControl(Control *control);
+ Control *getControl(uint32 key);
+
+ void focusControl(uint32 key);
+
+ /**
+ * Called when LeftMouse is pushed.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ void onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called when LeftMouse is lifted.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called on every MouseMove.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called when a key is pressed.
+ *
+ * @param keycode The key that was pressed
+ */
+ void onKeyDown(Common::KeyState keyState);
+ /**
+ * Called when a key is released.
+ *
+ * @param keycode The key that was pressed
+ */
+ void onKeyUp(Common::KeyState keyState);
+
+ void changeLocation(char world, char room, char node, char view, uint32 offset);
+
+ void serializeStateTable(Common::WriteStream *stream);
+ void deserializeStateTable(Common::SeekableReadStream *stream);
+ void serializeControls(Common::WriteStream *stream);
+ void deserializeControls(Common::SeekableReadStream *stream);
+
+ Location getCurrentLocation() const;
+
+private:
+ void createReferenceTable();
+ void updateNodes(uint deltaTimeMillis);
+ void checkPuzzleCriteria();
+ void cleanStateTable();
+
+// TODO: Make this private. It was only made public so Console::cmdParseAllScrFiles() could use it
+public:
+ /**
+ * Parses a script file into triggers and events
+ *
+ * @param fileName Name of the .scr file
+ * @param isGlobal Are the puzzles included in the file global (true). AKA, the won't be purged during location changes
+ */
+ void parseScrFile(const Common::String &fileName, bool isGlobal = false);
+
+private:
+ /**
+ * Parses the stream into a Puzzle object
+ * Helper method for parseScrFile.
+ *
+ * @param puzzle The object to store what is parsed
+ * @param stream Scr file stream
+ */
+ void parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stream);
+
+ /**
+ * Parses the stream into a Criteria object
+ * Helper method for parsePuzzle.
+ *
+ * @param criteria Pointer to the Criteria object to fill
+ * @param stream Scr file stream
+ * @return Whether any criteria were read
+ */
+ bool parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList) const;
+
+ /**
+ * Parses the stream into a ResultAction objects
+ * Helper method for parsePuzzle.
+ *
+ * @param stream Scr file stream
+ * @param actionList The list where the results will be added
+ * @return Created Results object
+ */
+ void parseResults(Common::SeekableReadStream &stream, Common::List<ResultAction *> &actionList) const;
+
+ /**
+ * Helper method for parsePuzzle. Parses the stream into a bitwise or of the StateFlags enum
+ *
+ * @param stream Scr file stream
+ * @return Bitwise OR of all the flags set within the puzzle
+ */
+ uint parseFlags(Common::SeekableReadStream &stream) const;
+
+ /**
+ * Helper method for parseScrFile. Parses the stream into a Control object
+ *
+ * @param line The line initially read
+ * @param stream Scr file stream
+ */
+ void parseControl(Common::String &line, Common::SeekableReadStream &stream);
+};
+
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp
new file mode 100644
index 0000000000..321ac93de2
--- /dev/null
+++ b/engines/zvision/sound/zork_raw.cpp
@@ -0,0 +1,217 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/sound/zork_raw.h"
+
+#include "zvision/zvision.h"
+#include "zvision/detection.h"
+#include "zvision/utility/utility.h"
+
+#include "common/file.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/memstream.h"
+#include "common/bufferedstream.h"
+#include "common/util.h"
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+
+
+namespace ZVision {
+
+const int16 RawZorkStream::_stepAdjustmentTable[8] = {-1, -1, -1, 1, 4, 7, 10, 12};
+
+const int32 RawZorkStream::_amplitudeLookupTable[89] = {0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E,
+ 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F,
+ 0x0022, 0x0025, 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042,
+ 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, 0x0082, 0x008F,
+ 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
+ 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292,
+ 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583,
+ 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, 0x0BD0,
+ 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954,
+ 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
+ 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF};
+
+const SoundParams RawZorkStream::_zNemSoundParamLookupTable[6] = {{'6', 0x2B11, false, false},
+ {'a', 0x5622, false, true},
+ {'b', 0x5622, true, true},
+ {'n', 0x2B11, false, true},
+ {'s', 0x5622, false, true},
+ {'t', 0x5622, true, true}
+};
+
+const SoundParams RawZorkStream::_zgiSoundParamLookupTable[5] = {{'a',0x5622, false, false},
+ {'k',0x2B11, true, true},
+ {'p',0x5622, false, true},
+ {'q',0x5622, true, true},
+ {'u',0xAC44, true, true}
+};
+
+RawZorkStream::RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream)
+ : _rate(rate),
+ _stereo(0),
+ _stream(stream, disposeStream),
+ _endOfData(false) {
+ if (stereo)
+ _stereo = 1;
+
+ _lastSample[0].index = 0;
+ _lastSample[0].sample = 0;
+ _lastSample[1].index = 0;
+ _lastSample[1].sample = 0;
+
+ // Calculate the total playtime of the stream
+ if (stereo)
+ _playtime = Audio::Timestamp(0, _stream->size() / 2, rate);
+ else
+ _playtime = Audio::Timestamp(0, _stream->size(), rate);
+}
+
+int RawZorkStream::readBuffer(int16 *buffer, const int numSamples) {
+ int bytesRead = 0;
+
+ // 0: Left, 1: Right
+ uint channel = 0;
+
+ while (bytesRead < numSamples) {
+ byte encodedSample = _stream->readByte();
+ if (_stream->eos()) {
+ _endOfData = true;
+ return bytesRead;
+ }
+ bytesRead++;
+
+ int16 index = _lastSample[channel].index;
+ uint32 lookUpSample = _amplitudeLookupTable[index];
+
+ int32 sample = 0;
+
+ if (encodedSample & 0x40)
+ sample += lookUpSample;
+ if (encodedSample & 0x20)
+ sample += lookUpSample >> 1;
+ if (encodedSample & 0x10)
+ sample += lookUpSample >> 2;
+ if (encodedSample & 8)
+ sample += lookUpSample >> 3;
+ if (encodedSample & 4)
+ sample += lookUpSample >> 4;
+ if (encodedSample & 2)
+ sample += lookUpSample >> 5;
+ if (encodedSample & 1)
+ sample += lookUpSample >> 6;
+ if (encodedSample & 0x80)
+ sample = -sample;
+
+ sample += _lastSample[channel].sample;
+ sample = CLIP<int32>(sample, -32768, 32767);
+
+ buffer[bytesRead - 1] = (int16)sample;
+
+ index += _stepAdjustmentTable[(encodedSample >> 4) & 7];
+ index = CLIP<int16>(index, 0, 88);
+
+ _lastSample[channel].sample = sample;
+ _lastSample[channel].index = index;
+
+ // Increment and wrap the channel
+ channel = (channel + 1) & _stereo;
+ }
+
+ return bytesRead;
+}
+
+bool RawZorkStream::rewind() {
+ _stream->seek(0, 0);
+ _stream->clearErr();
+ _endOfData = false;
+ _lastSample[0].index = 0;
+ _lastSample[0].sample = 0;
+ _lastSample[1].index = 0;
+ _lastSample[1].sample = 0;
+
+ return true;
+}
+
+Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stream,
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse) {
+ if (stereo)
+ assert(stream->size() % 2 == 0);
+
+ return new RawZorkStream(rate, stereo, disposeAfterUse, stream);
+}
+
+Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size,
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse) {
+ return makeRawZorkStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, stereo, DisposeAfterUse::YES);
+}
+
+Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) {
+ Common::File *file = new Common::File();
+ assert(file->open(filePath));
+
+ Common::String fileName = getFileName(filePath);
+ fileName.toLowercase();
+
+ SoundParams soundParams = { ' ', 0, false, false };
+ bool foundParams = false;
+ char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7];
+
+ if (engine->getGameId() == GID_NEMESIS) {
+ for (int i = 0; i < 6; ++i) {
+ if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) {
+ soundParams = RawZorkStream::_zNemSoundParamLookupTable[i];
+ foundParams = true;
+ }
+ }
+ } else if (engine->getGameId() == GID_GRANDINQUISITOR) {
+ for (int i = 0; i < 6; ++i) {
+ if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) {
+ soundParams = RawZorkStream::_zgiSoundParamLookupTable[i];
+ foundParams = true;
+ }
+ }
+ }
+
+ if (!foundParams)
+ error("Unable to find sound params for file '%s'. File identifier is '%c'", filePath.c_str(), fileIdentifier);
+
+ if (soundParams.packed) {
+ return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams.rate, soundParams.stereo, DisposeAfterUse::YES);
+ } else {
+ byte flags = 0;
+ if (soundParams.stereo)
+ flags |= Audio::FLAG_STEREO;
+
+ return Audio::makeRawStream(file, soundParams.rate, flags, DisposeAfterUse::YES);
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/sound/zork_raw.h b/engines/zvision/sound/zork_raw.h
new file mode 100644
index 0000000000..481ea79f2d
--- /dev/null
+++ b/engines/zvision/sound/zork_raw.h
@@ -0,0 +1,120 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_ZORK_RAW_H
+#define ZVISION_ZORK_RAW_H
+
+#include "audio/audiostream.h"
+
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+struct SoundParams {
+ char identifier;
+ uint32 rate;
+ bool stereo;
+ bool packed;
+};
+
+/**
+ * This is a stream, which allows for playing raw ADPCM data from a stream.
+ */
+class RawZorkStream : public Audio::RewindableAudioStream {
+public:
+ RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream);
+
+ ~RawZorkStream() {
+ }
+
+public:
+ static const SoundParams _zNemSoundParamLookupTable[6];
+ static const SoundParams _zgiSoundParamLookupTable[5];
+
+private:
+ const int _rate; // Sample rate of stream
+ Audio::Timestamp _playtime; // Calculated total play time
+ Common::DisposablePtr<Common::SeekableReadStream> _stream; // Stream to read data from
+ bool _endOfData; // Whether the stream end has been reached
+ uint _stereo;
+
+ /**
+ * Holds the frequency and index from the last sample
+ * 0 holds the left channel, 1 holds the right channel
+ */
+ struct {
+ int32 sample;
+ int16 index;
+ } _lastSample[2];
+
+ static const int16 _stepAdjustmentTable[8];
+ static const int32 _amplitudeLookupTable[89];
+
+public:
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const { return true; }
+ bool endOfData() const { return _endOfData; }
+
+ int getRate() const { return _rate; }
+ Audio::Timestamp getLength() const { return _playtime; }
+
+ bool rewind();
+};
+
+/**
+ * Creates an audio stream, which plays from the given buffer.
+ *
+ * @param buffer Buffer to play from.
+ * @param size Size of the buffer in bytes.
+ * @param rate Rate of the sound data.
+ * @param dispose AfterUse Whether to free the buffer after use (with free!).
+ * @return The new SeekableAudioStream (or 0 on failure).
+ */
+Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size,
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+
+/**
+ * Creates an audio stream, which plays from the given stream.
+ *
+ * @param stream Stream object to play from.
+ * @param rate Rate of the sound data.
+ * @param dispose AfterUse Whether to delete the stream after use.
+ * @return The new SeekableAudioStream (or 0 on failure).
+ */
+Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stream,
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+
+Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine);
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/strings/string_manager.cpp b/engines/zvision/strings/string_manager.cpp
new file mode 100644
index 0000000000..77ed501672
--- /dev/null
+++ b/engines/zvision/strings/string_manager.cpp
@@ -0,0 +1,255 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/strings/string_manager.h"
+
+#include "zvision/fonts/truetype_font.h"
+
+#include "common/file.h"
+#include "common/tokenizer.h"
+#include "common/debug.h"
+
+#include "graphics/fontman.h"
+#include "graphics/colormasks.h"
+
+
+namespace ZVision {
+
+StringManager::StringManager(ZVision *engine)
+ : _engine(engine) {
+}
+
+StringManager::~StringManager() {
+ for (Common::HashMap<Common::String, TruetypeFont *>::iterator iter = _fonts.begin(); iter != _fonts.end(); ++iter) {
+ delete iter->_value;
+ }
+}
+
+void StringManager::initialize(ZVisionGameId gameId) {
+ if (gameId == GID_NEMESIS) {
+ // TODO: Check this hardcoded filename against all versions of Nemesis
+ parseStrFile("nemesis.str");
+ } else if (gameId == GID_GRANDINQUISITOR) {
+ // TODO: Check this hardcoded filename against all versions of Grand Inquisitor
+ parseStrFile("inquis.str");
+ }
+}
+
+void StringManager::parseStrFile(const Common::String &fileName) {
+ Common::File file;
+ if (!file.open(fileName)) {
+ warning("%s does not exist. String parsing failed", fileName.c_str());
+ return;
+ }
+
+ uint lineNumber = 0;
+ while (!file.eos()) {
+ _lastStyle.align = Graphics::kTextAlignLeft;
+ _lastStyle.color = 0;
+ _lastStyle.font = nullptr;
+
+ Common::String asciiLine = readWideLine(file);
+ if (asciiLine.empty()) {
+ continue;
+ }
+
+ char tagString[150];
+ uint tagStringCursor = 0;
+ char textString[150];
+ uint textStringCursor = 0;
+ bool inTag = false;
+
+ for (uint i = 0; i < asciiLine.size(); ++i) {
+ switch (asciiLine[i]) {
+ case '<':
+ inTag = true;
+ if (!_inGameText[lineNumber].fragments.empty()) {
+ _inGameText[lineNumber].fragments.back().text = Common::String(textString, textStringCursor);
+ textStringCursor = 0;
+ }
+ break;
+ case '>':
+ inTag = false;
+ parseTag(Common::String(tagString, tagStringCursor), lineNumber);
+ tagStringCursor = 0;
+ break;
+ default:
+ if (inTag) {
+ tagString[tagStringCursor] = asciiLine[i];
+ tagStringCursor++;
+ } else {
+ textString[textStringCursor] = asciiLine[i];
+ textStringCursor++;
+ }
+ break;
+ }
+ }
+
+ if (textStringCursor > 0) {
+ _inGameText[lineNumber].fragments.back().text = Common::String(textString, textStringCursor);
+ }
+
+ lineNumber++;
+ assert(lineNumber <= NUM_TEXT_LINES);
+ }
+}
+
+void StringManager::parseTag(const Common::String &tagString, uint lineNumber) {
+ Common::StringTokenizer tokenizer(tagString);
+
+ Common::String token = tokenizer.nextToken();
+
+ Common::String fontName;
+ bool bold = false;
+ Graphics::TextAlign align = _lastStyle.align;
+ int point = _lastStyle.font != nullptr ? _lastStyle.font->_fontHeight : 12;
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+
+ while (!token.empty()) {
+ if (token.matchString("font", true)) {
+ fontName = tokenizer.nextToken();
+ } else if (token.matchString("bold", true)) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", false)) {
+ bold = true;
+ }
+ } else if (token.matchString("justify", true)) {
+ token = tokenizer.nextToken();
+ if (token.matchString("center", false)) {
+ align = Graphics::kTextAlignCenter;
+ } else if (token.matchString("right", false)) {
+ align = Graphics::kTextAlignRight;
+ }
+ } else if (token.matchString("point", true)) {
+ point = atoi(tokenizer.nextToken().c_str());
+ } else if (token.matchString("red", true)) {
+ red = atoi(tokenizer.nextToken().c_str());
+ } else if (token.matchString("green", true)) {
+ green = atoi(tokenizer.nextToken().c_str());
+ } else if (token.matchString("blue", true)) {
+ blue = atoi(tokenizer.nextToken().c_str());
+ }
+
+ token = tokenizer.nextToken();
+ }
+
+ TextFragment fragment;
+
+ if (fontName.empty()) {
+ fragment.style.font = _lastStyle.font;
+ } else {
+ Common::String newFontName;
+ if (fontName.matchString("*times new roman*", true)) {
+ if (bold) {
+ newFontName = "timesbd.ttf";
+ } else {
+ newFontName = "times.ttf";
+ }
+ } else if (fontName.matchString("*courier new*", true)) {
+ if (bold) {
+ newFontName = "courbd.ttf";
+ } else {
+ newFontName = "cour.ttf";
+ }
+ } else if (fontName.matchString("*century schoolbook*", true)) {
+ if (bold) {
+ newFontName = "censcbkbd.ttf";
+ } else {
+ newFontName = "censcbk.ttf";
+ }
+ } else if (fontName.matchString("*garamond*", true)) {
+ if (bold) {
+ newFontName = "garabd.ttf";
+ } else {
+ newFontName = "gara.ttf";
+ }
+ } else {
+ debug("Could not identify font: %s. Reverting to Arial", fontName.c_str());
+ if (bold) {
+ newFontName = "zorknorm.ttf";
+ } else {
+ newFontName = "arial.ttf";
+ }
+ }
+
+ Common::String fontKey = Common::String::format("%s-%d", newFontName.c_str(), point);
+ if (_fonts.contains(fontKey)) {
+ fragment.style.font = _fonts[fontKey];
+ } else {
+ fragment.style.font = new TruetypeFont(_engine, point);
+ fragment.style.font->loadFile(newFontName);
+ _fonts[fontKey] = fragment.style.font;
+ }
+ }
+
+ fragment.style.align = align;
+ fragment.style.color = Graphics::ARGBToColor<Graphics::ColorMasks<565> >(0, red, green, blue);
+ _inGameText[lineNumber].fragments.push_back(fragment);
+
+ _lastStyle = fragment.style;
+}
+
+Common::String StringManager::readWideLine(Common::SeekableReadStream &stream) {
+ Common::String asciiString;
+
+ // Don't spam the user with warnings about UTF-16 support.
+ // Just do one warning per String
+ bool charOverflowWarning = false;
+
+ uint16 value = stream.readUint16LE();
+ while (!stream.eos()) {
+ // Check for CRLF
+ if (value == 0x0A0D) {
+ // Read in the extra NULL char
+ stream.readByte(); // \0
+ // End of the line. Break
+ break;
+ }
+
+ // Crush each octet pair to a single octet with a simple cast
+ if (value > 255) {
+ charOverflowWarning = true;
+ value = '?';
+ }
+ char charValue = (char)value;
+
+ asciiString += charValue;
+
+ value = stream.readUint16LE();
+ }
+
+ if (charOverflowWarning) {
+ warning("UTF-16 is not supported. Characters greater than 255 are replaced with '?'");
+ }
+
+ return asciiString;
+}
+
+StringManager::TextStyle StringManager::getTextStyle(uint stringNumber) {
+ return _inGameText[stringNumber].fragments.front().style;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/strings/string_manager.h b/engines/zvision/strings/string_manager.h
new file mode 100644
index 0000000000..86bb9638d7
--- /dev/null
+++ b/engines/zvision/strings/string_manager.h
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef ZVISION_STRING_MANAGER_H
+#define ZVISION_STRING_MANAGER_H
+
+#include "zvision/detection.h"
+#include "zvision/fonts/truetype_font.h"
+
+
+namespace Graphics {
+class FontManager;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+class StringManager {
+public:
+ StringManager(ZVision *engine);
+ ~StringManager();
+
+public:
+ struct TextStyle {
+ TruetypeFont *font;
+ uint16 color; // In RBG 565
+ Graphics::TextAlign align;
+ };
+
+ struct TextFragment {
+ TextStyle style;
+ Common::String text;
+ };
+
+private:
+ struct InGameText {
+ Common::List<TextFragment> fragments;
+ };
+
+ enum {
+ NUM_TEXT_LINES = 56 // Max number of lines in a .str file. We hardcode this number because we know ZNem uses 42 strings and ZGI uses 56
+ };
+
+private:
+ ZVision *_engine;
+ InGameText _inGameText[NUM_TEXT_LINES];
+ Common::HashMap<Common::String, TruetypeFont *> _fonts;
+
+ TextStyle _lastStyle;
+
+public:
+ void initialize(ZVisionGameId gameId);
+ StringManager::TextStyle getTextStyle(uint stringNumber);
+
+private:
+ void parseStrFile(const Common::String &fileName);
+ void parseTag(const Common::String &tagString, uint lineNumber);
+
+ static Common::String readWideLine(Common::SeekableReadStream &stream);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/subtitles/subtitles.h b/engines/zvision/subtitles/subtitles.h
new file mode 100644
index 0000000000..13426e03e4
--- /dev/null
+++ b/engines/zvision/subtitles/subtitles.h
@@ -0,0 +1,29 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef ZVISION_SUBTITLES_H
+#define ZVISION_SUBTITLES_H
+
+// TODO: Implement Subtitles
+
+#endif
diff --git a/engines/zvision/utility/clock.cpp b/engines/zvision/utility/clock.cpp
new file mode 100644
index 0000000000..49e4b32054
--- /dev/null
+++ b/engines/zvision/utility/clock.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/utility/clock.h"
+
+#include "common/system.h"
+
+
+namespace ZVision {
+
+Clock::Clock(OSystem *system)
+ : _system(system),
+ _lastTime(0),
+ _deltaTime(0),
+ _pausedTime(0),
+ _paused(false) {
+}
+
+void Clock::update() {
+ uint32 currentTime = _system->getMillis();
+
+ _deltaTime = (currentTime - _lastTime);
+ if (_paused) {
+ _deltaTime -= (currentTime - _pausedTime);
+ }
+
+ if (_deltaTime < 0) {
+ _deltaTime = 0;
+ }
+
+ _lastTime = currentTime;
+}
+
+void Clock::start() {
+ if (_paused) {
+ _lastTime = _system->getMillis();
+ _paused = false;
+ }
+}
+
+void Clock::stop() {
+ if (!_paused) {
+ _pausedTime = _system->getMillis();
+ _paused = true;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/utility/clock.h b/engines/zvision/utility/clock.h
new file mode 100644
index 0000000000..3939ba1612
--- /dev/null
+++ b/engines/zvision/utility/clock.h
@@ -0,0 +1,78 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef ZVISION_CLOCK_H
+#define ZVISION_CLOCK_H
+
+#include "common/types.h"
+
+class OSystem;
+
+namespace ZVision {
+
+/* Class for handling frame to frame deltaTime while keeping track of time pauses/un-pauses */
+class Clock {
+public:
+ Clock(OSystem *system);
+
+private:
+ OSystem *_system;
+ uint32 _lastTime;
+ int32 _deltaTime;
+ uint32 _pausedTime;
+ bool _paused;
+
+public:
+ /**
+ * Updates _deltaTime with the difference between the current time and
+ * when the last update() was called.
+ */
+ void update();
+ /**
+ * Get the delta time since the last frame. (The time between update() calls)
+ *
+ * @return Delta time since the last frame (in milliseconds)
+ */
+ uint32 getDeltaTime() const { return _deltaTime; }
+ /**
+ * Get the time from the program starting to the last update() call
+ *
+ * @return Time from program start to last update() call (in milliseconds)
+ */
+ uint32 getLastMeasuredTime() { return _lastTime; }
+
+ /**
+ * Pause the clock. Any future delta times will take this pause into account.
+ * Has no effect if the clock is already paused.
+ */
+ void start();
+ /**
+ * Un-pause the clock.
+ * Has no effect if the clock is already un-paused.
+ */
+ void stop();
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/utility/lzss_read_stream.cpp b/engines/zvision/utility/lzss_read_stream.cpp
new file mode 100644
index 0000000000..dc537cd8ab
--- /dev/null
+++ b/engines/zvision/utility/lzss_read_stream.cpp
@@ -0,0 +1,103 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/utility/lzss_read_stream.h"
+
+
+namespace ZVision {
+
+LzssReadStream::LzssReadStream(Common::SeekableReadStream *source)
+ : _source(source),
+ // It's convention to set the starting cursor position to blockSize - 16
+ _windowCursor(0x0FEE),
+ _eosFlag(false) {
+ // Clear the window to null
+ memset(_window, 0, BLOCK_SIZE);
+}
+
+uint32 LzssReadStream::decompressBytes(byte *destination, uint32 numberOfBytes) {
+ uint32 destinationCursor = 0;
+
+ while (destinationCursor < numberOfBytes) {
+ byte flagbyte = _source->readByte();
+ if (_source->eos())
+ break;
+ uint mask = 1;
+
+ for (int i = 0; i < 8; ++i) {
+ if ((flagbyte & mask) == mask) {
+ byte data = _source->readByte();
+ if (_source->eos()) {
+ return destinationCursor;
+ }
+
+ _window[_windowCursor] = data;
+ destination[destinationCursor++] = data;
+
+ // Increment and wrap the window cursor
+ _windowCursor = (_windowCursor + 1) & 0xFFF;
+ } else {
+ byte low = _source->readByte();
+ if (_source->eos()) {
+ return destinationCursor;
+ }
+
+ byte high = _source->readByte();
+ if (_source->eos()) {
+ return destinationCursor;
+ }
+
+ uint16 length = (high & 0xF) + 2;
+ uint16 offset = low | ((high & 0xF0)<<4);
+
+ for(int j = 0; j <= length; ++j) {
+ byte temp = _window[(offset + j) & 0xFFF];
+ _window[_windowCursor] = temp;
+ destination[destinationCursor++] = temp;
+ _windowCursor = (_windowCursor + 1) & 0xFFF;
+ }
+ }
+
+ mask = mask << 1;
+ }
+ }
+
+ return destinationCursor;
+}
+
+bool LzssReadStream::eos() const {
+ return _eosFlag;
+}
+
+uint32 LzssReadStream::read(void *dataPtr, uint32 dataSize) {
+ uint32 bytesRead = decompressBytes(static_cast<byte *>(dataPtr), dataSize);
+ if (bytesRead < dataSize) {
+ // Flag that we're at EOS
+ _eosFlag = true;
+ }
+
+ return dataSize;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/utility/lzss_read_stream.h b/engines/zvision/utility/lzss_read_stream.h
new file mode 100644
index 0000000000..f6b1eb1a65
--- /dev/null
+++ b/engines/zvision/utility/lzss_read_stream.h
@@ -0,0 +1,72 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef ZVISION_LZSS_STREAM_H
+#define ZVISION_LZSS_STREAM_H
+
+#include "common/stream.h"
+#include "common/array.h"
+
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace ZVision {
+
+class LzssReadStream : public Common::ReadStream {
+public:
+ /**
+ * A class that decompresses LZSS data and implements ReadStream for easy access
+ * to the decompiled data.
+ *
+ * @param source The source data
+ */
+ LzssReadStream(Common::SeekableReadStream *source);
+
+private:
+ enum {
+ BLOCK_SIZE = 0x1000
+ };
+
+private:
+ Common::SeekableReadStream *_source;
+ byte _window[BLOCK_SIZE];
+ uint _windowCursor;
+ bool _eosFlag;
+
+public:
+ bool eos() const;
+ uint32 read(void *dataPtr, uint32 dataSize);
+
+private:
+ /**
+ * Decompress the next <numberOfBytes> from the source stream. Or until EOS
+ *
+ * @param numberOfBytes How many bytes to decompress. This is a count of source bytes, not destination bytes
+ */
+ uint32 decompressBytes(byte* destination, uint32 numberOfBytes);
+};
+
+}
+
+#endif
diff --git a/engines/zvision/utility/single_value_container.cpp b/engines/zvision/utility/single_value_container.cpp
new file mode 100644
index 0000000000..2667b27b75
--- /dev/null
+++ b/engines/zvision/utility/single_value_container.cpp
@@ -0,0 +1,348 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/utility/single_value_container.h"
+
+#include "common/textconsole.h"
+#include "common/str.h"
+
+
+namespace ZVision {
+
+SingleValueContainer::SingleValueContainer(ValueType type) : _objectType(type) { }
+
+SingleValueContainer::SingleValueContainer(bool value) : _objectType(BOOL) {
+ _value.boolVal = value;
+}
+
+SingleValueContainer::SingleValueContainer(byte value) : _objectType(BYTE) {
+ _value.byteVal = value;
+}
+
+SingleValueContainer::SingleValueContainer(int16 value) : _objectType(INT16) {
+ _value.int16Val = value;
+}
+
+SingleValueContainer::SingleValueContainer(uint16 value) : _objectType(UINT16) {
+ _value.uint16Val = value;
+}
+
+SingleValueContainer::SingleValueContainer(int32 value) : _objectType(INT32) {
+ _value.int32Val = value;
+}
+
+SingleValueContainer::SingleValueContainer(uint32 value) : _objectType(UINT32) {
+ _value.uint32Val = value;
+}
+
+SingleValueContainer::SingleValueContainer(float value) : _objectType(FLOAT) {
+ _value.floatVal = value;
+}
+
+SingleValueContainer::SingleValueContainer(double value) : _objectType(DOUBLE) {
+ _value.doubleVal = value;
+}
+
+SingleValueContainer::SingleValueContainer(Common::String value) : _objectType(BYTE) {
+ _value.stringVal = new char[value.size() + 1];
+ memcpy(_value.stringVal, value.c_str(), value.size() + 1);
+}
+
+SingleValueContainer::SingleValueContainer(const SingleValueContainer &other) {
+ _objectType = other._objectType;
+
+ switch (_objectType) {
+ case BOOL:
+ _value.boolVal = other._value.boolVal;
+ break;
+ case BYTE:
+ _value.byteVal = other._value.byteVal;
+ break;
+ case INT16:
+ _value.int16Val = other._value.int16Val;
+ break;
+ case UINT16:
+ _value.uint16Val = other._value.uint16Val;
+ break;
+ case INT32:
+ _value.int32Val = other._value.int32Val;
+ break;
+ case UINT32:
+ _value.uint32Val = other._value.uint32Val;
+ break;
+ case FLOAT:
+ _value.floatVal = other._value.floatVal;
+ break;
+ case DOUBLE:
+ _value.doubleVal = other._value.doubleVal;
+ break;
+ case STRING:
+ uint32 length = strlen(other._value.stringVal);
+ _value.stringVal = new char[length + 1];
+ memcpy(_value.stringVal, other._value.stringVal, length + 1);
+ break;
+ }
+}
+
+SingleValueContainer::~SingleValueContainer() {
+ deleteCharPointer();
+}
+
+void SingleValueContainer::deleteCharPointer() {
+ if (_objectType == STRING)
+ delete[] _value.stringVal;
+}
+
+
+SingleValueContainer &SingleValueContainer::operator=(const bool &rhs) {
+ if (_objectType == BOOL) {
+ _value.boolVal = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = BOOL;
+ _value.boolVal = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const byte &rhs) {
+ if (_objectType == BYTE) {
+ _value.byteVal = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = BYTE;
+ _value.byteVal = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const int16 &rhs) {
+ if (_objectType == INT16) {
+ _value.int16Val = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = INT16;
+ _value.int16Val = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const uint16 &rhs) {
+ if (_objectType == UINT16) {
+ _value.uint16Val = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = UINT16;
+ _value.uint16Val = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const int32 &rhs) {
+ if (_objectType == INT32) {
+ _value.int32Val = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = INT32;
+ _value.int32Val = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const uint32 &rhs) {
+ if (_objectType == UINT32) {
+ _value.uint32Val = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = UINT32;
+ _value.uint32Val = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const float &rhs) {
+ if (_objectType == FLOAT) {
+ _value.floatVal = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = FLOAT;
+ _value.floatVal = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const double &rhs) {
+ if (_objectType == DOUBLE) {
+ _value.doubleVal = rhs;
+ return *this;
+ }
+
+ deleteCharPointer();
+ _objectType = DOUBLE;
+ _value.doubleVal = rhs;
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const Common::String &rhs) {
+ if (_objectType != STRING) {
+ _objectType = STRING;
+ _value.stringVal = new char[rhs.size() + 1];
+ memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
+
+ return *this;
+ }
+
+ uint32 length = strlen(_value.stringVal);
+ if (length <= rhs.size() + 1) {
+ memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
+ } else {
+ delete[] _value.stringVal;
+ _value.stringVal = new char[rhs.size() + 1];
+ memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
+ }
+
+ return *this;
+}
+
+SingleValueContainer &SingleValueContainer::operator=(const SingleValueContainer &rhs) {
+ switch (_objectType) {
+ case BOOL:
+ return operator=(rhs._value.boolVal);
+ case BYTE:
+ return operator=(rhs._value.byteVal);
+ case INT16:
+ return operator=(rhs._value.int16Val);
+ case UINT16:
+ return operator=(rhs._value.uint16Val);
+ case INT32:
+ return operator=(rhs._value.int32Val);
+ case UINT32:
+ return operator=(rhs._value.uint32Val);
+ case FLOAT:
+ return operator=(rhs._value.floatVal);
+ case DOUBLE:
+ return operator=(rhs._value.doubleVal);
+ case STRING:
+ uint32 length = strlen(rhs._value.stringVal);
+
+ _value.stringVal = new char[length + 1];
+ memcpy(_value.stringVal, rhs._value.stringVal, length + 1);
+
+ return *this;
+ }
+
+ return *this;
+}
+
+
+bool SingleValueContainer::getBoolValue(bool *returnValue) const {
+ if (_objectType != BOOL) {
+ warning("'Object' is not storing a bool.");
+ return false;
+ }
+
+ *returnValue = _value.boolVal;
+ return true;
+}
+
+bool SingleValueContainer::getByteValue(byte *returnValue) const {
+ if (_objectType != BYTE)
+ warning("'Object' is not storing a byte.");
+
+ *returnValue = _value.byteVal;
+ return true;
+}
+
+bool SingleValueContainer::getInt16Value(int16 *returnValue) const {
+ if (_objectType != INT16)
+ warning("'Object' is not storing an int16.");
+
+ *returnValue = _value.int16Val;
+ return true;
+}
+
+bool SingleValueContainer::getUInt16Value(uint16 *returnValue) const {
+ if (_objectType != UINT16)
+ warning("'Object' is not storing a uint16.");
+
+ *returnValue = _value.uint16Val;
+ return true;
+}
+
+bool SingleValueContainer::getInt32Value(int32 *returnValue) const {
+ if (_objectType != INT32)
+ warning("'Object' is not storing an int32.");
+
+ *returnValue = _value.int32Val;
+ return true;
+}
+
+bool SingleValueContainer::getUInt32Value(uint32 *returnValue) const {
+ if (_objectType != UINT32)
+ warning("'Object' is not storing a uint32.");
+
+ *returnValue = _value.uint32Val;
+ return true;
+}
+
+bool SingleValueContainer::getFloatValue(float *returnValue) const {
+ if (_objectType != FLOAT)
+ warning("'Object' is not storing a float.");
+
+ *returnValue = _value.floatVal;
+ return true;
+}
+
+bool SingleValueContainer::getDoubleValue(double *returnValue) const {
+ if (_objectType != DOUBLE)
+ warning("'Object' is not storing a double.");
+
+ *returnValue = _value.doubleVal;
+ return true;
+}
+
+bool SingleValueContainer::getStringValue(Common::String *returnValue) const {
+ if (_objectType != STRING)
+ warning("'Object' is not storing a Common::String.");
+
+ *returnValue = _value.stringVal;
+ return true;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/utility/single_value_container.h b/engines/zvision/utility/single_value_container.h
new file mode 100644
index 0000000000..45b5a89e95
--- /dev/null
+++ b/engines/zvision/utility/single_value_container.h
@@ -0,0 +1,183 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_SINGLE_VALUE_CONTAINER_H
+#define ZVISION_SINGLE_VALUE_CONTAINER_H
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+/**
+ * A generic single value storage class. It is useful for storing different
+ * value types in a single List, Hashmap, etc.
+ */
+class SingleValueContainer {
+public:
+ enum ValueType {
+ BOOL,
+ BYTE,
+ INT16,
+ UINT16,
+ INT32,
+ UINT32,
+ FLOAT,
+ DOUBLE,
+ STRING
+ };
+
+ // Constructors
+ explicit SingleValueContainer(ValueType type);
+ explicit SingleValueContainer(bool value);
+ explicit SingleValueContainer(byte value);
+ explicit SingleValueContainer(int16 value);
+ explicit SingleValueContainer(uint16 value);
+ explicit SingleValueContainer(int32 value);
+ explicit SingleValueContainer(uint32 value);
+ explicit SingleValueContainer(float value);
+ explicit SingleValueContainer(double value);
+ explicit SingleValueContainer(Common::String value);
+
+ // Copy constructor
+ explicit SingleValueContainer(const SingleValueContainer& other);
+
+ // Destructor
+ ~SingleValueContainer();
+
+private:
+ ValueType _objectType;
+
+ union {
+ bool boolVal;
+ byte byteVal;
+ int16 int16Val;
+ uint16 uint16Val;
+ int32 int32Val;
+ uint32 uint32Val;
+ float floatVal;
+ double doubleVal;
+ char *stringVal;
+ } _value;
+
+public:
+ SingleValueContainer &operator=(const bool &rhs);
+ SingleValueContainer &operator=(const byte &rhs);
+ SingleValueContainer &operator=(const int16 &rhs);
+ SingleValueContainer &operator=(const uint16 &rhs);
+ SingleValueContainer &operator=(const int32 &rhs);
+ SingleValueContainer &operator=(const uint32 &rhs);
+ SingleValueContainer &operator=(const float &rhs);
+ SingleValueContainer &operator=(const double &rhs);
+ SingleValueContainer &operator=(const Common::String &rhs);
+
+ SingleValueContainer& operator=(const SingleValueContainer &rhs);
+
+ /**
+ * Retrieve a bool from the container. If the container is not storing a
+ * bool, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getBoolValue(bool *returnValue) const;
+ /**
+ * Retrieve a byte from the container. If the container is not storing a
+ * byte, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getByteValue(byte *returnValue) const;
+ /**
+ * Retrieve an int16 from the container. If the container is not storing an
+ * int16, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getInt16Value(int16 *returnValue) const;
+ /**
+ * Retrieve a uint16 from the container. If the container is not storing a
+ * uint16, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getUInt16Value(uint16 *returnValue) const;
+ /**
+ * Retrieve an int32 from the container. If the container is not storing an
+ * int32, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getInt32Value(int32 *returnValue) const;
+ /**
+ * Retrieve a uint32 from the container. If the container is not storing a
+ * uint32, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getUInt32Value(uint32 *returnValue) const;
+ /**
+ * Retrieve a float from the container. If the container is not storing a
+ * float, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getFloatValue(float *returnValue) const;
+ /**
+ * Retrieve a double from the container. If the container is not storing a
+ * double, this will return false and display a warning().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getDoubleValue(double *returnValue) const;
+ /**
+ * Retrieve a String from the container. If the container is not storing a
+ * string, this will return false and display a warning().
+ *
+ * Caution: Strings are internally stored as char[]. getStringValue uses
+ * Common::String::operator=(char *) to do the assigment, which uses both
+ * strlen() AND memmove().
+ *
+ * @param returnValue Pointer to where you want the value stored
+ * @return Value indicating whether the value assignment was successful
+ */
+ bool getStringValue(Common::String *returnValue) const;
+
+private:
+ /**
+ * Helper method for destruction and assignment. It checks to see
+ * if the char pointer is being used, and if so calls delete on it
+ */
+ void deleteCharPointer();
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/utility/utility.cpp b/engines/zvision/utility/utility.cpp
new file mode 100644
index 0000000000..6471d21e6c
--- /dev/null
+++ b/engines/zvision/utility/utility.cpp
@@ -0,0 +1,237 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/utility/utility.h"
+
+#include "zvision/zvision.h"
+#include "zvision/sound/zork_raw.h"
+
+#include "common/tokenizer.h"
+#include "common/file.h"
+
+
+namespace ZVision {
+
+void writeFileContentsToFile(const Common::String &sourceFile, const Common::String &destFile) {
+ Common::File f;
+ if (!f.open(sourceFile)) {
+ return;
+ }
+
+ byte* buffer = new byte[f.size()];
+ f.read(buffer, f.size());
+
+ Common::DumpFile dumpFile;
+ dumpFile.open(destFile);
+
+ dumpFile.write(buffer, f.size());
+ dumpFile.flush();
+ dumpFile.close();
+
+ delete[] buffer;
+}
+
+void trimCommentsAndWhiteSpace(Common::String *string) {
+ for (int i = string->size() - 1; i >= 0; i--) {
+ if ((*string)[i] == '#') {
+ string->erase(i);
+ }
+ }
+
+ string->trim();
+}
+
+void tryToDumpLine(const Common::String &key,
+ Common::String &line,
+ Common::HashMap<Common::String, byte> *count,
+ Common::HashMap<Common::String, bool> *fileAlreadyUsed,
+ Common::DumpFile &output) {
+ const byte numberOfExamplesPerType = 8;
+
+ if ((*count)[key] < numberOfExamplesPerType && !(*fileAlreadyUsed)[key]) {
+ output.writeString(line);
+ output.writeByte('\n');
+ (*count)[key]++;
+ (*fileAlreadyUsed)[key] = true;
+ }
+}
+
+void dumpEveryResultAction(const Common::String &destFile) {
+ Common::HashMap<Common::String, byte> count;
+ Common::HashMap<Common::String, bool> fileAlreadyUsed;
+
+ Common::DumpFile output;
+ output.open(destFile);
+
+ // Find scr files
+ Common::ArchiveMemberList list;
+ SearchMan.listMatchingMembers(list, "*.scr");
+
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ Common::SeekableReadStream *stream = (*iter)->createReadStream();
+
+ Common::String line = stream->readLine();
+ trimCommentsAndWhiteSpace(&line);
+
+ while (!stream->eos()) {
+ if (line.matchString("*:add*", true)) {
+ tryToDumpLine("add", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:animplay*", true)) {
+ tryToDumpLine("animplay", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:animpreload*", true)) {
+ tryToDumpLine("animpreload", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:animunload*", true)) {
+ tryToDumpLine("animunload", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:attenuate*", true)) {
+ tryToDumpLine("attenuate", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:assign*", true)) {
+ tryToDumpLine("assign", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:change_location*", true)) {
+ tryToDumpLine("change_location", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:crossfade*", true) && !fileAlreadyUsed["add"]) {
+ tryToDumpLine("crossfade", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:debug*", true)) {
+ tryToDumpLine("debug", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:delay_render*", true)) {
+ tryToDumpLine("delay_render", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:disable_control*", true)) {
+ tryToDumpLine("disable_control", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:disable_venus*", true)) {
+ tryToDumpLine("disable_venus", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:display_message*", true)) {
+ tryToDumpLine("display_message", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:dissolve*", true)) {
+ tryToDumpLine("dissolve", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:distort*", true)) {
+ tryToDumpLine("distort", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:enable_control*", true)) {
+ tryToDumpLine("enable_control", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:flush_mouse_events*", true)) {
+ tryToDumpLine("flush_mouse_events", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:inventory*", true)) {
+ tryToDumpLine("inventory", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:kill*", true)) {
+ tryToDumpLine("kill", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:menu_bar_enable*", true)) {
+ tryToDumpLine("menu_bar_enable", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:music*", true)) {
+ tryToDumpLine("music", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:pan_track*", true)) {
+ tryToDumpLine("pan_track", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:playpreload*", true)) {
+ tryToDumpLine("playpreload", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:preferences*", true)) {
+ tryToDumpLine("preferences", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:quit*", true)) {
+ tryToDumpLine("quit", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:random*", true)) {
+ tryToDumpLine("random", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:region*", true)) {
+ tryToDumpLine("region", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:restore_game*", true)) {
+ tryToDumpLine("restore_game", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:rotate_to*", true)) {
+ tryToDumpLine("rotate_to", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:save_game*", true)) {
+ tryToDumpLine("save_game", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:set_partial_screen*", true)) {
+ tryToDumpLine("set_partial_screen", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:set_screen*", true)) {
+ tryToDumpLine("set_screen", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:set_venus*", true)) {
+ tryToDumpLine("set_venus", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:stop*", true)) {
+ tryToDumpLine("stop", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:streamvideo*", true)) {
+ tryToDumpLine("streamvideo", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:syncsound*", true)) {
+ tryToDumpLine("syncsound", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:timer*", true)) {
+ tryToDumpLine("timer", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:ttytext*", true)) {
+ tryToDumpLine("ttytext", line, &count, &fileAlreadyUsed, output);
+ } else if (line.matchString("*:universe_music*", true)) {
+ tryToDumpLine("universe_music", line, &count, &fileAlreadyUsed, output);
+ }
+
+ line = stream->readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
+ for (Common::HashMap<Common::String, bool>::iterator fileUsedIter = fileAlreadyUsed.begin(); fileUsedIter != fileAlreadyUsed.end(); ++fileUsedIter) {
+ fileUsedIter->_value = false;
+ }
+ }
+
+ output.close();
+}
+
+Common::String getFileName(const Common::String &fullPath) {
+ Common::StringTokenizer tokenizer(fullPath, "/\\");
+ Common::String token;
+ while (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ }
+
+ return token;
+}
+
+void convertRawToWav(const Common::String &inputFile, ZVision *engine, const Common::String &outputFile) {
+ Common::File file;
+ if (!file.open(inputFile))
+ return;
+
+ Audio::AudioStream *audioStream = makeRawZorkStream(inputFile, engine);
+
+ Common::DumpFile output;
+ output.open(outputFile);
+
+ output.writeUint32BE(MKTAG('R', 'I', 'F', 'F'));
+ output.writeUint32LE(file.size() * 2 + 36);
+ output.writeUint32BE(MKTAG('W', 'A', 'V', 'E'));
+ output.writeUint32BE(MKTAG('f', 'm', 't', ' '));
+ output.writeUint32LE(16);
+ output.writeUint16LE(1);
+ uint16 numChannels;
+ if (audioStream->isStereo()) {
+ numChannels = 2;
+ output.writeUint16LE(2);
+ } else {
+ numChannels = 1;
+ output.writeUint16LE(1);
+ }
+ output.writeUint32LE(audioStream->getRate());
+ output.writeUint32LE(audioStream->getRate() * numChannels * 2);
+ output.writeUint16LE(numChannels * 2);
+ output.writeUint16LE(16);
+ output.writeUint32BE(MKTAG('d', 'a', 't', 'a'));
+ output.writeUint32LE(file.size() * 2);
+ int16 *buffer = new int16[file.size()];
+ audioStream->readBuffer(buffer, file.size());
+ output.write(buffer, file.size() * 2);
+
+ delete[] buffer;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/utility/utility.h b/engines/zvision/utility/utility.h
new file mode 100644
index 0000000000..fb571f3fe8
--- /dev/null
+++ b/engines/zvision/utility/utility.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.
+ *
+ *
+ */
+
+#ifndef ZVISION_UTILITY_H
+#define ZVISION_UTILITY_H
+
+#include "common/array.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+/**
+ * Opens the sourceFile utilizing Common::File (aka SearchMan) and writes the
+ * contents to destFile. destFile is created in the working directory
+ *
+ * @param sourceFile The 'file' you want the contents of
+ * @param destFile The name of the file where the content will be written to
+ */
+void writeFileContentsToFile(const Common::String &sourceFile, const Common::String &destFile);
+
+/**
+ * Removes any line comments using '#' as a sequence start.
+ * Then removes any trailing and leading 'whitespace' using String::trim()
+ * Note: String::trim uses isspace() to determine what is whitespace and what is not.
+ *
+ * @param string The string to modify. It is modified in place
+ */
+void trimCommentsAndWhiteSpace(Common::String *string);
+
+/**
+ * Searches through all the .scr files and dumps 'numberOfExamplesPerType' examples of each type of ResultAction
+ * ZVision::initialize() must have been called before this function can be used.
+ *
+ * @param destFile Where to write the examples
+ */
+void dumpEveryResultAction(const Common::String &destFile);
+
+/**
+ * Removes all duplicate entries from container. Relative order will be preserved.
+ *
+ * @param container The Array to remove duplicate entries from
+ */
+template<class T>
+void removeDuplicateEntries(Common::Array<T> &container) {
+ // Length of modified array
+ uint newLength = 1;
+ uint j;
+
+ for(uint i = 1; i < container.size(); i++) {
+ for(j = 0; j < newLength; j++) {
+ if (container[i] == container[j]) {
+ break;
+ }
+ }
+
+ // If none of the values in index[0..j] of container are the same as array[i],
+ // then copy the current value to corresponding new position in array
+ if (j == newLength) {
+ container[newLength++] = container[i];
+ }
+ }
+
+ // Actually remove the unneeded space
+ while (container.size() < newLength) {
+ container.pop_back();
+ }
+}
+
+/**
+ * Gets the name of the file (including extension). Forward or back slashes
+ * are interpreted as directory changes
+ *
+ * @param fullPath A full or partial path to the file. Ex: folderOne/folderTwo/file.txt
+ * @return The name of the file without any preceding directories. Ex: file.txt
+ */
+Common::String getFileName(const Common::String &fullPath);
+
+/**
+ * Converts a ZVision .RAW file to a .WAV
+ * The .WAV will be created in the working directory and will overwrite any existing file
+ *
+ * @param inputFile The path to the input .RAW file
+ * @param outputFile The name of the output .WAV file
+ */
+void convertRawToWav(const Common::String &inputFile, ZVision *engine, const Common::String &outputFile);
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp
new file mode 100644
index 0000000000..efaecb5045
--- /dev/null
+++ b/engines/zvision/video/video.cpp
@@ -0,0 +1,171 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/zvision.h"
+
+#include "zvision/utility/clock.h"
+#include "zvision/graphics/render_manager.h"
+
+#include "common/system.h"
+
+#include "video/video_decoder.h"
+
+#include "engines/util.h"
+
+#include "graphics/surface.h"
+
+
+namespace ZVision {
+
+// Taken/modified from SCI
+void scaleBuffer(const byte *src, byte *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint scaleAmount) {
+ assert(bytesPerPixel == 1 || bytesPerPixel == 2);
+
+ const uint32 newWidth = srcWidth * scaleAmount;
+ const uint32 pitch = newWidth * bytesPerPixel;
+ const byte *srcPtr = src;
+
+ if (bytesPerPixel == 1) {
+ for (uint32 y = 0; y < srcHeight; ++y) {
+ for (uint32 x = 0; x < srcWidth; ++x) {
+ const byte color = *srcPtr++;
+
+ for (uint i = 0; i < scaleAmount; ++i) {
+ dst[i] = color;
+ dst[pitch + i] = color;
+ }
+ dst += scaleAmount;
+ }
+ dst += pitch;
+ }
+ } else if (bytesPerPixel == 2) {
+ for (uint32 y = 0; y < srcHeight; ++y) {
+ for (uint32 x = 0; x < srcWidth; ++x) {
+ const byte color = *srcPtr++;
+ const byte color2 = *srcPtr++;
+
+ for (uint i = 0; i < scaleAmount; ++i) {
+ uint index = i *2;
+
+ dst[index] = color;
+ dst[index + 1] = color2;
+ dst[pitch + index] = color;
+ dst[pitch + index + 1] = color2;
+ }
+ dst += 2 * scaleAmount;
+ }
+ dst += pitch;
+ }
+ }
+}
+
+void ZVision::playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect, bool skippable) {
+ byte bytesPerPixel = videoDecoder.getPixelFormat().bytesPerPixel;
+
+ uint16 origWidth = videoDecoder.getWidth();
+ uint16 origHeight = videoDecoder.getHeight();
+
+ uint scale = 1;
+ // If destRect is empty, no specific scaling was requested. However, we may choose to do scaling anyway
+ if (destRect.isEmpty()) {
+ // Most videos are very small. Therefore we do a simple 2x scale
+ if (origWidth * 2 <= 640 && origHeight * 2 <= 480) {
+ scale = 2;
+ }
+ } else {
+ // Assume bilinear scaling. AKA calculate the scale from just the width.
+ // Also assume that the scaling is in integral intervals. AKA no 1.5x scaling
+ // TODO: Test ^these^ assumptions
+ scale = destRect.width() / origWidth;
+
+ // TODO: Test if we need to support downscale.
+ }
+
+ uint16 pitch = origWidth * bytesPerPixel;
+
+ uint16 finalWidth = origWidth * scale;
+ uint16 finalHeight = origHeight * scale;
+
+ byte *scaledVideoFrameBuffer = 0;
+ if (scale != 1) {
+ scaledVideoFrameBuffer = new byte[finalWidth * finalHeight * bytesPerPixel];
+ }
+
+ uint16 x = ((WINDOW_WIDTH - finalWidth) / 2) + destRect.left;
+ uint16 y = ((WINDOW_HEIGHT - finalHeight) / 2) + destRect.top;
+
+ _clock.stop();
+ videoDecoder.start();
+
+ // Only continue while the video is still playing
+ while (!shouldQuit() && !videoDecoder.endOfVideo() && videoDecoder.isPlaying()) {
+ // Check for engine quit and video stop key presses
+ while (!videoDecoder.endOfVideo() && videoDecoder.isPlaying() && _eventMan->pollEvent(_event)) {
+ switch (_event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (_event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ if (_event.kbd.hasFlags(Common::KBD_CTRL))
+ quitGame();
+ break;
+ case Common::KEYCODE_SPACE:
+ if (skippable) {
+ videoDecoder.stop();
+ }
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (videoDecoder.needsUpdate()) {
+ const Graphics::Surface *frame = videoDecoder.decodeNextFrame();
+
+ if (frame) {
+ if (scale != 1) {
+ scaleBuffer((const byte *)frame->getPixels(), scaledVideoFrameBuffer, origWidth, origHeight, bytesPerPixel, scale);
+ _system->copyRectToScreen(scaledVideoFrameBuffer, pitch * 2, x, y, finalWidth, finalHeight);
+ } else {
+ _system->copyRectToScreen((const byte *)frame->getPixels(), pitch, x, y, finalWidth, finalHeight);
+ }
+ }
+ }
+
+ // Always update the screen so the mouse continues to render
+ _system->updateScreen();
+
+ _system->delayMillis(videoDecoder.getTimeToNextFrame());
+ }
+
+ _clock.start();
+
+ if (scale != 1) {
+ delete[] scaledVideoFrameBuffer;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
new file mode 100644
index 0000000000..d3db3421af
--- /dev/null
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/video/zork_avi_decoder.h"
+
+#include "zvision/sound/zork_raw.h"
+
+#include "common/stream.h"
+
+#include "audio/audiostream.h"
+
+
+namespace ZVision {
+
+Video::AVIDecoder::AVIAudioTrack *ZorkAVIDecoder::createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo) {
+ ZorkAVIDecoder::ZorkAVIAudioTrack *audioTrack = new ZorkAVIDecoder::ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
+ return (Video::AVIDecoder::AVIAudioTrack *)audioTrack;
+}
+
+void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
+ if (_audStream) {
+ if (_wvInfo.tag == kWaveFormatZorkPCM) {
+ assert(_wvInfo.size == 8);
+ _audStream->queueAudioStream(makeRawZorkStream(stream, _wvInfo.samplesPerSec, _audStream->isStereo(), DisposeAfterUse::YES), DisposeAfterUse::YES);
+ }
+ } else {
+ delete stream;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/video/zork_avi_decoder.h b/engines/zvision/video/zork_avi_decoder.h
new file mode 100644
index 0000000000..ec2be1bb13
--- /dev/null
+++ b/engines/zvision/video/zork_avi_decoder.h
@@ -0,0 +1,60 @@
+/* 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 ZORK_AVI_DECODER_H
+#define ZORK_AVI_DECODER_H
+
+#include "video/avi_decoder.h"
+
+
+namespace ZVision {
+
+class ZorkAVIDecoder : public Video::AVIDecoder {
+public:
+ ZorkAVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType) :
+ Video::AVIDecoder(soundType) {}
+
+ virtual ~ZorkAVIDecoder() {}
+
+private:
+ class ZorkAVIAudioTrack : public Video::AVIDecoder::AVIAudioTrack {
+ public:
+ ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
+ Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType) {}
+ virtual ~ZorkAVIAudioTrack() {}
+
+ void queueSound(Common::SeekableReadStream *stream);
+ };
+
+ Video::AVIDecoder::AVIAudioTrack *createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo);
+
+private:
+ // Audio Codecs
+ enum {
+ kWaveFormatZorkPCM = 17 // special Zork PCM audio format (clashes with MS IMA ADPCM)
+ };
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
new file mode 100644
index 0000000000..f57e225ac1
--- /dev/null
+++ b/engines/zvision/zvision.cpp
@@ -0,0 +1,184 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/zvision.h"
+
+#include "zvision/core/console.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/core/save_manager.h"
+#include "zvision/strings/string_manager.h"
+#include "zvision/archives/zfs_archive.h"
+#include "zvision/detection.h"
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/textconsole.h"
+#include "common/error.h"
+#include "common/system.h"
+#include "common/file.h"
+
+#include "engines/util.h"
+
+#include "audio/mixer.h"
+
+
+namespace ZVision {
+
+ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc)
+ : Engine(syst),
+ _gameDescription(gameDesc),
+ _workingWindow(gameDesc->gameId == GID_NEMESIS ? Common::Rect((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2) + ZNEM_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2) + ZNEM_WORKING_WINDOW_HEIGHT) :
+ Common::Rect((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2) + ZGI_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2) + ZGI_WORKING_WINDOW_HEIGHT)),
+ _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/
+ _desiredFrameTime(33), /* ~30 fps */
+ _clock(_system),
+ _scriptManager(nullptr),
+ _renderManager(nullptr),
+ _saveManager(nullptr),
+ _stringManager(nullptr),
+ _cursorManager(nullptr) {
+
+ debug(1, "ZVision::ZVision");
+}
+
+ZVision::~ZVision() {
+ debug(1, "ZVision::~ZVision");
+
+ // Dispose of resources
+ delete _console;
+ delete _cursorManager;
+ delete _stringManager;
+ delete _saveManager;
+ delete _renderManager;
+ delete _scriptManager;
+ delete _rnd;
+
+ // Remove all of our debug levels
+ DebugMan.clearAllDebugChannels();
+}
+
+void ZVision::initialize() {
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ // TODO: There are 10 file clashes when we flatten the directories.
+ // From a quick look, the files are exactly the same, so it shouldn't matter.
+ // But I'm noting it here just in-case it does become a problem.
+ SearchMan.addSubDirectoryMatching(gameDataDir, "data1", 0, 4, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "data2", 0, 4, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "data3", 0, 4, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "zassets1", 0, 2, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "zassets2", 0, 2, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "znemmx", 0, 1, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "zgi", 0, 4, true);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "fonts", 0, 1, true);
+
+ // Find zfs archive files
+ Common::ArchiveMemberList list;
+ SearchMan.listMatchingMembers(list, "*.zfs");
+
+ // Register the file entries within the zfs archives with the SearchMan
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ Common::String name = (*iter)->getName();
+ Common::SeekableReadStream *stream = (*iter)->createReadStream();
+ ZfsArchive *archive = new ZfsArchive(name, stream);
+
+ delete stream;
+
+ SearchMan.add(name, archive);
+ }
+
+ initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_pixelFormat);
+
+ // Register random source
+ _rnd = new Common::RandomSource("zvision");
+
+ // Create managers
+ _scriptManager = new ScriptManager(this);
+ _renderManager = new RenderManager(_system, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat);
+ _saveManager = new SaveManager(this);
+ _stringManager = new StringManager(this);
+ _cursorManager = new CursorManager(this, &_pixelFormat);
+
+ // Initialize the managers
+ _cursorManager->initialize();
+ _scriptManager->initialize();
+ _stringManager->initialize(_gameDescription->gameId);
+
+ // Create debugger console. It requires GFX to be initialized
+ _console = new Console(this);
+}
+
+Common::Error ZVision::run() {
+ initialize();
+
+ // Main loop
+ while (!shouldQuit()) {
+ _clock.update();
+ uint32 currentTime = _clock.getLastMeasuredTime();
+ uint32 deltaTime = _clock.getDeltaTime();
+
+ processEvents();
+
+ // Call _renderManager->update() first so the background renders
+ // before anything that puzzles/controls will render
+ _renderManager->update(deltaTime);
+ _scriptManager->update(deltaTime);
+
+ // Render the backBuffer to the screen
+ _renderManager->renderBackbufferToScreen();
+
+ // Update the screen
+ _system->updateScreen();
+
+ // Calculate the frame delay based off a desired frame time
+ int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime);
+ // Ensure non-negative
+ delay = delay < 0 ? 0 : delay;
+ _system->delayMillis(delay);
+ }
+
+ return Common::kNoError;
+}
+
+void ZVision::pauseEngineIntern(bool pause) {
+ _mixer->pauseAll(pause);
+
+ if (pause) {
+ _clock.stop();
+ } else {
+ _clock.start();
+ }
+}
+
+Common::String ZVision::generateSaveFileName(uint slot) {
+ return Common::String::format("%s.%02u", _targetName.c_str(), slot);
+}
+
+Common::String ZVision::generateAutoSaveFileName() {
+ return Common::String::format("%s.auto", _targetName.c_str());
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h
new file mode 100644
index 0000000000..1c525c1fc1
--- /dev/null
+++ b/engines/zvision/zvision.h
@@ -0,0 +1,151 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef ZVISION_ZVISION_H
+#define ZVISION_ZVISION_H
+
+#include "zvision/detection.h"
+#include "zvision/utility/clock.h"
+
+#include "common/random.h"
+#include "common/events.h"
+
+#include "engines/engine.h"
+
+#include "graphics/pixelformat.h"
+
+#include "gui/debugger.h"
+
+
+namespace Video {
+class VideoDecoder;
+}
+
+namespace ZVision {
+
+struct ZVisionGameDescription;
+class Console;
+class ScriptManager;
+class RenderManager;
+class CursorManager;
+class StringManager;
+class SaveManager;
+class RlfAnimation;
+
+class ZVision : public Engine {
+public:
+ ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc);
+ ~ZVision();
+
+public:
+ /**
+ * A Rectangle centered inside the actual window. All in-game coordinates
+ * are given in this coordinate space. Also, all images are clipped to the
+ * edges of this Rectangle
+ */
+ const Common::Rect _workingWindow;
+ const Graphics::PixelFormat _pixelFormat;
+
+private:
+ enum {
+ WINDOW_WIDTH = 640,
+ WINDOW_HEIGHT = 480,
+
+ //Zork nemesis working window sizes
+ ZNEM_WORKING_WINDOW_WIDTH = 512,
+ ZNEM_WORKING_WINDOW_HEIGHT = 320,
+
+ //ZGI(and default) working window sizes
+ ZGI_WORKING_WINDOW_WIDTH = 640,
+ ZGI_WORKING_WINDOW_HEIGHT = 344,
+
+ ROTATION_SCREEN_EDGE_OFFSET = 60,
+ MAX_ROTATION_SPEED = 400 // Pixels per second
+ };
+
+ Console *_console;
+ const ZVisionGameDescription *_gameDescription;
+
+ const int _desiredFrameTime;
+
+ // We need random numbers
+ Common::RandomSource *_rnd;
+
+ // Managers
+ ScriptManager *_scriptManager;
+ RenderManager *_renderManager;
+ CursorManager *_cursorManager;
+ SaveManager *_saveManager;
+ StringManager *_stringManager;
+
+ // Clock
+ Clock _clock;
+
+ // To prevent allocation every time we process events
+ Common::Event _event;
+
+public:
+ uint32 getFeatures() const;
+ Common::Language getLanguage() const;
+ Common::Error run();
+ void pauseEngineIntern(bool pause);
+
+ ScriptManager *getScriptManager() const { return _scriptManager; }
+ RenderManager *getRenderManager() const { return _renderManager; }
+ CursorManager *getCursorManager() const { return _cursorManager; }
+ SaveManager *getSaveManager() const { return _saveManager; }
+ StringManager *getStringManager() const { return _stringManager; }
+ Common::RandomSource *getRandomSource() const { return _rnd; }
+ ZVisionGameId getGameId() const { return _gameDescription->gameId; }
+
+ /**
+ * Play a video until it is finished. This is a blocking call. It will call
+ * _clock.stop() when the video starts and _clock.start() when the video finishes.
+ * It will also consume all events during video playback.
+ *
+ * @param videoDecoder The video to play
+ * @param destRect Where to put the video. (In working window coords)
+ * @param skippable If true, the video can be skipped at any time using [Spacebar]
+ */
+ void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true);
+
+ Common::String generateSaveFileName(uint slot);
+ Common::String generateAutoSaveFileName();
+
+private:
+ void initialize();
+ void initFonts();
+
+ void parseStrFile(const Common::String fileName);
+
+ /** Called every frame from ZVision::run() to process any events from EventMan */
+ void processEvents();
+
+ void onMouseDown(const Common::Point &pos);
+ void onMouseUp(const Common::Point &pos);
+ void onMouseMove(const Common::Point &pos);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 0467cac946..8e1c5e91e1 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -73,6 +73,8 @@ struct DrawStep {
uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */
uint8 fillMode; /**< active fill mode */
+ uint8 shadowFillMode; /**< fill mode of the shadow used */
+
uint32 extraData; /**< Generic parameter for extra options (orientation/bevel) */
uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
@@ -103,7 +105,7 @@ VectorRenderer *createRenderer(int mode);
*/
class VectorRenderer {
public:
- VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0),
+ VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
_disableShadows(false), _strokeWidth(1), _gradientFactor(1) {
}
@@ -126,6 +128,11 @@ public:
kTriangleRight
};
+ enum ShadowFillMode {
+ kShadowLinear = 0,
+ kShadowExponential = 1
+ };
+
/**
* Draws a line by considering the special cases for optimization.
*
@@ -278,7 +285,7 @@ public:
* Clears the active surface.
*/
virtual void clearSurface() {
- byte *src = (byte *)_activeSurface->pixels;
+ byte *src = (byte *)_activeSurface->getPixels();
memset(src, 0, _activeSurface->pitch * _activeSurface->h);
}
@@ -292,6 +299,10 @@ public:
_fillMode = mode;
}
+ virtual void setShadowFillMode(ShadowFillMode mode) {
+ _shadowFillMode = mode;
+ }
+
/**
* Sets the stroke width. All shapes drawn with a stroke will
* have that width. Pass 0 to disable shape stroking.
@@ -466,7 +477,7 @@ public:
*/
virtual void drawString(const Graphics::Font *font, const Common::String &text,
const Common::Rect &area, Graphics::TextAlign alignH,
- GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool useEllipsis) = 0;
+ GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool useEllipsis, const Common::Rect &textDrawableArea) = 0;
/**
* Allows to temporarily enable/disable all shadows drawing.
@@ -485,6 +496,7 @@ protected:
Surface *_activeSurface; /**< Pointer to the surface currently being drawn */
FillMode _fillMode; /**< Defines in which way (if any) are filled the drawn shapes */
+ ShadowFillMode _shadowFillMode;
int _shadowOffset; /**< offset for drawn shadows */
int _bevel; /**< amount of fake bevel */
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 6a3ee306a5..491a9d7f42 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -119,6 +119,38 @@ inline frac_t fp_sqroot(uint32 x) {
*(ptr4 + (y) + (px)) = color2; \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (y) - (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (x) - (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (x) - (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (y) - (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (y) + (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (x) + (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (x) + (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (y) + (px), color, a); \
+} while (0)
+
#define BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py) do { \
*(ptr1 + (y) - (px)) = color1; \
*(ptr1 + (x) - (py)) = color2; \
@@ -222,6 +254,37 @@ inline frac_t fp_sqroot(uint32 x) {
this->blendPixelPtr(ptr4 + (y) + (px), color2, a); \
} while (0)
+#define WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (y) - (px), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (x) - (py), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (x) - (py), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (y) - (px), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (y) + (px), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr - (x) + (py), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (x) + (py), color, a); \
+} while (0)
+
+#define WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \
+ this->blendPixelPtr(ptr + (y) + (px), color, a); \
+} while (0)
// optimized Wu's algorithm
#define WU_ALGORITHM() do { \
@@ -277,16 +340,24 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) {
VectorRenderer *createRenderer(int mode) {
#ifdef DISABLE_FANCY_THEMES
- assert(mode == GUI::ThemeEngine::kGfxStandard16bit);
+ assert(mode == GUI::ThemeEngine::kGfxStandard);
#endif
PixelFormat format = g_system->getOverlayFormat();
switch (mode) {
- case GUI::ThemeEngine::kGfxStandard16bit:
- return new VectorRendererSpec<OverlayColor>(format);
+ case GUI::ThemeEngine::kGfxStandard:
+ if (g_system->getOverlayFormat().bytesPerPixel == 4)
+ return new VectorRendererSpec<uint32>(format);
+ else if (g_system->getOverlayFormat().bytesPerPixel == 2)
+ return new VectorRendererSpec<uint16>(format);
+ break;
#ifndef DISABLE_FANCY_THEMES
- case GUI::ThemeEngine::kGfxAntialias16bit:
- return new VectorRendererAA<OverlayColor>(format);
+ case GUI::ThemeEngine::kGfxAntialias:
+ if (g_system->getOverlayFormat().bytesPerPixel == 4)
+ return new VectorRendererAA<uint32>(format);
+ else if (g_system->getOverlayFormat().bytesPerPixel == 2)
+ return new VectorRendererAA<uint16>(format);
+ break;
#endif
default:
break;
@@ -317,9 +388,15 @@ setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) {
_gradientEnd = _format.RGBToColor(r2, g2, b2);
_gradientStart = _format.RGBToColor(r1, g1, b1);
- _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask);
- _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask);
- _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask);
+ if (sizeof(PixelType) == 4) {
+ _gradientBytes[0] = ((_gradientEnd & _redMask) >> _format.rShift) - ((_gradientStart & _redMask) >> _format.rShift);
+ _gradientBytes[1] = ((_gradientEnd & _greenMask) >> _format.gShift) - ((_gradientStart & _greenMask) >> _format.gShift);
+ _gradientBytes[2] = ((_gradientEnd & _blueMask) >> _format.bShift) - ((_gradientStart & _blueMask) >> _format.bShift);
+ } else {
+ _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask);
+ _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask);
+ _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask);
+ }
}
template<typename PixelType>
@@ -328,9 +405,15 @@ calcGradient(uint32 pos, uint32 max) {
PixelType output = 0;
pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max;
- output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask;
- output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask;
- output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask;
+ if (sizeof(PixelType) == 4) {
+ output |= ((_gradientStart & _redMask) + (((_gradientBytes[0] * pos) >> 12) << _format.rShift)) & _redMask;
+ output |= ((_gradientStart & _greenMask) + (((_gradientBytes[1] * pos) >> 12) << _format.gShift)) & _greenMask;
+ output |= ((_gradientStart & _blueMask) + (((_gradientBytes[2] * pos) >> 12) << _format.bShift)) & _blueMask;
+ } else {
+ output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask;
+ output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask;
+ output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask;
+ }
output |= _alphaMask;
return output;
@@ -397,7 +480,7 @@ gradientFill(PixelType *ptr, int width, int x, int y) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
fillSurface() {
- byte *ptr = (byte *)_activeSurface->getBasePtr(0, 0);
+ byte *ptr = (byte *)_activeSurface->getPixels();
int h = _activeSurface->h;
int pitch = _activeSurface->pitch;
@@ -453,7 +536,7 @@ template<typename PixelType>
void VectorRendererSpec<PixelType>::
blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) {
byte *dst_ptr = (byte *)_activeSurface->getBasePtr(r.left, r.top);
- const byte *src_ptr = (const byte *)source->getBasePtr(0, 0);
+ const byte *src_ptr = (const byte *)source->getPixels();
const int dst_pitch = _activeSurface->pitch;
const int src_pitch = source->pitch;
@@ -481,7 +564,7 @@ blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) {
y = y + (r.height() >> 1) - (source->h >> 1);
PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
- const PixelType *src_ptr = (const PixelType *)source->getBasePtr(0, 0);
+ const PixelType *src_ptr = (const PixelType *)source->getPixels();
int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int src_pitch = source->pitch / source->format.bytesPerPixel;
@@ -508,7 +591,7 @@ template<typename PixelType>
void VectorRendererSpec<PixelType>::
applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
int pixels = _activeSurface->w * _activeSurface->h;
- PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0);
+ PixelType *ptr = (PixelType *)_activeSurface->getPixels();
uint8 r, g, b;
uint lum;
@@ -537,20 +620,41 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
template<typename PixelType>
inline void VectorRendererSpec<PixelType>::
blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
- int idst = *ptr;
- int isrc = color;
-
- *ptr = (PixelType)(
- (_redMask & ((idst & _redMask) +
- ((int)(((int)(isrc & _redMask) -
- (int)(idst & _redMask)) * alpha) >> 8))) |
- (_greenMask & ((idst & _greenMask) +
- ((int)(((int)(isrc & _greenMask) -
- (int)(idst & _greenMask)) * alpha) >> 8))) |
- (_blueMask & ((idst & _blueMask) +
- ((int)(((int)(isrc & _blueMask) -
- (int)(idst & _blueMask)) * alpha) >> 8))) |
- (idst & _alphaMask));
+ if (sizeof(PixelType) == 4) {
+ const byte sR = (color & _redMask) >> _format.rShift;
+ const byte sG = (color & _greenMask) >> _format.gShift;
+ const byte sB = (color & _blueMask) >> _format.bShift;
+
+ byte dR = (*ptr & _redMask) >> _format.rShift;
+ byte dG = (*ptr & _greenMask) >> _format.gShift;
+ byte dB = (*ptr & _blueMask) >> _format.bShift;
+
+ dR += ((sR - dR) * alpha) >> 8;
+ dG += ((sG - dG) * alpha) >> 8;
+ dB += ((sB - dB) * alpha) >> 8;
+
+ *ptr = ((dR << _format.rShift) & _redMask)
+ | ((dG << _format.gShift) & _greenMask)
+ | ((dB << _format.bShift) & _blueMask)
+ | (*ptr & _alphaMask);
+ } else if (sizeof(PixelType) == 2) {
+ int idst = *ptr;
+ int isrc = color;
+
+ *ptr = (PixelType)(
+ (_redMask & ((idst & _redMask) +
+ ((int)(((int)(isrc & _redMask) -
+ (int)(idst & _redMask)) * alpha) >> 8))) |
+ (_greenMask & ((idst & _greenMask) +
+ ((int)(((int)(isrc & _greenMask) -
+ (int)(idst & _greenMask)) * alpha) >> 8))) |
+ (_blueMask & ((idst & _blueMask) +
+ ((int)(((int)(isrc & _blueMask) -
+ (int)(idst & _blueMask)) * alpha) >> 8))) |
+ (idst & _alphaMask));
+ } else {
+ error("Unsupported BPP format: %u", (uint)sizeof(PixelType));
+ }
}
template<typename PixelType>
@@ -607,24 +711,45 @@ darkenFill(PixelType *ptr, PixelType *end) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area,
- Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis) {
+ Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis, const Common::Rect &textDrawableArea) {
int offset = area.top;
if (font->getFontHeight() < area.height()) {
switch (alignV) {
- case GUI::ThemeEngine::kTextAlignVCenter:
- offset = area.top + ((area.height() - font->getFontHeight()) >> 1);
- break;
- case GUI::ThemeEngine::kTextAlignVBottom:
- offset = area.bottom - font->getFontHeight();
- break;
- default:
- break;
+ case GUI::ThemeEngine::kTextAlignVCenter:
+ offset = area.top + ((area.height() - font->getFontHeight()) >> 1);
+ break;
+ case GUI::ThemeEngine::kTextAlignVBottom:
+ offset = area.bottom - font->getFontHeight();
+ break;
+ default:
+ break;
}
}
- font->drawString(_activeSurface, text, area.left, offset, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
+ Common::Rect drawArea;
+ if (textDrawableArea.isEmpty()) {
+ // In case no special area to draw to is given we only draw in the
+ // area specified by the user.
+ drawArea = area;
+ // warning("there is no text drawable area. Please set this area for clipping");
+ } else {
+ // The area we can draw to is the intersection between the allowed
+ // drawing area (textDrawableArea) and the area where we try to draw
+ // the text (area).
+ drawArea = textDrawableArea.findIntersectingRect(area);
+ }
+
+ // Better safe than sorry. We intersect with the actual surface boundaries
+ // to avoid any ugly clipping in _activeSurface->getSubArea which messes
+ // up the calculation of the x and y coordinates where to draw the string.
+ drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h));
+
+ if (!drawArea.isEmpty()) {
+ Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
+ font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
+ }
}
/** LINES **/
@@ -778,7 +903,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
- && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h) {
+ && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
+ && h > (Base::_shadowOffset + 1) * 2) {
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
}
@@ -809,13 +935,14 @@ drawTab(int x, int y, int r, int w, int h) {
// FIXME: This is broken for the AA renderer.
// See the rounded rect alg for how to fix it. (The border should
// be drawn before the interior, both inside drawTabAlg.)
- drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode);
+ drawTabShadow(x, y, w - 2, h, r);
+ drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
if (Base::_strokeWidth)
drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
break;
case kFillForeground:
- drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode);
+ drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
break;
}
}
@@ -996,6 +1123,67 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTabShadow(int x1, int y1, int w, int h, int r) {
+ int offset = 3;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+ // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+ uint8 expFactor = 3;
+ uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
+
+ int xstart = x1;
+ int ystart = y1;
+ int width = w;
+ int height = h + offset + 1;
+
+ for (int i = offset; i >= 0; i--) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+ int short_h = height - (2 * r) + 2;
+ PixelType color = _format.RGBToColor(0, 0, 0);
+
+ BE_RESET();
+
+ // HACK: As we are drawing circles exploting 8-axis symmetry,
+ // there are 4 pixels on each circle which are drawn twice.
+ // this is ok on filled circles, but when blending on surfaces,
+ // we cannot let it blend twice. awful.
+ uint32 hb = 0;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
+
+ if (((1 << x) & hb) == 0) {
+ blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
+ hb |= (1 << x);
+ }
+
+ if (((1 << y) & hb) == 0) {
+ blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
+ hb |= (1 << y);
+ }
+ }
+
+ ptr_fill += pitch * r;
+ while (short_h--) {
+ blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+ ptr_fill += pitch;
+ }
+
+ // Move shadow one pixel upward each iteration
+ xstart += 1;
+ // Multiply with expfactor
+ alpha = (alpha * (expFactor << 8)) >> 9;
+ }
+}
+
/** BEVELED TABS FOR CLASSIC THEME **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1429,118 +1617,160 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto
/** ROUNDED SQUARE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int sw = 0, sp = 0, hp = h * pitch;
- // TODO: Split this up into border, bevel and interior functions
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
- if (fill_m != kFillDisabled) {
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
-
- int real_radius = r;
- int short_h = h - (2 * r) + 2;
- int long_h = h;
+ int real_radius = r;
+ int short_h = h - (2 * r) + 2;
- BE_RESET();
+ PixelType color1 = color;
+ PixelType color2 = color;
- PixelType color1 = color;
- if (fill_m == kFillBackground)
- color1 = _bgColor;
+ while (sw++ < Base::_strokeWidth) {
+ blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top
+ blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom
+ sp += pitch;
- if (fill_m == kFillGradient) {
- PixelType color2, color3, color4;
- precalcGradient(long_h);
+ BE_RESET();
+ r--;
+
+ int alphaStep_tr = ((alpha_t - alpha_r)/(y+1));
+ int alphaStep_br = ((alpha_r - alpha_b)/(y+1));
+ int alphaStep_bl = ((alpha_b - alpha_l)/(y+1));
+ int alphaStep_tl = ((alpha_l - alpha_t)/(y+1));
+
+ // Avoid blending the last pixels twice, since we have an alpha
+ while (x++ < (y - 2)) {
+ BE_ALGORITHM();
- while (x++ < y) {
- BE_ALGORITHM();
+ BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
+ BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
+ BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
+ BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)));
+
+ BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)));
+ BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)));
+ BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)));
+ BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)));
+
+ if (Base::_strokeWidth > 1) {
+ BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
+ BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
+ }
+ }
+ }
- color1 = calcGradient(real_radius - x, long_h);
- color2 = calcGradient(real_radius - y, long_h);
- color3 = calcGradient(long_h - r + x, long_h);
- color4 = calcGradient(long_h - r + y, long_h);
+ ptr_fill += pitch * real_radius;
+ while (short_h--) {
+ blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l); // left
+ blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r); // right
+ ptr_fill += pitch;
+ }
+}
- gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
- gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
- gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y);
- gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x);
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
- BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
- }
- } else {
- while (x++ < y) {
- BE_ALGORITHM();
+ int real_radius = r;
+ int short_h = h - (2 * r) + 2;
+ int long_h = h;
- colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1);
- colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1);
+ BE_RESET();
- colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1);
- colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1);
+ PixelType color1 = color;
- // do not remove - messes up the drawing at lower resolutions
- BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
- }
- }
+ if (fill_m == kFillGradient) {
+ PixelType color2, color3, color4;
+ precalcGradient(long_h);
- ptr_fill += pitch * r;
- while (short_h--) {
- if (fill_m == kFillGradient) {
- gradientFill(ptr_fill, w + 1, x1, real_radius++);
- } else {
- colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color1);
- }
- ptr_fill += pitch;
- }
- }
+ while (x++ < y) {
+ BE_ALGORITHM();
+ color1 = calcGradient(real_radius - x, long_h);
+ color2 = calcGradient(real_radius - y, long_h);
+ color3 = calcGradient(long_h - r + x, long_h);
+ color4 = calcGradient(long_h - r + y, long_h);
- if (Base::_strokeWidth) {
- int sw = 0, sp = 0, hp = h * pitch;
+ gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
+ gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+ gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y);
+ gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x);
- int real_radius = r;
- int short_h = h - (2 * r) + 2;
+ BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+ }
+ } else {
+ while (x++ < y) {
+ BE_ALGORITHM();
- // TODO: A gradient effect on the bevel
- PixelType color1, color2;
- color1 = Base::_bevel ? _bevelColor : color;
- color2 = color;
+ colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1);
+ colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1);
- while (sw++ < Base::_strokeWidth) {
- colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1);
- colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2);
- sp += pitch;
+ colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1);
+ colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1);
- BE_RESET();
- r--;
-
- while (x++ < y) {
- BE_ALGORITHM();
- BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+ // do not remove - messes up the drawing at lower resolutions
+ BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+ }
+ }
- if (Base::_strokeWidth > 1) {
- BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
- BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
- }
- }
+ ptr_fill += pitch * r;
+ while (short_h--) {
+ if (fill_m == kFillGradient) {
+ gradientFill(ptr_fill, w + 1, x1, real_radius++);
+ } else {
+ colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color1);
}
+ ptr_fill += pitch;
+ }
+}
- ptr_fill += pitch * real_radius;
- while (short_h--) {
- colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1);
- colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2);
- ptr_fill += pitch;
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ const uint8 borderAlpha_t = 0;
+ const uint8 borderAlpha_r = 127;
+ const uint8 borderAlpha_b = 255;
+ const uint8 borderAlpha_l = 63;
+
+ const uint8 bevelAlpha_t = 255;
+ const uint8 bevelAlpha_r = 31;
+ const uint8 bevelAlpha_b = 0;
+ const uint8 bevelAlpha_l = 127;
+
+ // If only border is visible
+ if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
+ if (fill_m == Base::kFillBackground)
+ drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m);
+ else
+ drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
+ }
+
+ if (Base::_strokeWidth) {
+ if (r != 0 && _bevel > 0) {
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
+ } else {
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
}
}
}
@@ -1599,85 +1829,112 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
********************************************************************/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawSquareShadow(int x, int y, int w, int h, int blur) {
- PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
+drawSquareShadow(int x, int y, int w, int h, int offset) {
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;
- i = h - blur;
+ i = h - offset;
while (i--) {
- j = blur;
+ j = offset;
while (j--)
- blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur);
+ blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset);
ptr += pitch;
}
- ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1);
+ ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
- while (i++ < blur) {
- j = w - blur;
+ while (i++ < offset) {
+ j = w - offset;
while (j--)
- blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur);
+ blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset);
ptr += pitch;
}
ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
i = 0;
- while (i++ < blur) {
- j = blur - 1;
+ while (i++ < offset) {
+ j = offset - 1;
while (j--)
- blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur));
+ blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset));
ptr += pitch;
}
}
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) {
- int f, ddF_x, ddF_y;
- int x, y, px, py;
+drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
- int alpha = 102;
- x1 += blur;
- y1 += blur;
+ // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+ uint8 expFactor = 3;
+ uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
+
+ // These constants ensure a border of 2px on the left and of each rounded square
+ int xstart = (x1 > 2) ? x1 - 2 : x1;
+ int ystart = y1;
+ int width = w + offset + 2;
+ int height = h + offset + 1;
+
+ for (int i = offset; i >= 0; i--) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+ int short_h = height - (2 * r) + 2;
+ PixelType color = _format.RGBToColor(0, 0, 0);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r);
-
- int short_h = h - (2 * r) + 1;
+ BE_RESET();
- BE_RESET();
+ // HACK: As we are drawing circles exploting 8-axis symmetry,
+ // there are 4 pixels on each circle which are drawn twice.
+ // this is ok on filled circles, but when blending on surfaces,
+ // we cannot let it blend twice. awful.
+ uint32 hb = 0;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
- // HACK: As we are drawing circles exploting 8-axis symmetry,
- // there are 4 pixels on each circle which are drawn twice.
- // this is ok on filled circles, but when blending on surfaces,
- // we cannot let it blend twice. awful.
- uint32 hb = 0;
- while (x++ < y) {
- BE_ALGORITHM();
+ if (((1 << x) & hb) == 0) {
+ blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
+
+ // Will create a dark line of pixles if left out
+ if (hb > 0) {
+ blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
+ }
+ hb |= (1 << x);
+ }
- if (((1 << x) & hb) == 0) {
- blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha);
- blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha);
- hb |= (1 << x);
+ if (((1 << y) & hb) == 0) {
+ blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
+ blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
+ hb |= (1 << y);
+ }
}
-
- if (((1 << y) & hb) == 0) {
- blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha);
- blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha);
- hb |= (1 << y);
+
+ ptr_fill += pitch * r;
+ while (short_h--) {
+ blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+ ptr_fill += pitch;
}
- }
- while (short_h--) {
- blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha);
- ptr_fill += pitch;
+ // Make shadow smaller each iteration, and move it one pixel inward
+ xstart += 1;
+ ystart += 1;
+ width -= 2;
+ height -= 2;
+
+ if (_shadowFillMode == kShadowExponential)
+ // Multiply with expfactor
+ alpha = (alpha * (expFactor << 8)) >> 9;
}
}
@@ -1870,7 +2127,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
/** ROUNDED SQUARES **/
template<typename PixelType>
void VectorRendererAA<PixelType>::
-drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
int x, y;
const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int px, py;
@@ -1879,65 +2136,89 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
frac_t T = 0, oldT;
uint8 a1, a2;
- // TODO: Split this up into border, bevel and interior functions
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
- if (Base::_strokeWidth) {
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
-
- int sw = 0, sp = 0;
- int short_h = h - 2 * r;
- int hp = h * pitch;
-
- int strokeWidth = Base::_strokeWidth;
- // If we're going to fill the inside, draw a slightly thicker border
- // so we can blend the inside on top of it.
- if (fill_m != Base::kFillDisabled) strokeWidth++;
-
- // TODO: A gradient effect on the bevel
- PixelType color1, color2;
- color1 = Base::_bevel ? Base::_bevelColor : color;
- color2 = color;
+ int sw = 0, sp = 0;
+ int short_h = h - 2 * r;
+ int hp = h * pitch;
+ int strokeWidth = Base::_strokeWidth;
- while (sw++ < strokeWidth) {
- colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1);
- colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2);
- sp += pitch;
+ while (sw++ < strokeWidth) {
+ this->blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, alpha_b); // bottom
+ this->blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, alpha_t); // top
- x = r - (sw - 1);
- y = 0;
- T = 0;
- px = pitch * x;
- py = 0;
+ sp += pitch;
- while (x > y++) {
- WU_ALGORITHM();
+ x = r - (sw - 1);
+ y = 0;
+ T = 0;
+ px = pitch * x;
+ py = 0;
- // sw == 1: outside, sw = _strokeWidth: inside
- // We always draw the outer edge AAed, but the inner edge
- // only when the inside isn't filled
- if (sw != strokeWidth || fill_m != Base::kFillDisabled)
- a2 = 255;
+ int alphaStep_tr = ((alpha_t - alpha_r)/(x+1));
+ int alphaStep_br = ((alpha_r - alpha_b)/(x+1));
+ int alphaStep_bl = ((alpha_b - alpha_l)/(x+1));
+ int alphaStep_tl = ((alpha_l - alpha_t)/(x+1));
- // inner arc
- WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - pitch), py, a2);
+ while (x > y++) {
+ WU_ALGORITHM();
- if (sw == 1) // outer arc
- WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
+ // sw == 1: outside, sw = _strokeWidth: inside
+ // We always draw the outer edge AAed, but the inner edge
+ // only when the inside isn't filled
+ if (sw != strokeWidth || fill_m != Base::kFillDisabled)
+ a2 = 255;
+
+ // inner arc
+ WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a2) >> 16));
+
+ WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a2) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a2) >> 16));
+
+ // outer arc
+ if (sw == 1) {
+ WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a1) >> 16));
+
+ WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a1) >> 16));
+ WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a1) >> 16));
+ }
}
- }
ptr_fill += pitch * r;
- while (short_h-- >= 0) {
- colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1);
- colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2);
+
+ while (short_h-- >= -2) {
+ this->blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color, alpha_l); // left
+ this->blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, alpha_r); // right
ptr_fill += pitch;
}
}
+}
+
+template<typename PixelType>
+void VectorRendererAA<PixelType>::
+drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ int x, y;
+ const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
+ int px, py;
+
+ uint32 rsq = r*r;
+ frac_t T = 0, oldT;
+ uint8 a1, a2;
r -= Base::_strokeWidth;
x1 += Base::_strokeWidth;
@@ -1946,93 +2227,116 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
h -= 2*Base::_strokeWidth;
rsq = r*r;
- if (w <= 0 || h <= 0)
- return; // Only border is visible
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
- if (fill_m != Base::kFillDisabled) {
- if (fill_m == Base::kFillBackground)
- color = Base::_bgColor;
+ int short_h = h - 2 * r;
+ x = r;
+ y = 0;
+ T = 0;
+ px = pitch * x;
+ py = 0;
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+ if (fill_m == Base::kFillGradient) {
- int short_h = h - 2 * r;
- x = r;
- y = 0;
- T = 0;
- px = pitch * x;
- py = 0;
+ Base::precalcGradient(h);
- if (fill_m == Base::kFillGradient) {
+ PixelType color1, color2, color3, color4;
+ while (x > y++) {
+ WU_ALGORITHM();
- Base::precalcGradient(h);
+ color1 = Base::calcGradient(r - x, h);
+ color2 = Base::calcGradient(r - y, h);
+ color3 = Base::calcGradient(h - r + x, h);
+ color4 = Base::calcGradient(h - r + y, h);
- PixelType color1, color2, color3, color4;
- while (x > y++) {
- WU_ALGORITHM();
+ Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y);
- color1 = Base::calcGradient(r - x, h);
- color2 = Base::calcGradient(r - y, h);
- color3 = Base::calcGradient(h - r + x, h);
- color4 = Base::calcGradient(h - r + y, h);
+ // Only fill each horizontal line once (or we destroy
+ // the gradient effect at the edges)
+ if (T < oldT || y == 1)
+ Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x);
- Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y);
+ Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y);
- // Only fill each horizontal line once (or we destroy
- // the gradient effect at the edges)
- if (T < oldT || y == 1)
- Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x);
+ // Only fill each horizontal line once (or we destroy
+ // the gradient effect at the edges)
+ if (T < oldT || y == 1)
+ Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x);
- Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y);
+ // This shape is used for dialog backgrounds.
+ // If we're drawing on top of an empty overlay background,
+ // and the overlay supports alpha, we have to do AA by
+ // setting the dest alpha channel, instead of blending with
+ // dest color channels.
+ if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha))
+ WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr);
+ else
+ WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr);
+ }
- // Only fill each horizontal line once (or we destroy
- // the gradient effect at the edges)
- if (T < oldT || y == 1)
- Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x);
-
- // This shape is used for dialog backgrounds.
- // If we're drawing on top of an empty overlay background,
- // and the overlay supports alpha, we have to do AA by
- // setting the dest alpha channel, instead of blending with
- // dest color channels.
- if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha))
- WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr);
- else
- WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr);
- }
+ ptr_fill += pitch * r;
+ while (short_h-- >= 0) {
+ Base::gradientFill(ptr_fill, w + 1, x1, r++);
+ ptr_fill += pitch;
+ }
- ptr_fill += pitch * r;
- while (short_h-- >= 0) {
- Base::gradientFill(ptr_fill, w + 1, x1, r++);
- ptr_fill += pitch;
- }
+ } else {
- } else {
+ while (x > 1 + y++) {
+ WU_ALGORITHM();
- while (x > 1 + y++) {
- WU_ALGORITHM();
+ colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
+ if (T < oldT || y == 1)
+ colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
- colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
- if (T < oldT || y == 1)
- colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
+ colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color);
+ if (T < oldT || y == 1)
+ colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color);
- colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color);
- if (T < oldT || y == 1)
- colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color);
+ WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
+ }
- WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
- }
+ ptr_fill += pitch * r;
+ while (short_h-- >= 0) {
+ colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
+ ptr_fill += pitch;
+ }
+ }
+}
- ptr_fill += pitch * r;
- while (short_h-- >= 0) {
- colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
- ptr_fill += pitch;
- }
+template<typename PixelType>
+void VectorRendererAA<PixelType>::
+drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ const uint8 borderAlpha_t = 0;
+ const uint8 borderAlpha_r = 127;
+ const uint8 borderAlpha_b = 255;
+ const uint8 borderAlpha_l = 63;
+
+ const uint8 bevelAlpha_t = 255;
+ const uint8 bevelAlpha_r = 31;
+ const uint8 bevelAlpha_b = 0;
+ const uint8 bevelAlpha_l = 127;
+
+ if (Base::_strokeWidth) {
+ if (r != 0 && Base::_bevel > 0) {
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, Base::_bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
+ } else {
+ drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
}
}
+
+ // If only border is visible
+ if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
+ if (fill_m == Base::kFillBackground)
+ drawInteriorRoundedSquareAlg(x1, y1, r, w, h, Base::_bgColor, fill_m);
+ else
+ drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
+ }
}
/** CIRCLES **/
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 4ed80cb55f..c035ca0e19 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -61,7 +61,7 @@ public:
}
void drawString(const Graphics::Font *font, const Common::String &text,
const Common::Rect &area, Graphics::TextAlign alignH,
- GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool elipsis);
+ GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool elipsis, const Common::Rect &textDrawableArea = Common::Rect(0, 0, 0, 0));
void setFgColor(uint8 r, uint8 g, uint8 b) { _fgColor = _format.RGBToColor(r, g, b); }
void setBgColor(uint8 r, uint8 g, uint8 b) { _bgColor = _format.RGBToColor(r, g, b); }
@@ -158,6 +158,12 @@ protected:
virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h,
PixelType color, FillMode fill_m);
+ virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h,
+ PixelType color, FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l);
+
+ virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h,
+ PixelType color, FillMode fill_m);
+
virtual void drawSquareAlg(int x, int y, int w, int h,
PixelType color, FillMode fill_m);
@@ -174,6 +180,8 @@ protected:
PixelType color, VectorRenderer::FillMode fill_m,
int baseLeft = 0, int baseRight = 0);
+ virtual void drawTabShadow(int x, int y, int w, int h, int r);
+
virtual void drawBevelTabAlg(int x, int y, int w, int h,
int bevel, PixelType topColor, PixelType bottomColor,
int baseLeft = 0, int baseRight = 0);
@@ -186,10 +194,10 @@ protected:
* There functions may be overloaded in inheriting classes to improve performance
* in the slowest platforms where pixel alpha blending just doesn't cut it.
*
- * @param blur Intensity/size of the shadow.
+ * @param offset Intensity/size of the shadow.
*/
- virtual void drawSquareShadow(int x, int y, int w, int h, int blur);
- virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur);
+ virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
+ virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset);
/**
* Calculates the color gradient on a given point.
@@ -292,10 +300,12 @@ protected:
*/
virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
- virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) {
- Base::drawRoundedSquareShadow(x, y, r, w, h, blur);
-// VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur,
-// Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2));
+ virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_l, uint8 alpha_r, uint8 alpha_b);
+
+ virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
+
+ virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) {
+ Base::drawRoundedSquareShadow(x, y, r, w, h, offset);
}
virtual void drawTabAlg(int x, int y, int w, int h, int r,
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index c818101645..133ee5fd71 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)
@@ -246,6 +253,7 @@ CursorManager::Cursor::Cursor(const void *data, uint w, uint h, int hotspotX, in
_hotspotX = hotspotX;
_hotspotY = hotspotY;
_dontScale = dontScale;
+ _visible = false;
}
CursorManager::Cursor::~Cursor() {
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/decoders/bmp.cpp b/graphics/decoders/bmp.cpp
index bcfd0abbda..2eabbb7631 100644
--- a/graphics/decoders/bmp.cpp
+++ b/graphics/decoders/bmp.cpp
@@ -130,14 +130,14 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0;
if (bitsPerPixel == 8) {
- byte *dst = (byte *)_surface->pixels;
+ byte *dst = (byte *)_surface->getPixels();
for (int32 i = 0; i < height; i++) {
stream.read(dst + (height - i - 1) * width, width);
stream.skip(extraDataLength);
}
} else if (bitsPerPixel == 24) {
- byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch;
+ byte *dst = (byte *)_surface->getBasePtr(0, height - 1);
for (int32 i = 0; i < height; i++) {
for (uint32 j = 0; j < width; j++) {
@@ -154,7 +154,7 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
dst -= _surface->pitch * 2;
}
} else { // 32 bpp
- byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch;
+ byte *dst = (byte *)_surface->getBasePtr(0, height - 1);
for (int32 i = 0; i < height; i++) {
for (uint32 j = 0; j < width; j++) {
diff --git a/graphics/decoders/iff.cpp b/graphics/decoders/iff.cpp
index 50c7b4f7de..fe27258d28 100644
--- a/graphics/decoders/iff.cpp
+++ b/graphics/decoders/iff.cpp
@@ -30,6 +30,10 @@ namespace Graphics {
IFFDecoder::IFFDecoder() {
_surface = 0;
_palette = 0;
+
+ // these 2 properties are not reset by destroy(), so the default is set here.
+ _numRelevantPlanes = 8;
+ _pixelPacking = false;
destroy();
}
@@ -54,8 +58,6 @@ void IFFDecoder::destroy() {
_paletteRanges.clear();
_type = TYPE_UNKNOWN;
_paletteColorCount = 0;
- _numRelevantPlanes = 8;
- _pixelPacking = false;
}
bool IFFDecoder::loadStream(Common::SeekableReadStream &stream) {
@@ -170,7 +172,7 @@ void IFFDecoder::loadBitmap(Common::SeekableReadStream &stream) {
if (_type == TYPE_ILBM) {
uint32 scanlinePitch = ((_header.width + 15) >> 4) << 1;
byte *scanlines = new byte[scanlinePitch * _header.numPlanes];
- byte *data = (byte *)_surface->pixels;
+ byte *data = (byte *)_surface->getPixels();
for (uint16 i = 0; i < _header.height; ++i) {
byte *scanline = scanlines;
@@ -194,7 +196,7 @@ void IFFDecoder::loadBitmap(Common::SeekableReadStream &stream) {
delete[] scanlines;
} else if (_type == TYPE_PBM) {
- byte *data = (byte *)_surface->pixels;
+ byte *data = (byte *)_surface->getPixels();
uint32 outSize = _header.width * _header.height;
if (_header.compression) {
diff --git a/graphics/decoders/iff.h b/graphics/decoders/iff.h
index beac62e519..37cb4b38c1 100644
--- a/graphics/decoders/iff.h
+++ b/graphics/decoders/iff.h
@@ -85,6 +85,8 @@ public:
/**
* The number of planes to decode, also determines the pixel packing if _packPixels is true.
* 8 == decode all planes, map 1 pixel in 1 byte. (default, no packing even if _packPixels is true)
+ *
+ * NOTE: this property must be reset manually, and is not reset by a call to destroy().
*/
void setNumRelevantPlanes(const uint8 numRelevantPlanes) { _numRelevantPlanes = numRelevantPlanes; }
@@ -94,6 +96,8 @@ public:
* 2 == decode first 2 planes, pack 4 pixels in 1 byte. This makes _surface->w 1/4th of _header.width
* 4 == decode first 4 planes, pack 2 pixels in 1 byte. This makes _surface->w half of _header.width
* Packed bitmaps won't have a proper surface format since there is no way to tell it to use 1, 2 or 4 bits per pixel
+ *
+ * NOTE: this property must be reset manually, and is not reset by a call to destroy().
*/
void setPixelPacking(const bool pixelPacking) { _pixelPacking = pixelPacking; }
private:
diff --git a/graphics/decoders/image_decoder.h b/graphics/decoders/image_decoder.h
index 49e31c6e3a..a39a9a1493 100644
--- a/graphics/decoders/image_decoder.h
+++ b/graphics/decoders/image_decoder.h
@@ -44,6 +44,9 @@ public:
/**
* Load an image from the specified stream
+ *
+ * loadStream() should implicitly call destroy() to free the memory
+ * of the last loadStream() call.
*
* @param stream the input stream
* @return whether loading the file succeeded
@@ -54,6 +57,9 @@ public:
/**
* Destroy this decoder's surface and palette
+ *
+ * This should be called by a loadStream() implementation as well
+ * as the destructor.
*/
virtual void destroy() = 0;
diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp
index 75fdcd6e5a..c858884095 100644
--- a/graphics/decoders/jpeg.cpp
+++ b/graphics/decoders/jpeg.cpp
@@ -20,8 +20,11 @@
*
*/
+// libjpeg uses forbidden symbols in its header. Thus, we need to allow them
+// here.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
#include "graphics/pixelformat.h"
-#include "graphics/yuv_to_rgb.h"
#include "graphics/decoders/jpeg.h"
#include "common/debug.h"
@@ -29,35 +32,19 @@
#include "common/stream.h"
#include "common/textconsole.h"
-namespace Graphics {
-
-// Order used to traverse the quantization tables
-static const uint8 _zigZagOrder[64] = {
- 0, 1, 8, 16, 9, 2, 3, 10,
- 17, 24, 32, 25, 18, 11, 4, 5,
- 12, 19, 26, 33, 40, 48, 41, 34,
- 27, 20, 13, 6, 7, 14, 21, 28,
- 35, 42, 49, 56, 57, 50, 43, 36,
- 29, 22, 15, 23, 30, 37, 44, 51,
- 58, 59, 52, 45, 38, 31, 39, 46,
- 53, 60, 61, 54, 47, 55, 62, 63
-};
-
-JPEGDecoder::JPEGDecoder() : ImageDecoder(),
- _stream(NULL), _w(0), _h(0), _numComp(0), _components(NULL), _numScanComp(0),
- _scanComp(NULL), _currentComp(NULL), _rgbSurface(0) {
+#ifdef USE_JPEG
+// The original release of libjpeg v6b did not contain any extern "C" in case
+// its header files are included in a C++ environment. To avoid any linking
+// issues we need to add it on our own.
+extern "C" {
+#include <jpeglib.h>
+#include <jerror.h>
+}
+#endif
- // Initialize the quantization tables
- for (int i = 0; i < JPEG_MAX_QUANT_TABLES; i++)
- _quant[i] = NULL;
+namespace Graphics {
- // Initialize the Huffman tables
- for (int i = 0; i < 2 * JPEG_MAX_HUFF_TABLES; i++) {
- _huff[i].count = 0;
- _huff[i].values = NULL;
- _huff[i].sizes = NULL;
- _huff[i].codes = NULL;
- }
+JPEGDecoder::JPEGDecoder() : ImageDecoder(), _surface(), _colorSpace(kColorSpaceRGBA) {
}
JPEGDecoder::~JPEGDecoder() {
@@ -65,723 +52,215 @@ JPEGDecoder::~JPEGDecoder() {
}
const Surface *JPEGDecoder::getSurface() const {
- // Make sure we have loaded data
- if (!isLoaded())
- return 0;
-
- if (_rgbSurface)
- return _rgbSurface;
-
- // Create an RGBA8888 surface
- _rgbSurface = new Graphics::Surface();
- _rgbSurface->create(_w, _h, Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16, 8, 0));
-
- // Get our component surfaces
- const Graphics::Surface *yComponent = getComponent(1);
- const Graphics::Surface *uComponent = getComponent(2);
- const Graphics::Surface *vComponent = getComponent(3);
-
- YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch);
-
- return _rgbSurface;
+ return &_surface;
}
void JPEGDecoder::destroy() {
- // Reset member variables
- _stream = NULL;
- _w = _h = 0;
- _restartInterval = 0;
-
- // Free the components
- for (int c = 0; c < _numComp; c++)
- _components[c].surface.free();
- delete[] _components; _components = NULL;
- _numComp = 0;
-
- // Free the scan components
- delete[] _scanComp; _scanComp = NULL;
- _numScanComp = 0;
- _currentComp = NULL;
-
- // Free the quantization tables
- for (int i = 0; i < JPEG_MAX_QUANT_TABLES; i++) {
- delete[] _quant[i];
- _quant[i] = NULL;
- }
-
- // Free the Huffman tables
- for (int i = 0; i < 2 * JPEG_MAX_HUFF_TABLES; i++) {
- _huff[i].count = 0;
- delete[] _huff[i].values; _huff[i].values = NULL;
- delete[] _huff[i].sizes; _huff[i].sizes = NULL;
- delete[] _huff[i].codes; _huff[i].codes = NULL;
- }
-
- if (_rgbSurface) {
- _rgbSurface->free();
- delete _rgbSurface;
- }
+ _surface.free();
}
-bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {
- // Reset member variables and tables from previous reads
- destroy();
-
- // Save the input stream
- _stream = &stream;
-
- bool ok = true;
- bool done = false;
- while (!_stream->eos() && ok && !done) {
- // Read the marker
-
- // WORKAROUND: While each and every JPEG file should end with
- // an EOI (end of image) tag, in reality this may not be the
- // case. For instance, at least one image in the Masterpiece
- // edition of Myst doesn't, yet other programs are able to read
- // the image without complaining.
- //
- // Apparently, the customary workaround is to insert a fake
- // EOI tag.
-
- uint16 marker = _stream->readByte();
- bool fakeEOI = false;
-
- if (_stream->eos()) {
- fakeEOI = true;
- marker = 0xFF;
- }
-
- if (marker != 0xFF) {
- error("JPEG: Invalid marker[0]: 0x%02X", marker);
- ok = false;
- break;
- }
-
- while (marker == 0xFF && !_stream->eos())
- marker = _stream->readByte();
-
- if (_stream->eos()) {
- fakeEOI = true;
- marker = 0xD9;
- }
-
- if (fakeEOI)
- warning("JPEG: Inserted fake EOI");
+#ifdef USE_JPEG
+namespace {
- // Process the marker data
- switch (marker) {
- case 0xC0: // Start Of Frame
- ok = readSOF0();
- break;
- case 0xC4: // Define Huffman Tables
- ok = readDHT();
- break;
- case 0xD8: // Start Of Image
- break;
- case 0xD9: // End Of Image
- done = true;
- break;
- case 0xDA: // Start Of Scan
- ok = readSOS();
- break;
- case 0xDB: // Define Quantization Tables
- ok = readDQT();
- break;
- case 0xE0: // JFIF/JFXX segment
- ok = readJFIF();
- break;
- case 0xDD: // Define Restart Interval
- ok = readDRI();
- break;
- case 0xFE: // Comment
- _stream->seek(_stream->readUint16BE() - 2, SEEK_CUR);
- break;
- default: { // Unknown marker
- uint16 size = _stream->readUint16BE();
+#define JPEG_BUFFER_SIZE 4096
- if ((marker & 0xE0) != 0xE0)
- warning("JPEG: Unknown marker %02X, skipping %d bytes", marker, size - 2);
-
- _stream->seek(size - 2, SEEK_CUR);
- }
- }
- }
+struct StreamSource : public jpeg_source_mgr {
+ Common::SeekableReadStream *stream;
+ bool startOfFile;
+ JOCTET buffer[JPEG_BUFFER_SIZE];
+};
- _stream = 0;
- return ok;
+void initSource(j_decompress_ptr cinfo) {
+ StreamSource *source = (StreamSource *)cinfo->src;
+ source->startOfFile = true;
}
-bool JPEGDecoder::readJFIF() {
- uint16 length = _stream->readUint16BE();
- uint32 tag = _stream->readUint32BE();
+boolean fillInputBuffer(j_decompress_ptr cinfo) {
+ StreamSource *source = (StreamSource *)cinfo->src;
- if (tag != MKTAG('J', 'F', 'I', 'F')) {
- warning("JPEGDecoder::readJFIF() tag mismatch");
- return false;
- }
-
- if (_stream->readByte() != 0) { // NULL
- warning("JPEGDecoder::readJFIF() NULL mismatch");
- return false;
+ uint32 bufferSize = source->stream->read((byte *)source->buffer, sizeof(source->buffer));
+ if (bufferSize == 0) {
+ if (source->startOfFile) {
+ // An empty file is a fatal error
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ } else {
+ // Otherwise we insert an EOF marker
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ source->buffer[0] = (JOCTET)0xFF;
+ source->buffer[1] = (JOCTET)JPEG_EOI;
+ bufferSize = 2;
+ }
}
- byte majorVersion = _stream->readByte();
- byte minorVersion = _stream->readByte();
- if (majorVersion != 1 || minorVersion > 2)
- warning("JPEGDecoder::readJFIF(): v%d.%02d JPEGs may not be handled correctly", majorVersion, minorVersion);
-
- /* byte densityUnits = */_stream->readByte();
- /* uint16 xDensity = */_stream->readUint16BE();
- /* uint16 yDensity = */_stream->readUint16BE();
- byte thumbW = _stream->readByte();
- byte thumbH = _stream->readByte();
-
- _stream->seek(thumbW * thumbH * 3, SEEK_CUR); // Ignore thumbnail
- if (length != (thumbW * thumbH * 3) + 16) {
- warning("JPEGDecoder::readJFIF() length mismatch");
- return false;
- }
+ source->next_input_byte = source->buffer;
+ source->bytes_in_buffer = bufferSize;
+ source->startOfFile = false;
- return true;
+ return TRUE;
}
-// Marker 0xC0 (Start Of Frame, Baseline DCT)
-bool JPEGDecoder::readSOF0() {
- debug(5, "JPEG: readSOF0");
- uint16 size = _stream->readUint16BE();
-
- // Read the sample precision
- uint8 precision = _stream->readByte();
- if (precision != 8) {
- warning("JPEG: Just 8 bit precision supported at the moment");
- return false;
- }
+void skipInputData(j_decompress_ptr cinfo, long numBytes) {
+ StreamSource *source = (StreamSource *)cinfo->src;
- // Image size
- _h = _stream->readUint16BE();
- _w = _stream->readUint16BE();
-
- // Number of components
- _numComp = _stream->readByte();
- if (size != 8 + 3 * _numComp) {
- warning("JPEG: Invalid number of components");
- return false;
- }
+ if (numBytes > 0) {
+ if (numBytes > (long)source->bytes_in_buffer) {
+ // In case we need to skip more bytes than there are in the buffer
+ // we will skip the remaining data and fill the buffer again
+ numBytes -= (long)source->bytes_in_buffer;
- // Allocate the new components
- delete[] _components;
- _components = new Component[_numComp];
-
- // Read the components details
- for (int c = 0; c < _numComp; c++) {
- _components[c].id = _stream->readByte();
- _components[c].factorH = _stream->readByte();
- _components[c].factorV = _components[c].factorH & 0xF;
- _components[c].factorH >>= 4;
- _components[c].quantTableSelector = _stream->readByte();
- }
-
- return true;
-}
+ // Skip the remaining bytes
+ source->stream->skip(numBytes);
-// Marker 0xC4 (Define Huffman Tables)
-bool JPEGDecoder::readDHT() {
- debug(5, "JPEG: readDHT");
- uint16 size = _stream->readUint16BE() - 2;
- uint32 pos = _stream->pos();
-
- while ((uint32)_stream->pos() < (size + pos)) {
- // Read the table type and id
- uint8 tableId = _stream->readByte();
- uint8 tableType = tableId >> 4; // type 0: DC, 1: AC
- tableId &= 0xF;
- uint8 tableNum = (tableId << 1) + tableType;
-
- // Free the Huffman table
- delete[] _huff[tableNum].values; _huff[tableNum].values = NULL;
- delete[] _huff[tableNum].sizes; _huff[tableNum].sizes = NULL;
- delete[] _huff[tableNum].codes; _huff[tableNum].codes = NULL;
-
- // Read the number of values for each length
- uint8 numValues[16];
- _huff[tableNum].count = 0;
- for (int len = 0; len < 16; len++) {
- numValues[len] = _stream->readByte();
- _huff[tableNum].count += numValues[len];
- }
-
- // Allocate memory for the current table
- _huff[tableNum].values = new uint8[_huff[tableNum].count];
- _huff[tableNum].sizes = new uint8[_huff[tableNum].count];
- _huff[tableNum].codes = new uint16[_huff[tableNum].count];
-
- // Read the table contents
- int cur = 0;
- for (int len = 0; len < 16; len++) {
- for (int i = 0; i < numValues[len]; i++) {
- _huff[tableNum].values[cur] = _stream->readByte();
- _huff[tableNum].sizes[cur] = len + 1;
- cur++;
- }
+ // Fill up the buffer again
+ (*source->fill_input_buffer)(cinfo);
+ } else {
+ source->next_input_byte += (size_t)numBytes;
+ source->bytes_in_buffer -= (size_t)numBytes;
}
- // Fill the table of Huffman codes
- cur = 0;
- uint16 curCode = 0;
- uint8 curCodeSize = _huff[tableNum].sizes[0];
- while (cur < _huff[tableNum].count) {
- // Increase the code size to fit the request
- while (_huff[tableNum].sizes[cur] != curCodeSize) {
- curCode <<= 1;
- curCodeSize++;
- }
-
- // Assign the current code
- _huff[tableNum].codes[cur] = curCode;
- curCode++;
- cur++;
- }
}
-
- return true;
}
-// Marker 0xDA (Start Of Scan)
-bool JPEGDecoder::readSOS() {
- debug(5, "JPEG: readSOS");
- uint16 size = _stream->readUint16BE();
-
- // Number of scan components
- _numScanComp = _stream->readByte();
- if (size != 6 + 2 * _numScanComp) {
- warning("JPEG: Invalid number of components");
- return false;
- }
-
- // Allocate the new scan components
- delete[] _scanComp;
- _scanComp = new Component *[_numScanComp];
-
- // Reset the maximum sampling factors
- _maxFactorV = 0;
- _maxFactorH = 0;
-
- // Component-specification parameters
- for (int c = 0; c < _numScanComp; c++) {
- // Read the desired component id
- uint8 id = _stream->readByte();
-
- // Search the component with the specified id
- bool found = false;
- for (int i = 0; !found && i < _numComp; i++) {
- if (_components[i].id == id) {
- // We found the desired component
- found = true;
-
- // Assign the found component to the c'th scan component
- _scanComp[c] = &_components[i];
- }
- }
-
- if (!found) {
- warning("JPEG: Invalid component");
- return false;
- }
-
- // Read the entropy table selectors
- _scanComp[c]->DCentropyTableSelector = _stream->readByte();
- _scanComp[c]->ACentropyTableSelector = _scanComp[c]->DCentropyTableSelector & 0xF;
- _scanComp[c]->DCentropyTableSelector >>= 4;
-
- // Calculate the maximum sampling factors
- if (_scanComp[c]->factorV > _maxFactorV)
- _maxFactorV = _scanComp[c]->factorV;
-
- if (_scanComp[c]->factorH > _maxFactorH)
- _maxFactorH = _scanComp[c]->factorH;
-
- // Initialize the DC predictor
- _scanComp[c]->DCpredictor = 0;
- }
-
- // Start of spectral selection
- if (_stream->readByte() != 0) {
- warning("JPEG: Progressive scanning not supported");
- return false;
- }
-
- // End of spectral selection
- if (_stream->readByte() != 63) {
- warning("JPEG: Progressive scanning not supported");
- return false;
- }
-
- // Successive approximation parameters
- if (_stream->readByte() != 0) {
- warning("JPEG: Progressive scanning not supported");
- return false;
- }
-
- // Entropy coded sequence starts, initialize Huffman decoder
- _bitsNumber = 0;
-
- // Read all the scan MCUs
- uint16 xMCU = _w / (_maxFactorH * 8);
- uint16 yMCU = _h / (_maxFactorV * 8);
-
- // Check for non- multiple-of-8 dimensions
- if (_w % (_maxFactorH * 8) != 0)
- xMCU++;
- if (_h % (_maxFactorV * 8) != 0)
- yMCU++;
-
- // Initialize the scan surfaces
- for (uint16 c = 0; c < _numScanComp; c++) {
- _scanComp[c]->surface.create(xMCU * _maxFactorH * 8, yMCU * _maxFactorV * 8, PixelFormat::createFormatCLUT8());
- }
-
- bool ok = true;
- uint16 interval = _restartInterval;
-
- for (int y = 0; ok && (y < yMCU); y++) {
- for (int x = 0; ok && (x < xMCU); x++) {
- ok = readMCU(x, y);
-
- // If we have a restart interval, we'll need to reset a couple
- // variables
- if (_restartInterval != 0) {
- interval--;
-
- if (interval == 0) {
- interval = _restartInterval;
- _bitsNumber = 0;
-
- for (byte i = 0; i < _numScanComp; i++)
- _scanComp[i]->DCpredictor = 0;
- }
- }
- }
- }
-
- // Trim Component surfaces back to image height and width
- // Note: Code using jpeg must use surface.pitch correctly...
- for (uint16 c = 0; c < _numScanComp; c++) {
- _scanComp[c]->surface.w = _w;
- _scanComp[c]->surface.h = _h;
- }
-
- return ok;
+void termSource(j_decompress_ptr cinfo) {
}
-// Marker 0xDB (Define Quantization Tables)
-bool JPEGDecoder::readDQT() {
- debug(5, "JPEG: readDQT");
- uint16 size = _stream->readUint16BE() - 2;
- uint32 pos = _stream->pos();
-
- while ((uint32)_stream->pos() < (pos + size)) {
- // Read the table precision and id
- uint8 tableId = _stream->readByte();
- bool highPrecision = (tableId & 0xF0) != 0;
-
- // Validate the table id
- tableId &= 0xF;
- if (tableId >= JPEG_MAX_QUANT_TABLES) {
- warning("JPEG: Invalid quantization table");
- return false;
- }
-
- // Create the new table if necessary
- if (!_quant[tableId])
- _quant[tableId] = new uint16[64];
+void jpeg_scummvm_src(j_decompress_ptr cinfo, Common::SeekableReadStream *stream) {
+ StreamSource *source;
- // Read the table (stored in Zig-Zag order)
- for (int i = 0; i < 64; i++)
- _quant[tableId][i] = highPrecision ? _stream->readUint16BE() : _stream->readByte();
+ // Initialize the source in case it has not been done yet.
+ if (cinfo->src == NULL) {
+ cinfo->src = (jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(StreamSource));
}
- return true;
-}
+ source = (StreamSource *)cinfo->src;
+ source->init_source = &initSource;
+ source->fill_input_buffer = &fillInputBuffer;
+ source->skip_input_data = &skipInputData;
+ source->resync_to_restart = &jpeg_resync_to_restart;
+ source->term_source = &termSource;
+ source->bytes_in_buffer = 0;
+ source->next_input_byte = NULL;
-// Marker 0xDD (Define Restart Interval)
-bool JPEGDecoder::readDRI() {
- debug(5, "JPEG: readDRI");
- uint16 size = _stream->readUint16BE() - 2;
-
- if (size != 2) {
- warning("JPEG: Invalid DRI size %d", size);
- return false;
- }
-
- _restartInterval = _stream->readUint16BE();
- debug(5, "Restart interval: %d", _restartInterval);
- return true;
+ source->stream = stream;
}
-bool JPEGDecoder::readMCU(uint16 xMCU, uint16 yMCU) {
- bool ok = true;
- for (int c = 0; ok && (c < _numComp); c++) {
- // Set the current component
- _currentComp = _scanComp[c];
-
- // Read the data units of the current component
- for (int y = 0; ok && (y < _scanComp[c]->factorV); y++)
- for (int x = 0; ok && (x < _scanComp[c]->factorH); x++)
- ok = readDataUnit(xMCU * _scanComp[c]->factorH + x, yMCU * _scanComp[c]->factorV + y);
- }
-
- return ok;
+void errorExit(j_common_ptr cinfo) {
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+ // This function is not allowed to return to the caller, thus we simply
+ // error out with our error handling here.
+ error("%s", buffer);
}
-// triple-butterfly-add (and possible rounding)
-#define xadd3(xa, xb, xc, xd, h) \
- p = xa + xb; \
- n = xa - xb; \
- xa = p + xc + h; \
- xb = n + xd + h; \
- xc = p - xc + h; \
- xd = n - xd + h;
-
-// butterfly-mul
-#define xmul(xa, xb, k1, k2, sh) \
- n = k1 * (xa + xb); \
- p = xa; \
- xa = (n + (k2 - k1) * xb) >> sh; \
- xb = (n - (k2 + k1) * p) >> sh;
-
-// IDCT based on public domain code from http://halicery.com/jpeg/idct.html
-void JPEGDecoder::idct1D8x8(int32 src[8], int32 dest[64], int32 ps, int32 half) {
- int p, n;
-
- src[0] <<= 9;
- src[1] <<= 7;
- src[3] *= 181;
- src[4] <<= 9;
- src[5] *= 181;
- src[7] <<= 7;
-
- // Even part
- xmul(src[6], src[2], 277, 669, 0)
- xadd3(src[0], src[4], src[6], src[2], half)
-
- // Odd part
- xadd3(src[1], src[7], src[3], src[5], 0)
- xmul(src[5], src[3], 251, 50, 6)
- xmul(src[1], src[7], 213, 142, 6)
-
- dest[0 * 8] = (src[0] + src[1]) >> ps;
- dest[1 * 8] = (src[4] + src[5]) >> ps;
- dest[2 * 8] = (src[2] + src[3]) >> ps;
- dest[3 * 8] = (src[6] + src[7]) >> ps;
- dest[4 * 8] = (src[6] - src[7]) >> ps;
- dest[5 * 8] = (src[2] - src[3]) >> ps;
- dest[6 * 8] = (src[4] - src[5]) >> ps;
- dest[7 * 8] = (src[0] - src[1]) >> ps;
+void outputMessage(j_common_ptr cinfo) {
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+ // Is using debug here a good idea? Or do we want to ignore all libjpeg
+ // messages?
+ debug(3, "libjpeg: %s", buffer);
}
-void JPEGDecoder::idct2D8x8(int32 block[64]) {
- int32 tmp[64];
-
- // Apply 1D IDCT to rows
- for (int i = 0; i < 8; i++)
- idct1D8x8(&block[i * 8], &tmp[i], 9, 1 << 8);
-
- // Apply 1D IDCT to columns
- for (int i = 0; i < 8; i++)
- idct1D8x8(&tmp[i * 8], &block[i], 12, 1 << 11);
- }
-
-bool JPEGDecoder::readDataUnit(uint16 x, uint16 y) {
- // Prepare an empty data array
- int16 readData[64];
- for (int i = 1; i < 64; i++)
- readData[i] = 0;
-
- // Read the DC component
- readData[0] = _currentComp->DCpredictor + readDC();
- _currentComp->DCpredictor = readData[0];
-
- // Read the AC components (stored in Zig-Zag)
- readAC(readData);
-
- // Calculate the DCT coefficients from the input sequence
- int32 block[64];
- for (uint8 i = 0; i < 64; i++) {
- // Dequantize
- int32 val = readData[i];
- int16 quant = _quant[_currentComp->quantTableSelector][i];
- val *= quant;
-
- // Store the normalized coefficients, undoing the Zig-Zag
- block[_zigZagOrder[i]] = val;
- }
+} // End of anonymous namespace
+#endif
- // Apply the IDCT
- idct2D8x8(block);
+bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {
+#ifdef USE_JPEG
+ // Reset member variables from previous decodings
+ destroy();
- // Level shift to make the values unsigned
- for (int i = 0; i < 64; i++) {
- block[i] = block[i] + 128;
+ jpeg_decompress_struct cinfo;
+ jpeg_error_mgr jerr;
- if (block[i] < 0)
- block[i] = 0;
+ // Initialize error handling callbacks
+ cinfo.err = jpeg_std_error(&jerr);
+ cinfo.err->error_exit = &errorExit;
+ cinfo.err->output_message = &outputMessage;
- if (block[i] > 255)
- block[i] = 255;
- }
+ // Initialize the decompression structure
+ jpeg_create_decompress(&cinfo);
- // Paint the component surface
- uint8 scalingV = _maxFactorV / _currentComp->factorV;
- uint8 scalingH = _maxFactorH / _currentComp->factorH;
+ // Initialize our buffer handling
+ jpeg_scummvm_src(&cinfo, &stream);
- // Convert coordinates from MCU blocks to pixels
- x <<= 3;
- y <<= 3;
+ // Read the file header
+ jpeg_read_header(&cinfo, TRUE);
- for (uint8 j = 0; j < 8; j++) {
- for (uint16 sV = 0; sV < scalingV; sV++) {
- // Get the beginning of the block line
- byte *ptr = (byte *)_currentComp->surface.getBasePtr(x * scalingH, (y + j) * scalingV + sV);
+ // We can request YUV output because Groovie requires it
+ switch (_colorSpace) {
+ case kColorSpaceRGBA:
+ cinfo.out_color_space = JCS_RGB;
+ break;
- for (uint8 i = 0; i < 8; i++) {
- for (uint16 sH = 0; sH < scalingH; sH++) {
- *ptr = (byte)(block[j * 8 + i]);
- ptr++;
- }
- }
- }
+ case kColorSpaceYUV:
+ cinfo.out_color_space = JCS_YCbCr;
+ break;
}
- return true;
-}
-
-int16 JPEGDecoder::readDC() {
- // DC is type 0
- uint8 tableNum = _currentComp->DCentropyTableSelector << 1;
-
- // Get the number of bits to read
- uint8 numBits = readHuff(tableNum);
-
- // Read the requested bits
- return readSignedBits(numBits);
-}
-
-void JPEGDecoder::readAC(int16 *out) {
- // AC is type 1
- uint8 tableNum = (_currentComp->ACentropyTableSelector << 1) + 1;
-
- // Start reading AC element 1
- uint8 cur = 1;
- while (cur < 64) {
- uint8 s = readHuff(tableNum);
- uint8 r = s >> 4;
- s &= 0xF;
-
- if (s == 0) {
- if (r == 15) {
- // Skip 16 values
- cur += 16;
- } else {
- // EOB: end of block
- cur = 64;
- }
- } else {
- // Skip r values
- cur += r;
-
- // Read the next value
- out[cur] = readSignedBits(s);
- cur++;
- }
+ // Actually start decompressing the image
+ jpeg_start_decompress(&cinfo);
+
+ // Allocate buffers for the output data
+ switch (_colorSpace) {
+ case kColorSpaceRGBA:
+ // We use RGBA8888 in this scenario
+ _surface.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16, 8, 0));
+ break;
+
+ case kColorSpaceYUV:
+ // We use YUV with 3 bytes per pixel otherwise.
+ // This is pretty ugly since our PixelFormat cannot express YUV...
+ _surface.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat(3, 0, 0, 0, 0, 0, 0, 0, 0));
+ break;
}
-}
-
-int16 JPEGDecoder::readSignedBits(uint8 numBits) {
- uint16 ret = 0;
- if (numBits > 16)
- error("requested %d bits", numBits); //XXX
-
- // MSB=0 for negatives, 1 for positives
- for (int i = 0; i < numBits; i++)
- ret = (ret << 1) + readBit();
-
- // Extend sign bits (PAG109)
- if (!(ret >> (numBits - 1))) {
- uint16 tmp = ((uint16)-1 << numBits) + 1;
- ret = ret + tmp;
- }
- return ret;
-}
-
-// TODO: optimize?
-uint8 JPEGDecoder::readHuff(uint8 table) {
- bool foundCode = false;
- uint8 val = 0;
-
- uint8 cur = 0;
- uint8 codeSize = 1;
- uint16 code = readBit();
- while (!foundCode) {
- // Prepare a code of the current size
- while (codeSize < _huff[table].sizes[cur]) {
- code = (code << 1) + readBit();
- codeSize++;
- }
- // Compare the codes of the current size
- while (!foundCode && (codeSize == _huff[table].sizes[cur])) {
- if (code == _huff[table].codes[cur]) {
- // Found the code
- val = _huff[table].values[cur];
- foundCode = true;
- } else {
- // Continue reading
- cur++;
+ // Allocate buffer for one scanline
+ assert(cinfo.output_components == 3);
+ JDIMENSION pitch = cinfo.output_width * cinfo.output_components;
+ assert(_surface.pitch >= pitch);
+ JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, pitch, 1);
+
+ // Go through the image data scanline by scanline
+ while (cinfo.output_scanline < cinfo.output_height) {
+ byte *dst = (byte *)_surface.getBasePtr(0, cinfo.output_scanline);
+
+ jpeg_read_scanlines(&cinfo, buffer, 1);
+
+ const byte *src = buffer[0];
+ switch (_colorSpace) {
+ case kColorSpaceRGBA: {
+ for (int remaining = cinfo.output_width; remaining > 0; --remaining) {
+ byte r = *src++;
+ byte g = *src++;
+ byte b = *src++;
+ // We need to insert a alpha value of 255 (opaque) here.
+#ifdef SCUMM_BIG_ENDIAN
+ *dst++ = r;
+ *dst++ = g;
+ *dst++ = b;
+ *dst++ = 0xFF;
+#else
+ *dst++ = 0xFF;
+ *dst++ = b;
+ *dst++ = g;
+ *dst++ = r;
+#endif
}
- }
- }
+ } break;
- return val;
-}
-
-uint8 JPEGDecoder::readBit() {
- // Read a whole byte if necessary
- if (_bitsNumber == 0) {
- _bitsData = _stream->readByte();
- _bitsNumber = 8;
-
- // Detect markers
- if (_bitsData == 0xFF) {
- uint8 byte2 = _stream->readByte();
-
- // A stuffed 0 validates the previous byte
- if (byte2 != 0) {
- if (byte2 == 0xDC) {
- // DNL marker: Define Number of Lines
- // TODO: terminate scan
- warning("DNL marker detected: terminate scan");
- } else if (byte2 >= 0xD0 && byte2 <= 0xD7) {
- debug(7, "RST%d marker detected", byte2 & 7);
- _bitsData = _stream->readByte();
- } else {
- warning("Error: marker 0x%02X read in entropy data", byte2);
- }
- }
+ case kColorSpaceYUV:
+ memcpy(dst, src, pitch);
+ break;
}
}
- _bitsNumber--;
-
- return (_bitsData & (1 << _bitsNumber)) ? 1 : 0;
-}
-const Surface *JPEGDecoder::getComponent(uint c) const {
- for (int i = 0; i < _numComp; i++)
- if (_components[i].id == c) // We found the desired component
- return &_components[i].surface;
+ // We are done with decompressing, thus free all the data
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
- error("JPEGDecoder::getComponent: No component %d present", c);
- return NULL;
+ return true;
+#else
+ return false;
+#endif
}
} // End of Graphics namespace
diff --git a/graphics/decoders/jpeg.h b/graphics/decoders/jpeg.h
index d59b72adf4..8460bc2698 100644
--- a/graphics/decoders/jpeg.h
+++ b/graphics/decoders/jpeg.h
@@ -40,100 +40,54 @@ class SeekableReadStream;
namespace Graphics {
-struct PixelFormat;
-
-#define JPEG_MAX_QUANT_TABLES 4
-#define JPEG_MAX_HUFF_TABLES 2
-
class JPEGDecoder : public ImageDecoder {
public:
JPEGDecoder();
~JPEGDecoder();
// ImageDecoder API
- void destroy();
- bool loadStream(Common::SeekableReadStream &str);
- const Surface *getSurface() const;
-
- bool isLoaded() const { return _numComp && _w && _h; }
- uint16 getWidth() const { return _w; }
- uint16 getHeight() const { return _h; }
- const Surface *getComponent(uint c) const;
-
-private:
- Common::SeekableReadStream *_stream;
- uint16 _w, _h;
- uint16 _restartInterval;
-
- // mutable so that we can convert to RGB only during
- // a getSurface() call while still upholding the
- // const requirement in other ImageDecoders
- mutable Graphics::Surface *_rgbSurface;
-
- // Image components
- uint8 _numComp;
- struct Component {
- // Global values
- uint8 id;
- uint8 factorH;
- uint8 factorV;
- uint8 quantTableSelector;
-
- // Scan specific values
- uint8 DCentropyTableSelector;
- uint8 ACentropyTableSelector;
- int16 DCpredictor;
-
- // Result image for this component
- Surface surface;
+ virtual void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &str);
+ virtual const Surface *getSurface() const;
+
+ // Special API for JPEG
+ enum ColorSpace {
+ /**
+ * Output 32bit RGBA data.
+ *
+ * This is the default output.
+ */
+ kColorSpaceRGBA,
+
+ /**
+ * Output (interleaved) YUV data.
+ *
+ * Be aware that some images cannot be output in YUV mode.
+ * These are (non-standard) JPEG images which are in RGB colorspace.
+ *
+ * The resulting Surface will have a PixelFormat with 3 bytes per
+ * pixel and the remaining entries are completely zeroed. This works
+ * around the fact that PixelFormat can only describe RGB formats.
+ *
+ * You should only use this when you are really aware of what you are
+ * doing!
+ */
+ kColorSpaceYUV
};
- Component *_components;
+ /**
+ * Request the output color space. This can be used to obtain raw YUV
+ * data from the JPEG file. But this might not work for all files!
+ *
+ * The decoder itself defaults to RGBA.
+ *
+ * @param outSpace The color space to output.
+ */
+ void setOutputColorSpace(ColorSpace outSpace) { _colorSpace = outSpace; }
- // Scan components
- uint8 _numScanComp;
- Component **_scanComp;
- Component *_currentComp;
-
- // Maximum sampling factors, used to calculate the interleaving of the MCU
- uint8 _maxFactorV;
- uint8 _maxFactorH;
-
- // Quantization tables
- uint16 *_quant[JPEG_MAX_QUANT_TABLES];
-
- // Huffman tables
- struct HuffmanTable {
- uint8 count;
- uint8 *values;
- uint8 *sizes;
- uint16 *codes;
- } _huff[2 * JPEG_MAX_HUFF_TABLES];
-
- // Marker read functions
- bool readJFIF();
- bool readSOF0();
- bool readDHT();
- bool readSOS();
- bool readDQT();
- bool readDRI();
-
- // Helper functions
- bool readMCU(uint16 xMCU, uint16 yMCU);
- bool readDataUnit(uint16 x, uint16 y);
- int16 readDC();
- void readAC(int16 *out);
- int16 readSignedBits(uint8 numBits);
-
- // Huffman decoding
- uint8 readHuff(uint8 table);
- uint8 readBit();
- uint8 _bitsData;
- uint8 _bitsNumber;
-
- // Inverse Discrete Cosine Transformation
- static void idct1D8x8(int32 src[8], int32 dest[64], int32 ps, int32 half);
- static void idct2D8x8(int32 block[64]);
+private:
+ Graphics::Surface _surface;
+ ColorSpace _colorSpace;
};
} // End of Graphics namespace
diff --git a/graphics/decoders/pcx.cpp b/graphics/decoders/pcx.cpp
index 1250398c73..eb9b4c997d 100644
--- a/graphics/decoders/pcx.cpp
+++ b/graphics/decoders/pcx.cpp
@@ -117,7 +117,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) {
if (nPlanes == 3 && bitsPerPixel == 8) { // 24bpp
Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
_surface->create(width, height, format);
- dst = (byte *)_surface->pixels;
+ dst = (byte *)_surface->getPixels();
_paletteColorCount = 0;
for (y = 0; y < height; y++) {
@@ -135,7 +135,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) {
}
} else if (nPlanes == 1 && bitsPerPixel == 8) { // 8bpp indexed
_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- dst = (byte *)_surface->pixels;
+ dst = (byte *)_surface->getPixels();
_paletteColorCount = 16;
for (y = 0; y < height; y++, dst += _surface->pitch) {
@@ -163,7 +163,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) {
}
} else if ((nPlanes == 2 || nPlanes == 3 || nPlanes == 4) && bitsPerPixel == 1) { // planar, 4, 8 or 16 colors
_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- dst = (byte *)_surface->pixels;
+ dst = (byte *)_surface->getPixels();
_paletteColorCount = 16;
for (y = 0; y < height; y++, dst += _surface->pitch) {
diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp
index b1d408ebc3..f3e17b33e2 100644
--- a/graphics/decoders/pict.cpp
+++ b/graphics/decoders/pict.cpp
@@ -364,7 +364,7 @@ void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPa
case 1:
// Just copy to the image
_outputSurface->create(width, height, PixelFormat::createFormatCLUT8());
- memcpy(_outputSurface->pixels, buffer, _outputSurface->w * _outputSurface->h);
+ memcpy(_outputSurface->getPixels(), buffer, _outputSurface->w * _outputSurface->h);
break;
case 2:
// We have a 16-bit surface
diff --git a/graphics/decoders/png.cpp b/graphics/decoders/png.cpp
index 11e26162eb..c4fee46fec 100644
--- a/graphics/decoders/png.cpp
+++ b/graphics/decoders/png.cpp
@@ -38,7 +38,7 @@
namespace Graphics {
-PNGDecoder::PNGDecoder() : _outputSurface(0), _palette(0), _paletteColorCount(0) {
+PNGDecoder::PNGDecoder() : _outputSurface(0), _palette(0), _paletteColorCount(0), _stream(0) {
}
PNGDecoder::~PNGDecoder() {
@@ -163,16 +163,20 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) {
_outputSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
png_set_packing(pngPtr);
} else {
- _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
- if (!_outputSurface->pixels) {
+ bool isAlpha = (colorType & PNG_COLOR_MASK_ALPHA);
+ if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
+ isAlpha = true;
+ png_set_expand(pngPtr);
+ }
+ _outputSurface->create(width, height, Graphics::PixelFormat(4,
+ 8, 8, 8, isAlpha ? 8 : 0, 24, 16, 8, 0));
+ if (!_outputSurface->getPixels()) {
error("Could not allocate memory for output image.");
}
if (bitDepth == 16)
png_set_strip_16(pngPtr);
if (bitDepth < 8)
png_set_expand(pngPtr);
- if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
- png_set_expand(pngPtr);
if (colorType == PNG_COLOR_TYPE_GRAY ||
colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(pngPtr);
diff --git a/graphics/decoders/tga.cpp b/graphics/decoders/tga.cpp
index c3b9d84055..bc27f18a49 100644
--- a/graphics/decoders/tga.cpp
+++ b/graphics/decoders/tga.cpp
@@ -50,6 +50,8 @@ void TGADecoder::destroy() {
}
bool TGADecoder::loadStream(Common::SeekableReadStream &tga) {
+ destroy();
+
byte imageType, pixelDepth;
bool success;
success = readHeader(tga, imageType, pixelDepth);
@@ -272,7 +274,7 @@ bool TGADecoder::readData(Common::SeekableReadStream &tga, byte imageType, byte
} else if (imageType == TYPE_BW) {
_surface.create(_surface.w, _surface.h, _format);
- byte *data = (byte *)_surface.pixels;
+ byte *data = (byte *)_surface.getPixels();
uint32 count = _surface.w * _surface.h;
while (count-- > 0) {
@@ -318,7 +320,7 @@ bool TGADecoder::readDataRLE(Common::SeekableReadStream &tga, byte imageType, by
if (imageType == TYPE_RLE_TRUECOLOR || imageType == TYPE_RLE_BW || imageType == TYPE_RLE_CMAP) {
_surface.create(_surface.w, _surface.h, _format);
uint32 count = _surface.w * _surface.h;
- byte *data = (byte *)_surface.pixels;
+ byte *data = (byte *)_surface.getPixels();
while (count > 0) {
uint32 header = tga.readByte();
diff --git a/graphics/decoders/tga.h b/graphics/decoders/tga.h
index d8ccf8f766..5b1e87d4c5 100644
--- a/graphics/decoders/tga.h
+++ b/graphics/decoders/tga.h
@@ -26,6 +26,7 @@
/*
* TGA decoder used in engines:
* - wintermute
+ * - zvision
*/
#ifndef GRAPHICS_DECODERS_TGA_H
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 3b00cd8568..e9f139c478 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -26,93 +26,32 @@
namespace Graphics {
-int Font::getKerningOffset(byte left, byte right) const {
+int Font::getKerningOffset(uint32 left, uint32 right) const {
return 0;
}
-int Font::getStringWidth(const Common::String &str) const {
+namespace {
+
+template<class StringType>
+int getStringWidthImpl(const Font &font, const StringType &str) {
int space = 0;
- uint last = 0;
+ typename StringType::unsigned_type last = 0;
for (uint i = 0; i < str.size(); ++i) {
- const uint cur = str[i];
- space += getCharWidth(cur) + getKerningOffset(last, cur);
+ const typename StringType::unsigned_type cur = str[i];
+ space += font.getCharWidth(cur) + font.getKerningOffset(last, cur);
last = cur;
}
return space;
}
-void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+template<class StringType>
+void drawStringImpl(const Font &font, Surface *dst, const StringType &str, int x, int y, int w, uint32 color, TextAlign align, int deltax) {
assert(dst != 0);
- const int leftX = x, rightX = x + w;
- uint i;
- Common::String s = sOld;
- int width = getStringWidth(s);
- Common::String str;
-
- if (useEllipsis && width > w && s.hasSuffix("...")) {
- // String is too wide. Check whether it ends in an ellipsis
- // ("..."). If so, remove that and try again!
- s.deleteLastChar();
- s.deleteLastChar();
- s.deleteLastChar();
- width = getStringWidth(s);
- }
-
- if (useEllipsis && width > w) {
- // String is too wide. So we shorten it "intelligently" by
- // replacing parts of the string by an ellipsis. There are
- // three possibilities for this: replace the start, the end, or
- // the middle of the string. What is best really depends on the
- // context; but unless we want to make this configurable,
- // replacing the middle seems to be a good compromise.
-
- const int ellipsisWidth = getStringWidth("...");
-
- // SLOW algorithm to remove enough of the middle. But it is good enough
- // for now.
- const int halfWidth = (w - ellipsisWidth) / 2;
- int w2 = 0;
- uint last = 0;
-
- for (i = 0; i < s.size(); ++i) {
- const uint cur = s[i];
- int charWidth = getCharWidth(cur) + getKerningOffset(last, cur);
- if (w2 + charWidth > halfWidth)
- break;
- last = cur;
- w2 += charWidth;
- str += cur;
- }
-
- // At this point we know that the first 'i' chars are together 'w2'
- // pixels wide. We took the first i-1, and add "..." to them.
- str += "...";
- last = '.';
- // The original string is width wide. Of those we already skipped past
- // w2 pixels, which means (width - w2) remain.
- // The new str is (w2+ellipsisWidth) wide, so we can accommodate about
- // (w - (w2+ellipsisWidth)) more pixels.
- // Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
- // (width + ellipsisWidth - w)
- int skip = width + ellipsisWidth - w;
- for (; i < s.size() && skip > 0; ++i) {
- const uint cur = s[i];
- skip -= getCharWidth(cur) + getKerningOffset(last, cur);
- last = cur;
- }
-
- // Append the remaining chars, if any
- for (; i < s.size(); ++i) {
- str += s[i];
- }
-
- width = getStringWidth(str);
- } else {
- str = s;
- }
+ const int leftX = x, rightX = x + w;
+ int width = font.getStringWidth(str);
if (align == kTextAlignCenter)
x = x + (w - width)/2;
@@ -120,29 +59,29 @@ void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, in
x = x + w - width;
x += deltax;
- uint last = 0;
- for (i = 0; i < str.size(); ++i) {
- const uint cur = str[i];
- x += getKerningOffset(last, cur);
+ typename StringType::unsigned_type last = 0;
+ for (typename StringType::const_iterator i = str.begin(), end = str.end(); i != end; ++i) {
+ const typename StringType::unsigned_type cur = *i;
+ x += font.getKerningOffset(last, cur);
last = cur;
- w = getCharWidth(cur);
+ w = font.getCharWidth(cur);
if (x+w > rightX)
break;
- if (x >= leftX)
- drawChar(dst, str[i], x, y, color);
+ if (x+w >= leftX)
+ font.drawChar(dst, cur, x, y, color);
x += w;
}
}
-
+template<class StringType>
struct WordWrapper {
- Common::Array<Common::String> &lines;
+ Common::Array<StringType> &lines;
int actualMaxLineWidth;
- WordWrapper(Common::Array<Common::String> &l) : lines(l), actualMaxLineWidth(0) {
+ WordWrapper(Common::Array<StringType> &l) : lines(l), actualMaxLineWidth(0) {
}
- void add(Common::String &line, int &w) {
+ void add(StringType &line, int &w) {
if (actualMaxLineWidth < w)
actualMaxLineWidth = w;
@@ -153,10 +92,11 @@ struct WordWrapper {
}
};
-int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
- WordWrapper wrapper(lines);
- Common::String line;
- Common::String tmpStr;
+template<class StringType>
+int wordWrapTextImpl(const Font &font, const StringType &str, int maxWidth, Common::Array<StringType> &lines) {
+ WordWrapper<StringType> wrapper(lines);
+ StringType line;
+ StringType tmpStr;
int lineWidth = 0;
int tmpWidth = 0;
@@ -173,10 +113,10 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
// of a line. If we encounter such a word, we have to wrap it over multiple
// lines.
- uint last = 0;
- for (Common::String::const_iterator x = str.begin(); x != str.end(); ++x) {
- const byte c = *x;
- const int w = getCharWidth(c) + getKerningOffset(last, c);
+ typename StringType::unsigned_type last = 0;
+ for (typename StringType::const_iterator x = str.begin(); x != str.end(); ++x) {
+ const typename StringType::unsigned_type c = *x;
+ const int w = font.getCharWidth(c) + font.getKerningOffset(last, c);
last = c;
const bool wouldExceedWidth = (lineWidth + tmpWidth + w > maxWidth);
@@ -212,7 +152,7 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
tmpStr.deleteChar(0);
// This is not very fast, but it is the simplest way to
// assure we do not mess something up because of kerning.
- tmpWidth = getStringWidth(tmpStr);
+ tmpWidth = font.getStringWidth(tmpStr);
}
} else {
wrapper.add(tmpStr, tmpWidth);
@@ -232,5 +172,98 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
return wrapper.actualMaxLineWidth;
}
+} // End of anonymous namespace
+
+int Font::getStringWidth(const Common::String &str) const {
+ return getStringWidthImpl(*this, str);
+}
+
+int Font::getStringWidth(const Common::U32String &str) const {
+ return getStringWidthImpl(*this, str);
+}
+
+void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ Common::String s = sOld;
+ int width = getStringWidth(s);
+ Common::String str;
+
+ if (useEllipsis && width > w && s.hasSuffix("...")) {
+ // String is too wide. Check whether it ends in an ellipsis
+ // ("..."). If so, remove that and try again!
+ s.deleteLastChar();
+ s.deleteLastChar();
+ s.deleteLastChar();
+ width = getStringWidth(s);
+ }
+
+ if (useEllipsis && width > w) {
+ // String is too wide. So we shorten it "intelligently" by
+ // replacing parts of the string by an ellipsis. There are
+ // three possibilities for this: replace the start, the end, or
+ // the middle of the string. What is best really depends on the
+ // context; but unless we want to make this configurable,
+ // replacing the middle seems to be a good compromise.
+
+ const int ellipsisWidth = getStringWidth("...");
+
+ // SLOW algorithm to remove enough of the middle. But it is good enough
+ // for now.
+ const int halfWidth = (w - ellipsisWidth) / 2;
+ int w2 = 0;
+ Common::String::unsigned_type last = 0;
+ uint i;
+
+ for (i = 0; i < s.size(); ++i) {
+ const Common::String::unsigned_type cur = s[i];
+ int charWidth = getCharWidth(cur) + getKerningOffset(last, cur);
+ if (w2 + charWidth > halfWidth)
+ break;
+ last = cur;
+ w2 += charWidth;
+ str += cur;
+ }
+
+ // At this point we know that the first 'i' chars are together 'w2'
+ // pixels wide. We took the first i-1, and add "..." to them.
+ str += "...";
+ last = '.';
+
+ // The original string is width wide. Of those we already skipped past
+ // w2 pixels, which means (width - w2) remain.
+ // The new str is (w2+ellipsisWidth) wide, so we can accommodate about
+ // (w - (w2+ellipsisWidth)) more pixels.
+ // Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
+ // (width + ellipsisWidth - w)
+ int skip = width + ellipsisWidth - w;
+ for (; i < s.size() && skip > 0; ++i) {
+ const Common::String::unsigned_type cur = s[i];
+ skip -= getCharWidth(cur) + getKerningOffset(last, cur);
+ last = cur;
+ }
+
+ // Append the remaining chars, if any
+ for (; i < s.size(); ++i) {
+ str += s[i];
+ }
+
+ width = getStringWidth(str);
+ } else {
+ str = s;
+ }
+
+ drawStringImpl(*this, dst, str, x, y, w, color, align, deltax);
+}
+
+void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align) const {
+ drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
+}
+
+int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
+ return wordWrapTextImpl(*this, str, maxWidth, lines);
+}
+
+int Font::wordWrapText(const Common::U32String &str, int maxWidth, Common::Array<Common::U32String> &lines) const {
+ return wordWrapTextImpl(*this, str, maxWidth, lines);
+}
} // End of namespace Graphics
diff --git a/graphics/font.h b/graphics/font.h
index 6819b42f52..77b7623a85 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -23,6 +23,7 @@
#define GRAPHICS_FONT_H
#include "common/str.h"
+#include "common/ustr.h"
namespace Common {
template<class T> class Array;
@@ -70,7 +71,7 @@ public:
* @param chr The character to query the width of.
* @return The character's width.
*/
- virtual int getCharWidth(byte chr) const = 0;
+ virtual int getCharWidth(uint32 chr) const = 0;
/**
* Query the kerning offset between two characters.
@@ -79,7 +80,7 @@ public:
* @param right The right character. May be 0.
* @return The horizontal displacement.
*/
- virtual int getKerningOffset(byte left, byte right) const;
+ virtual int getKerningOffset(uint32 left, uint32 right) const;
/**
* Draw a character at a specific point on a surface.
@@ -96,15 +97,17 @@ public:
* @param y The y coordinate where to draw the character.
* @param color The color of the character.
*/
- virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const = 0;
+ virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const = 0;
// TODO: Add doxygen comments to this
void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+ void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
/**
* Compute and return the width the string str has when rendered using this font.
*/
int getStringWidth(const Common::String &str) const;
+ int getStringWidth(const Common::U32String &str) const;
/**
* Take a text (which may contain newline characters) and word wrap it so that
@@ -120,6 +123,7 @@ public:
* @return the maximal width of any of the lines added to lines
*/
int wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const;
+ int wordWrapText(const Common::U32String &str, int maxWidth, Common::Array<Common::U32String> &lines) const;
};
} // End of namespace Graphics
diff --git a/graphics/fonts/bdf.cpp b/graphics/fonts/bdf.cpp
index 6d4befa37c..7b2290cc3a 100644
--- a/graphics/fonts/bdf.cpp
+++ b/graphics/fonts/bdf.cpp
@@ -51,7 +51,7 @@ int BdfFont::getMaxCharWidth() const {
return _data.maxAdvance;
}
-int BdfFont::getCharWidth(byte chr) const {
+int BdfFont::getCharWidth(uint32 chr) const {
// In case all font have the same advance value, we use the maximum.
if (!_data.advances)
return _data.maxAdvance;
@@ -85,9 +85,9 @@ void drawCharIntern(byte *ptr, uint pitch, const byte *src, int h, int width, in
}
}
-int BdfFont::mapToIndex(byte ch) const {
+int BdfFont::mapToIndex(uint32 ch) const {
// Check whether the character is included
- if (_data.firstCharacter <= ch && ch <= _data.firstCharacter + _data.numCharacters) {
+ if (_data.firstCharacter <= (int)ch && (int)ch <= _data.firstCharacter + _data.numCharacters) {
if (_data.bitmaps[ch - _data.firstCharacter])
return ch - _data.firstCharacter;
}
@@ -95,14 +95,14 @@ int BdfFont::mapToIndex(byte ch) const {
return _data.defaultCharacter - _data.firstCharacter;
}
-void BdfFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const uint32 color) const {
+void BdfFont::drawChar(Surface *dst, uint32 chr, const int tx, const int ty, const uint32 color) const {
assert(dst != 0);
// TODO: Where is the relation between the max advance being smaller or
// equal to 50 and the decision of the theme designer?
// asserting _data.maxAdvance <= 50: let the theme designer decide what looks best
assert(_data.maxAdvance <= 50);
- assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2);
+ assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
const int idx = mapToIndex(chr);
if (idx < 0)
@@ -165,6 +165,8 @@ void BdfFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const
drawCharIntern<byte>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color);
else if (dst->format.bytesPerPixel == 2)
drawCharIntern<uint16>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color);
+ else if (dst->format.bytesPerPixel == 4)
+ drawCharIntern<uint32>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color);
}
namespace {
diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h
index b0166a2095..842e54f851 100644
--- a/graphics/fonts/bdf.h
+++ b/graphics/fonts/bdf.h
@@ -61,14 +61,14 @@ public:
virtual int getFontHeight() const;
virtual int getMaxCharWidth() const;
- virtual int getCharWidth(byte chr) const;
- virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+ virtual int getCharWidth(uint32 chr) const;
+ virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
static BdfFont *loadFont(Common::SeekableReadStream &stream);
static bool cacheFontData(const BdfFont &font, const Common::String &filename);
static BdfFont *loadFromCache(Common::SeekableReadStream &stream);
private:
- int mapToIndex(byte ch) const;
+ int mapToIndex(uint32 ch) const;
const BdfFontData _data;
const DisposeAfterUse::Flag _dispose;
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index 2b1dca1eae..93f119f028 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -107,11 +107,11 @@ public:
virtual int getMaxCharWidth() const;
- virtual int getCharWidth(byte chr) const;
+ virtual int getCharWidth(uint32 chr) const;
- virtual int getKerningOffset(byte left, byte right) const;
+ virtual int getKerningOffset(uint32 left, uint32 right) const;
- virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+ virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
private:
bool _initialized;
FT_Face _face;
@@ -126,13 +126,14 @@ private:
Surface image;
int xOffset, yOffset;
int advance;
+ FT_UInt slot;
};
- bool cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr);
- typedef Common::HashMap<byte, Glyph> GlyphCache;
- GlyphCache _glyphs;
-
- FT_UInt _glyphSlots[256];
+ bool cacheGlyph(Glyph &glyph, uint32 chr) const;
+ typedef Common::HashMap<uint32, Glyph> GlyphCache;
+ mutable GlyphCache _glyphs;
+ bool _allowLateCaching;
+ void assureCached(uint32 chr) const;
bool _monochrome;
bool _hasKerning;
@@ -140,7 +141,7 @@ private:
TTFFont::TTFFont()
: _initialized(false), _face(), _ttfFile(0), _size(0), _width(0), _height(0), _ascent(0),
- _descent(0), _glyphs(), _glyphSlots(), _monochrome(false), _hasKerning(false) {
+ _descent(0), _glyphs(), _monochrome(false), _hasKerning(false), _allowLateCaching(false) {
}
TTFFont::~TTFFont() {
@@ -212,19 +213,26 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
_height = _ascent - _descent + 1;
if (!mapping) {
+ // Allow loading of all unicode characters.
+ _allowLateCaching = true;
+
// Load all ISO-8859-1 characters.
for (uint i = 0; i < 256; ++i) {
- if (!cacheGlyph(_glyphs[i], _glyphSlots[i], i))
- _glyphSlots[i] = 0;
+ if (!cacheGlyph(_glyphs[i], i)) {
+ _glyphs.erase(i);
+ }
}
} else {
+ // We have a fixed map of characters do not load more later.
+ _allowLateCaching = false;
+
for (uint i = 0; i < 256; ++i) {
const uint32 unicode = mapping[i] & 0x7FFFFFFF;
const bool isRequired = (mapping[i] & 0x80000000) != 0;
// Check whether loading an important glyph fails and error out if
// that is the case.
- if (!cacheGlyph(_glyphs[i], _glyphSlots[i], unicode)) {
- _glyphSlots[i] = 0;
+ if (!cacheGlyph(_glyphs[i], unicode)) {
+ _glyphs.erase(i);
if (isRequired)
return false;
}
@@ -243,7 +251,8 @@ int TTFFont::getMaxCharWidth() const {
return _width;
}
-int TTFFont::getCharWidth(byte chr) const {
+int TTFFont::getCharWidth(uint32 chr) const {
+ assureCached(chr);
GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
if (glyphEntry == _glyphs.end())
return 0;
@@ -251,12 +260,29 @@ int TTFFont::getCharWidth(byte chr) const {
return glyphEntry->_value.advance;
}
-int TTFFont::getKerningOffset(byte left, byte right) const {
+int TTFFont::getKerningOffset(uint32 left, uint32 right) const {
if (!_hasKerning)
return 0;
- FT_UInt leftGlyph = _glyphSlots[left];
- FT_UInt rightGlyph = _glyphSlots[right];
+ assureCached(left);
+ assureCached(right);
+
+ FT_UInt leftGlyph, rightGlyph;
+ GlyphCache::const_iterator glyphEntry;
+
+ glyphEntry = _glyphs.find(left);
+ if (glyphEntry != _glyphs.end()) {
+ leftGlyph = glyphEntry->_value.slot;
+ } else {
+ return 0;
+ }
+
+ glyphEntry = _glyphs.find(right);
+ if (glyphEntry != _glyphs.end()) {
+ rightGlyph = glyphEntry->_value.slot;
+ } else {
+ return 0;
+ }
if (!leftGlyph || !rightGlyph)
return 0;
@@ -304,7 +330,8 @@ void renderGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos, const i
} // End of anonymous namespace
-void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const {
+void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ assureCached(chr);
GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
if (glyphEntry == _glyphs.end())
return;
@@ -322,7 +349,7 @@ void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const
int w = glyph.image.w;
int h = glyph.image.h;
- const uint8 *srcPos = (const uint8 *)glyph.image.getBasePtr(0, 0);
+ const uint8 *srcPos = (const uint8 *)glyph.image.getPixels();
// Make sure we are not drawing outside the screen bounds
if (x < 0) {
@@ -376,11 +403,13 @@ void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const
}
}
-bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) {
- slot = FT_Get_Char_Index(_face, chr);
+bool TTFFont::cacheGlyph(Glyph &glyph, uint32 chr) const {
+ FT_UInt slot = FT_Get_Char_Index(_face, chr);
if (!slot)
return false;
+ glyph.slot = slot;
+
// We use the light target and render mode to improve the looks of the
// glyphs. It is most noticable in FreeSansBold.ttf, where otherwise the
// 't' glyph looks like it is cut off on the right side.
@@ -422,7 +451,7 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) {
srcPitch = -srcPitch;
}
- uint8 *dst = (uint8 *)glyph.image.getBasePtr(0, 0);
+ uint8 *dst = (uint8 *)glyph.image.getPixels();
memset(dst, 0, glyph.image.h * glyph.image.pitch);
switch (bitmap.pixel_mode) {
@@ -456,12 +485,24 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) {
default:
warning("TTFFont::cacheGlyph: Unsupported pixel mode %d", bitmap.pixel_mode);
+ glyph.image.free();
return false;
}
return true;
}
+void TTFFont::assureCached(uint32 chr) const {
+ if (!chr || !_allowLateCaching || _glyphs.contains(chr)) {
+ return;
+ }
+
+ Glyph newGlyph;
+ if (cacheGlyph(newGlyph, chr)) {
+ _glyphs[chr] = newGlyph;
+ }
+}
+
Font *loadTTFFont(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping) {
TTFFont *font = new TTFFont();
diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp
index 3bad92236d..c0ebab19ba 100644
--- a/graphics/fonts/winfont.cpp
+++ b/graphics/fonts/winfont.cpp
@@ -200,7 +200,7 @@ char WinFont::indexToCharacter(uint16 index) const {
return index + _firstChar;
}
-uint16 WinFont::characterToIndex(byte character) const {
+uint16 WinFont::characterToIndex(uint32 character) const {
// Go to the default character if we didn't find a mapping
if (character < _firstChar || character > _lastChar)
character = _defaultChar;
@@ -208,7 +208,7 @@ uint16 WinFont::characterToIndex(byte character) const {
return character - _firstChar;
}
-int WinFont::getCharWidth(byte chr) const {
+int WinFont::getCharWidth(uint32 chr) const {
return _glyphs[characterToIndex(chr)].charWidth;
}
@@ -324,7 +324,7 @@ bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
return true;
}
-void WinFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const {
+void WinFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
assert(dst);
assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
assert(_glyphs);
diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h
index 4382d7ed6b..2c7ba07b41 100644
--- a/graphics/fonts/winfont.h
+++ b/graphics/fonts/winfont.h
@@ -62,8 +62,8 @@ public:
// Font API
int getFontHeight() const { return _pixHeight; }
int getMaxCharWidth() const { return _maxWidth; }
- int getCharWidth(byte chr) const;
- void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
+ int getCharWidth(uint32 chr) const;
+ void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
private:
bool loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry);
@@ -72,7 +72,7 @@ private:
uint32 getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry);
bool loadFromFNT(Common::SeekableReadStream &stream);
char indexToCharacter(uint16 index) const;
- uint16 characterToIndex(byte character) const;
+ uint16 characterToIndex(uint32 character) const;
uint16 _pixHeight;
uint16 _maxWidth;
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index 88f3cc2077..c30fc3b6fd 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -42,8 +42,10 @@ uint16 quadBlockInterpolate(const uint8 *src, uint32 srcPitch) {
template<int bitFormat>
void createThumbnail_2(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
- assert(width % 2 == 0);
- assert(height % 2 == 0);
+ // Make sure the width and height is a multiple of 2.
+ width &= ~1;
+ height &= ~1;
+
for (int y = 0; y < height; y += 2) {
for (int x = 0; x < width; x += 2, dstPtr += 2) {
*((uint16 *)dstPtr) = quadBlockInterpolate<bitFormat>(src + 2 * x, srcPitch);
@@ -55,8 +57,10 @@ void createThumbnail_2(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32
template<int bitFormat>
void createThumbnail_4(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
- assert(width % 4 == 0);
- assert(height % 4 == 0);
+ // Make sure the width and height is a multiple of 4
+ width &= ~3;
+ height &= ~3;
+
for (int y = 0; y < height; y += 4) {
for (int x = 0; x < width; x += 4, dstPtr += 2) {
uint16 upleft = quadBlockInterpolate<bitFormat>(src + 2 * x, srcPitch);
@@ -71,17 +75,87 @@ void createThumbnail_4(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32
}
}
-static void createThumbnail(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
- // only 1/2 and 1/4 downscale supported
- if (width != 320 && width != 640)
- return;
+static void scaleThumbnail(Graphics::Surface &in, Graphics::Surface &out) {
+ while (in.w / out.w >= 4 || in.h / out.h >= 4) {
+ createThumbnail_4<565>((const uint8 *)in.getPixels(), in.pitch, (uint8 *)in.getPixels(), in.pitch, in.w, in.h);
+ in.w /= 4;
+ in.h /= 4;
+ }
+
+ while (in.w / out.w >= 2 || in.h / out.h >= 2) {
+ createThumbnail_2<565>((const uint8 *)in.getPixels(), in.pitch, (uint8 *)in.getPixels(), in.pitch, in.w, in.h);
+ in.w /= 2;
+ in.h /= 2;
+ }
+
+ if ((in.w == out.w && in.h < out.h) || (in.w < out.w && in.h == out.h)) {
+ // In this case we simply center the input surface in the output
+ uint8 *dst = (uint8 *)out.getBasePtr((out.w - in.w) / 2, (out.h - in.h) / 2);
+ const uint8 *src = (const uint8 *)in.getPixels();
- int downScaleMode = (width == 320) ? 2 : 4;
+ for (int y = 0; y < in.h; ++y) {
+ memcpy(dst, src, in.w * in.format.bytesPerPixel);
+ src += in.pitch;
+ dst += out.pitch;
+ }
+ } else {
+ // Assure the aspect of the scaled image still matches the original.
+ int targetWidth = out.w, targetHeight = out.h;
- if (downScaleMode == 2) {
- createThumbnail_2<565>(src, srcPitch, dstPtr, dstPitch, width, height);
- } else if (downScaleMode == 4) {
- createThumbnail_4<565>(src, srcPitch, dstPtr, dstPitch, width, height);
+ const float inputAspect = (float)in.w / in.h;
+ const float outputAspect = (float)out.w / out.h;
+
+ if (inputAspect > outputAspect) {
+ targetHeight = int(targetWidth / inputAspect);
+ } else if (inputAspect < outputAspect) {
+ targetWidth = int(targetHeight * inputAspect);
+ }
+
+ // Make sure we are still in the bounds of the output
+ assert(targetWidth <= out.w);
+ assert(targetHeight <= out.h);
+
+ // Center the image on the output surface
+ byte *dst = (byte *)out.getBasePtr((out.w - targetWidth) / 2, (out.h - targetHeight) / 2);
+ const uint dstLineIncrease = out.pitch - targetWidth * out.format.bytesPerPixel;
+
+ const float scaleFactorX = (float)targetWidth / in.w;
+ const float scaleFactorY = (float)targetHeight / in.h;
+
+ for (int y = 0; y < targetHeight; ++y) {
+ const float yFrac = (y / scaleFactorY);
+ const int y1 = (int)yFrac;
+ const int y2 = (y1 + 1 < in.h) ? (y1 + 1) : (in.h - 1);
+
+ for (int x = 0; x < targetWidth; ++x) {
+ const float xFrac = (x / scaleFactorX);
+ const int x1 = (int)xFrac;
+ const int x2 = (x1 + 1 < in.w) ? (x1 + 1) : (in.w - 1);
+
+ // Look up colors at the points
+ uint8 p1R, p1G, p1B;
+ Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x1, y1)), p1R, p1G, p1B);
+ uint8 p2R, p2G, p2B;
+ Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x2, y1)), p2R, p2G, p2B);
+ uint8 p3R, p3G, p3B;
+ Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x1, y2)), p3R, p3G, p3B);
+ uint8 p4R, p4G, p4B;
+ Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x2, y2)), p4R, p4G, p4B);
+
+ const float xDiff = xFrac - x1;
+ const float yDiff = yFrac - y1;
+
+ uint8 pR = (uint8)((1 - yDiff) * ((1 - xDiff) * p1R + xDiff * p2R) + yDiff * ((1 - xDiff) * p3R + xDiff * p4R));
+ uint8 pG = (uint8)((1 - yDiff) * ((1 - xDiff) * p1G + xDiff * p2G) + yDiff * ((1 - xDiff) * p3G + xDiff * p4G));
+ uint8 pB = (uint8)((1 - yDiff) * ((1 - xDiff) * p1B + xDiff * p2B) + yDiff * ((1 - xDiff) * p3B + xDiff * p4B));
+
+ WRITE_UINT16(dst, Graphics::RGBToColor<Graphics::ColorMasks<565> >(pR, pG, pB));
+ dst += 2;
+ }
+
+ // Move to the next line
+ dst = (byte *)dst + dstLineIncrease;
+ }
}
}
@@ -90,7 +164,7 @@ static void createThumbnail(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, ui
* Copies the current screen contents to a new surface, using RGB565 format.
* WARNING: surf->free() must be called by the user to avoid leaking.
*
- * @param surf the surface to store the data in it
+ * @param surf the surface to store the data in it
*/
static bool grabScreen565(Graphics::Surface *surf) {
Graphics::Surface *screen = g_system->lockScreen();
@@ -98,7 +172,7 @@ static bool grabScreen565(Graphics::Surface *surf) {
return false;
assert(screen->format.bytesPerPixel == 1 || screen->format.bytesPerPixel == 2);
- assert(screen->pixels != 0);
+ assert(screen->getPixels() != 0);
Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
@@ -116,15 +190,16 @@ static bool grabScreen565(Graphics::Surface *surf) {
byte r = 0, g = 0, b = 0;
if (screenFormat.bytesPerPixel == 1) {
- r = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3];
- g = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3 + 1];
- b = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3 + 2];
+ uint8 pixel = *(uint8 *)screen->getBasePtr(x, y);
+ r = palette[pixel * 3 + 0];
+ g = palette[pixel * 3 + 1];
+ b = palette[pixel * 3 + 2];
} else if (screenFormat.bytesPerPixel == 2) {
uint16 col = READ_UINT16(screen->getBasePtr(x, y));
screenFormat.colorToRGB(col, r, g, b);
}
- ((uint16 *)surf->pixels)[y * surf->w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
+ *((uint16 *)surf->getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
}
}
@@ -135,78 +210,20 @@ static bool grabScreen565(Graphics::Surface *surf) {
}
static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
- uint16 width = in.w;
- uint16 inHeight = in.h;
-
- if (width < 320) {
- // Special case to handle MM NES (uses a screen width of 256)
- width = 320;
-
- // center MM NES screen
- Graphics::Surface newscreen;
- newscreen.create(width, in.h, in.format);
-
- uint8 *dst = (uint8 *)newscreen.getBasePtr((320 - in.w) / 2, 0);
- const uint8 *src = (const uint8 *)in.getBasePtr(0, 0);
- uint16 height = in.h;
-
- while (height--) {
- memcpy(dst, src, in.pitch);
- dst += newscreen.pitch;
- src += in.pitch;
- }
-
- in.free();
- in = newscreen;
- } else if (width == 720) {
- // Special case to handle Hercules mode
- //
- // NOTE: This code is pretty SCUMM specific.
- // For other games this code might cut off
- // not only the menu, but also other graphics.
- width = 640;
- inHeight = 400;
-
- // cut off menu and so on..
- Graphics::Surface newscreen;
- newscreen.create(width, 400, in.format);
-
- uint8 *dst = (uint8 *)newscreen.getBasePtr(0, (400 - 240) / 2);
- const uint8 *src = (const uint8 *)in.getBasePtr(41, 28);
-
- for (int y = 0; y < 240; ++y) {
- memcpy(dst, src, 640 * in.format.bytesPerPixel);
- dst += newscreen.pitch;
- src += in.pitch;
- }
-
- in.free();
- in = newscreen;
- } else if (width == 640 && inHeight == 440) {
- // Special case to handle KQ6 Windows: resize the screen to 640x480,
- // adding a black band in the bottom.
- inHeight = 480;
-
- Graphics::Surface newscreen;
- newscreen.create(width, 480, in.format);
-
- memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.format.bytesPerPixel);
-
- in.free();
- in = newscreen;
+ int height;
+ if ((in.w == 320 && in.h == 200) || (in.w == 640 && in.h == 400)) {
+ height = kThumbnailHeight1;
+ } else {
+ height = kThumbnailHeight2;
}
- uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
-
- out.create(kThumbnailWidth, newHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight);
-
+ out.create(kThumbnailWidth, height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ scaleThumbnail(in, out);
in.free();
-
return true;
}
-bool createThumbnailFromScreen(Graphics::Surface* surf) {
+bool createThumbnailFromScreen(Graphics::Surface *surf) {
assert(surf);
Graphics::Surface screen;
@@ -230,9 +247,37 @@ bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h,
g = palette[pixels[y * w + x] * 3 + 1];
b = palette[pixels[y * w + x] * 3 + 2];
- ((uint16 *)screen.pixels)[y * screen.w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
+ *((uint16 *)screen.getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
}
}
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.getBasePtr(x, y)) = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b);
+ }
+ }
+ g_system->unlockScreen();
+ return true;
+ }
+}
+} // End of namespace Graphics
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index 41ae8dcebb..777c1058fb 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -82,9 +82,79 @@ void Surface::free() {
format = PixelFormat();
}
+void Surface::init(uint16 width, uint16 height, uint16 newPitch, void *newPixels, const PixelFormat &f) {
+ w = width;
+ h = height;
+ pitch = newPitch;
+ pixels = newPixels;
+ format = f;
+}
+
void Surface::copyFrom(const Surface &surf) {
create(surf.w, surf.h, surf.format);
- memcpy(pixels, surf.pixels, h * pitch);
+ if (surf.pitch == pitch) {
+ memcpy(pixels, surf.pixels, h * pitch);
+ } else {
+ const byte *src = (const byte *)surf.pixels;
+ byte *dst = (byte *)pixels;
+ for (int y = h; y > 0; --y) {
+ memcpy(dst, src, w * format.bytesPerPixel);
+ src += surf.pitch;
+ dst += pitch;
+ }
+ }
+}
+
+Surface Surface::getSubArea(const Common::Rect &area) {
+ Common::Rect effectiveArea(area);
+ effectiveArea.clip(w, h);
+
+ Surface subSurface;
+ subSurface.w = effectiveArea.width();
+ subSurface.h = effectiveArea.height();
+ subSurface.pitch = pitch;
+ subSurface.pixels = getBasePtr(area.left, area.top);
+ subSurface.format = format;
+ return subSurface;
+}
+
+const Surface Surface::getSubArea(const Common::Rect &area) const {
+ Common::Rect effectiveArea(area);
+ effectiveArea.clip(w, h);
+
+ Surface subSurface;
+ subSurface.w = effectiveArea.width();
+ subSurface.h = effectiveArea.height();
+ subSurface.pitch = pitch;
+ // We need to cast the const away here because a Surface always has a
+ // pointer to modifiable pixel data.
+ subSurface.pixels = const_cast<void *>(getBasePtr(area.left, area.top));
+ subSurface.format = format;
+ return subSurface;
+}
+
+void Surface::copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
+ assert(buffer);
+
+ assert(destX >= 0 && destX < w);
+ assert(destY >= 0 && destY < h);
+ assert(height > 0 && destY + height <= h);
+ assert(width > 0 && destX + width <= w);
+
+ // Copy buffer data to internal buffer
+ const byte *src = (const byte *)buffer;
+ byte *dst = (byte *)getBasePtr(destX, destY);
+ for (int i = 0; i < height; i++) {
+ memcpy(dst, src, width * format.bytesPerPixel);
+ src += srcPitch;
+ dst += pitch;
+ }
+}
+
+void Surface::copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect) {
+ assert(srcSurface.format == format);
+
+ copyRectToSurface(srcSurface.getBasePtr(subRect.left, subRect.top), srcSurface.pitch, destX, destY, subRect.width(), subRect.height());
}
void Surface::hLine(int x, int y, int x2, uint32 color) {
diff --git a/graphics/surface.h b/graphics/surface.h
index 6c9e464657..f1b2aa64ab 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -61,11 +61,13 @@ struct Surface {
*/
uint16 pitch;
+protected:
/**
* The surface's pixel data.
*/
void *pixels;
+public:
/**
* The pixel format of the surface.
*/
@@ -78,6 +80,33 @@ struct Surface {
}
/**
+ * Return a pointer to the pixel data.
+ *
+ * @return Pointer to the pixel data.
+ */
+ inline const void *getPixels() const {
+ return pixels;
+ }
+
+ /**
+ * Return a pointer to the pixel data.
+ *
+ * @return Pointer to the pixel data.
+ */
+ inline void *getPixels() {
+ return pixels;
+ }
+
+ /**
+ * Sets the pixel data.
+ *
+ * Note that this is a simply a setter. Be careful what you are doing!
+ *
+ * @param newPixels The new pixel data.
+ */
+ void setPixels(void *newPixels) { pixels = newPixels; }
+
+ /**
* Return a pointer to the pixel at the specified point.
*
* @param x The x coordinate of the pixel.
@@ -122,6 +151,20 @@ struct Surface {
void free();
/**
+ * Set up the Surface with user specified data.
+ *
+ * Note that this simply sets the 'internal' attributes of the Surface. It
+ * will not take care of freeing old data via free or similar!
+ *
+ * @param width Width of the pixel data.
+ * @param height Height of the pixel data.
+ * @param pitch The pitch of the pixel data.
+ * @param pixels The pixel data itself.
+ * @param format The pixel format of the pixel data.
+ */
+ void init(uint16 width, uint16 height, uint16 pitch, void *pixels, const PixelFormat &format);
+
+ /**
* Copy the data from another Surface.
*
* Note that this calls free on the current surface, to assure it being
@@ -135,10 +178,66 @@ struct Surface {
void copyFrom(const Surface &surf);
/**
+ * Creates a Surface which represents a sub-area of this Surface object.
+ *
+ * The pixel (0, 0) of the returned Surface will be the same as Pixel
+ * (area.x, area.y) of this Surface. Changes to any of the Surface objects
+ * will change the shared pixel data.
+ *
+ * Note that the Surface returned is only valid as long as this Surface
+ * object is still alive (i.e. its pixel data is not destroyed or
+ * reallocated). Do *never* try to free the returned Surface.
+ *
+ * @param area The area which should be represented. Note that the area
+ * will get clipped in case it does not fit!
+ */
+ Surface getSubArea(const Common::Rect &area);
+
+ /**
+ * Creates a Surface which represents a sub-area of this Surface object.
+ *
+ * The pixel (0, 0) of the returned Surface will be the same as Pixel
+ * (area.x, area.y) of this Surface.
+ *
+ * Note that the Surface returned is only valid as long as this Surface
+ * object is still alive (i.e. its pixel data is not destroyed or
+ * reallocated). Do *never* try to free the returned Surface.
+ *
+ * @param area The area which should be represented. Note that the area
+ * will get clipped in case it does not fit!
+ */
+ const Surface getSubArea(const Common::Rect &area) const;
+
+ /**
+ * Copies a bitmap to the Surface internal buffer. The pixel format
+ * of buffer must match the pixel format of the Surface.
+ *
+ * @param buffer The buffer containing the graphics data source
+ * @param pitch The pitch of the buffer (number of bytes in a scanline)
+ * @param destX The x coordinate of the destination rectangle
+ * @param destY The y coordinate of the destination rectangle
+ * @param width The width of the destination rectangle
+ * @param height The height of the destination rectangle
+ */
+ void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height);
+ /**
+ * Copies a bitmap to the Surface internal buffer. The pixel format
+ * of buffer must match the pixel format of the Surface.
+ *
+ * @param srcSurface The source of the bitmap data
+ * @param destX The x coordinate of the destination rectangle
+ * @param destY The y coordinate of the destination rectangle
+ * @param subRect The subRect of surface to be blitted
+ * @return
+ */
+ void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect);
+
+ /**
* Convert the data to another pixel format.
*
* This works in-place. This means it will not create an additional buffer
- * for the conversion process. The value of pixels might change though.
+ * for the conversion process. The value of 'pixels' might change though
+ * (that means it might realloc the pixel data).
*
* Note that you should only use this, when you created the Surface data via
* create! Otherwise this function has undefined behavior.
@@ -235,7 +334,9 @@ struct Surface {
*/
struct SharedPtrSurfaceDeleter {
void operator()(Surface *ptr) {
- ptr->free();
+ if (ptr) {
+ ptr->free();
+ }
delete ptr;
}
};
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.cpp b/graphics/yuv_to_rgb.cpp
index 6043315a13..2a485fa664 100644
--- a/graphics/yuv_to_rgb.cpp
+++ b/graphics/yuv_to_rgb.cpp
@@ -229,7 +229,7 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
// Sanity checks
- assert(dst && dst->pixels);
+ assert(dst && dst->getPixels());
assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
assert(ySrc && uSrc && vSrc);
@@ -237,9 +237,9 @@ void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::Lumina
// Use a templated function to avoid an if check on every pixel
if (dst->format.bytesPerPixel == 2)
- convertYUV444ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV444ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV444ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV444ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
template<typename PixelInt>
@@ -283,7 +283,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
void YUVToRGBManager::convert420(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
// Sanity checks
- assert(dst && dst->pixels);
+ assert(dst && dst->getPixels());
assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
assert(ySrc && uSrc && vSrc);
assert((yWidth & 1) == 0);
@@ -293,9 +293,9 @@ void YUVToRGBManager::convert420(Graphics::Surface *dst, YUVToRGBManager::Lumina
// Use a templated function to avoid an if check on every pixel
if (dst->format.bytesPerPixel == 2)
- convertYUV420ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV420ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV420ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV420ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
#define READ_QUAD(ptr, prefix) \
@@ -368,7 +368,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
void YUVToRGBManager::convert410(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
// Sanity checks
- assert(dst && dst->pixels);
+ assert(dst && dst->getPixels());
assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
assert(ySrc && uSrc && vSrc);
assert((yWidth & 3) == 0);
@@ -378,9 +378,9 @@ void YUVToRGBManager::convert410(Graphics::Surface *dst, YUVToRGBManager::Lumina
// Use a templated function to avoid an if check on every pixel
if (dst->format.bytesPerPixel == 2)
- convertYUV410ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV410ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV410ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV410ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
} // End of namespace Graphics
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..71f66911e9
--- /dev/null
+++ b/gui/EventRecorder.cpp
@@ -0,0 +1,680 @@
+/* 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(const Common::ConfigManager::Domain *domain) {
+ for (Common::ConfigManager::Domain::const_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::const_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::const_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);
+ }
+
+ 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.getPixels(), 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..b2a549ece8
--- /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(const 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..9fe482ddcc 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;
@@ -114,15 +122,16 @@ protected:
class ThemeItemTextData : public ThemeItem {
public:
- ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::String &text,
- Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
+ ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::Rect &textDrawableArea,
+ const Common::String &text, Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
bool ellipsis, bool restoreBg, int deltaX) :
ThemeItem(engine, area), _data(data), _color(color), _text(text), _alignH(alignH), _alignV(alignV),
- _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {}
+ _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX), _textDrawableArea(textDrawableArea) {}
void drawSelf(bool draw, bool restore);
protected:
+ Common::Rect _textDrawableArea;
const TextDrawData *_data;
const TextColorData *_color;
Common::String _text;
@@ -238,7 +247,7 @@ void ThemeItemTextData::drawSelf(bool draw, bool restore) {
if (draw) {
_engine->renderer()->setFgColor(_color->r, _color->g, _color->b);
- _engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis);
+ _engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis, _textDrawableArea);
}
_engine->addDirtyRect(_area);
@@ -335,9 +344,9 @@ ThemeEngine::~ThemeEngine() {
*********************************************************/
const ThemeEngine::Renderer ThemeEngine::_rendererModes[] = {
{ _s("Disabled GFX"), _sc("Disabled GFX", "lowres"), "none", kGfxDisabled },
- { _s("Standard Renderer (16bpp)"), _s("Standard (16bpp)"), "normal_16bpp", kGfxStandard16bit },
+ { _s("Standard Renderer"), _s("Standard"), "normal", kGfxStandard },
#ifndef DISABLE_FANCY_THEMES
- { _s("Antialiased Renderer (16bpp)"), _s("Antialiased (16bpp)"), "aa_16bpp", kGfxAntialias16bit }
+ { _s("Antialiased Renderer"), _s("Antialiased"), "antialias", kGfxAntialias }
#endif
};
@@ -345,9 +354,9 @@ const uint ThemeEngine::_rendererModesSize = ARRAYSIZE(ThemeEngine::_rendererMod
const ThemeEngine::GraphicsMode ThemeEngine::_defaultRendererMode =
#ifndef DISABLE_FANCY_THEMES
- ThemeEngine::kGfxAntialias16bit;
+ ThemeEngine::kGfxAntialias;
#else
- ThemeEngine::kGfxStandard16bit;
+ ThemeEngine::kGfxStandard;
#endif
ThemeEngine::GraphicsMode ThemeEngine::findMode(const Common::String &cfg) {
@@ -381,7 +390,7 @@ bool ThemeEngine::init() {
_overlayFormat = _system->getOverlayFormat();
setGraphicsMode(_graphicsMode);
- if (_screen.pixels && _backBuffer.pixels) {
+ if (_screen.getPixels() && _backBuffer.getPixels()) {
_initOk = true;
}
@@ -431,7 +440,7 @@ bool ThemeEngine::init() {
void ThemeEngine::clearAll() {
if (_initOk) {
_system->clearOverlay();
- _system->grabOverlay(_screen.pixels, _screen.pitch);
+ _system->grabOverlay(_screen.getPixels(), _screen.pitch);
}
}
@@ -465,11 +474,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,23 +487,25 @@ void ThemeEngine::disable() {
_system->hideOverlay();
- if (_useCursor) {
- CursorMan.popCursorPalette();
- CursorMan.popCursor();
- }
+ hideCursor();
+
_enabled = false;
}
void ThemeEngine::setGraphicsMode(GraphicsMode mode) {
switch (mode) {
- case kGfxStandard16bit:
+ case kGfxStandard:
#ifndef DISABLE_FANCY_THEMES
- case kGfxAntialias16bit:
+ case kGfxAntialias:
#endif
- _bytesPerPixel = sizeof(uint16);
- break;
-
+ if (g_system->getOverlayFormat().bytesPerPixel == 4) {
+ _bytesPerPixel = sizeof(uint32);
+ break;
+ } else if (g_system->getOverlayFormat().bytesPerPixel == 2) {
+ _bytesPerPixel = sizeof(uint16);
+ break;
+ }
default:
error("Invalid graphics mode");
}
@@ -515,6 +522,12 @@ void ThemeEngine::setGraphicsMode(GraphicsMode mode) {
delete _vectorRenderer;
_vectorRenderer = Graphics::createRenderer(mode);
_vectorRenderer->setSurface(&_screen);
+
+ // Since we reinitialized our screen surfaces we know nothing has been
+ // drawn so far. Sometimes we still end up with dirty screen bits in the
+ // list. Clearing it avoids invalid overlay writes when the backend
+ // resizes the overlay.
+ _dirtyScreen.clear();
}
void WidgetDrawData::calcBackgroundOffset() {
@@ -830,7 +843,7 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic,
}
void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
- bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) {
+ bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) {
if (_texts[type] == 0)
return;
@@ -838,7 +851,7 @@ void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect
Common::Rect area = r;
area.clip(_screen.w, _screen.h);
- ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, text, alignH, alignV, ellipsis, restoreBg, deltax);
+ ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, drawableTextArea, text, alignH, alignV, ellipsis, restoreBg, deltax);
if (_buffering) {
_screenQueue.push_back(q);
@@ -1109,7 +1122,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
}
}
-void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore) {
+void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
if (!ready())
return;
@@ -1179,7 +1192,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
break;
}
- queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax);
+ queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
}
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
@@ -1217,7 +1230,7 @@ void ThemeEngine::updateScreen(bool render) {
}
_vectorRenderer->setSurface(&_screen);
- memcpy(_screen.getBasePtr(0, 0), _backBuffer.getBasePtr(0, 0), _screen.pitch * _screen.h);
+ memcpy(_screen.getPixels(), _backBuffer.getPixels(), _screen.pitch * _screen.h);
_bufferQueue.clear();
}
@@ -1285,7 +1298,7 @@ void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) {
addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h));
}
- memcpy(_backBuffer.getBasePtr(0, 0), _screen.getBasePtr(0, 0), _screen.pitch * _screen.h);
+ memcpy(_backBuffer.getPixels(), _screen.getPixels(), _screen.pitch * _screen.h);
_vectorRenderer->setSurface(&_screen);
}
@@ -1318,44 +1331,52 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
memset(_cursor, 0xFF, sizeof(byte) * _cursorWidth * _cursorHeight);
// the transparent color is 0xFF00FF
- const int colTransparent = _overlayFormat.RGBToColor(0xFF, 0, 0xFF);
+ const uint32 colTransparent = _overlayFormat.RGBToColor(0xFF, 0, 0xFF);
// Now, scan the bitmap. We have to convert it from 16 bit color mode
// to 8 bit mode, and have to create a suitable palette on the fly.
uint colorsFound = 0;
Common::HashMap<int, int> colorToIndex;
- const OverlayColor *src = (const OverlayColor *)cursor->pixels;
+ const byte *src = (const byte *)cursor->getPixels();
for (uint y = 0; y < _cursorHeight; ++y) {
for (uint x = 0; x < _cursorWidth; ++x) {
+ uint32 color = colTransparent;
byte r, g, b;
+ if (cursor->format.bytesPerPixel == 2) {
+ color = READ_UINT16(src);
+ } else if (cursor->format.bytesPerPixel == 4) {
+ color = READ_UINT32(src);
+ }
+
+ src += cursor->format.bytesPerPixel;
+
// Skip transparency
- if (src[x] == colTransparent)
+ if (color == colTransparent)
continue;
- _overlayFormat.colorToRGB(src[x], r, g, b);
+ cursor->format.colorToRGB(color, r, g, b);
const int col = (r << 16) | (g << 8) | b;
// If there is no entry yet for this color in the palette: Add one
if (!colorToIndex.contains(col)) {
+ if (colorsFound >= MAX_CURS_COLORS) {
+ warning("Cursor contains too many colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS);
+ return false;
+ }
+
const int index = colorsFound++;
colorToIndex[col] = index;
_cursorPal[index * 3 + 0] = r;
_cursorPal[index * 3 + 1] = g;
_cursorPal[index * 3 + 2] = b;
-
- if (colorsFound > MAX_CURS_COLORS) {
- warning("Cursor contains too many colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS);
- return false;
- }
}
// Copy pixel from the 16 bit source surface to the 8bit target surface
const int index = colorToIndex[col];
_cursor[y * _cursorWidth + x] = index;
}
- src += _cursorWidth;
}
_useCursor = true;
@@ -1787,5 +1808,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..4dffb13e71 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -29,6 +29,7 @@
#include "common/hashmap.h"
#include "common/list.h"
#include "common/str.h"
+#include "common/rect.h"
#include "graphics/surface.h"
#include "graphics/font.h"
@@ -39,10 +40,6 @@
class OSystem;
-namespace Common {
-struct Rect;
-}
-
namespace Graphics {
struct DrawStep;
class VectorRenderer;
@@ -234,6 +231,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.
@@ -242,8 +247,8 @@ public:
*/
enum GraphicsMode {
kGfxDisabled = 0, ///< No GFX
- kGfxStandard16bit, ///< 2BPP with the standard (aliased) renderer.
- kGfxAntialias16bit ///< 2BPP with the optimized AA renderer.
+ kGfxStandard, ///< Standard (aliased) renderer.
+ kGfxAntialias ///< Optimized AA renderer.
};
/** Constant value to expand dirty rectangles, to make sure they are fully copied */
@@ -275,8 +280,13 @@ public:
void refresh();
void enable();
+
+ void showCursor();
+ void hideCursor();
+
void disable();
+
/**
* Query the set up pixel format.
*/
@@ -363,7 +373,7 @@ public:
void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
- void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true);
+ void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
@@ -575,7 +585,7 @@ protected:
*/
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false);
void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
- bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0);
+ bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
/**
diff --git a/gui/about.cpp b/gui/about.cpp
index 088971f273..3bb1934e28 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;
@@ -180,9 +180,10 @@ void AboutDialog::close() {
}
void AboutDialog::drawDialog() {
-// g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h));
Dialog::drawDialog();
+ setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h));
+
// Draw text
// TODO: Add a "fade" effect for the top/bottom text lines
// TODO: Maybe prerender all of the text into another surface,
@@ -239,8 +240,8 @@ void AboutDialog::drawDialog() {
while (*str && *str == ' ')
str++;
- if (*str && y > _y && y + g_gui.theme()->getFontHeight() < _y + _h)
- g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false);
+ if (*str)
+ g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
y += _lineHeight;
}
}
diff --git a/gui/browser.h b/gui/browser.h
index 7c098617bb..b82fe516f9 100644
--- a/gui/browser.h
+++ b/gui/browser.h
@@ -51,6 +51,7 @@ protected:
#ifdef MACOSX
const void *_titleRef;
const void *_chooseRef;
+ const void *_hiddenFilesRef;
#else
ListWidget *_fileList;
StaticTextWidget *_currentPath;
diff --git a/gui/browser_osx.mm b/gui/browser_osx.mm
index ecd60915f8..642718df94 100644
--- a/gui/browser_osx.mm
+++ b/gui/browser_osx.mm
@@ -30,10 +30,55 @@
#include "common/algorithm.h"
#include "common/translation.h"
+#include <AppKit/NSNibDeclarations.h>
#include <AppKit/NSOpenPanel.h>
+#include <AppKit/NSButton.h>
#include <Foundation/NSString.h>
#include <Foundation/NSURL.h>
+@interface ShowHiddenFilesController : NSObject {
+ NSOpenPanel* _panel;
+}
+
+- (id) init;
+- (void) dealloc;
+- (void) setOpenPanel : (NSOpenPanel*) panel;
+- (IBAction) showHiddenFiles : (id) sender;
+
+@end
+
+@implementation ShowHiddenFilesController
+
+- (id) init {
+ self = [super init];
+ _panel = 0;
+
+ return self;
+}
+
+- (void) dealloc {
+ [_panel release];
+ [super dealloc];
+}
+
+- (void) setOpenPanel : (NSOpenPanel*) panel {
+ _panel = panel;
+ [_panel retain];
+}
+
+
+- (IBAction) showHiddenFiles : (id) sender {
+ if ([sender state] == NSOnState) {
+ [_panel setShowsHiddenFiles: YES];
+ ConfMan.setBool("gui_browser_show_hidden", true, Common::ConfigManager::kApplicationDomain);
+ } else {
+ [_panel setShowsHiddenFiles: NO];
+ ConfMan.setBool("gui_browser_show_hidden", false, Common::ConfigManager::kApplicationDomain);
+ }
+}
+
+@end
+
namespace GUI {
BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
@@ -56,11 +101,13 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
// Convert button text to NSString
_chooseRef = CFStringCreateWithCString(0, _("Choose"), stringEncoding);
+ _hiddenFilesRef = CFStringCreateWithCString(0, _("Show hidden files"), stringEncoding);
}
BrowserDialog::~BrowserDialog() {
CFRelease(_titleRef);
CFRelease(_chooseRef);
+ CFRelease(_hiddenFilesRef);
}
int BrowserDialog::runModal() {
@@ -82,6 +129,29 @@ int BrowserDialog::runModal() {
[panel setCanChooseDirectories:_isDirBrowser];
[panel setTitle:(NSString *)_titleRef];
[panel setPrompt:(NSString *)_chooseRef];
+
+ NSButton *showHiddenFilesButton = 0;
+ ShowHiddenFilesController *showHiddenFilesController = 0;
+ if ([panel respondsToSelector:@selector(setShowsHiddenFiles:)]) {
+ showHiddenFilesButton = [[NSButton alloc] init];
+ [showHiddenFilesButton setButtonType:NSSwitchButton];
+ [showHiddenFilesButton setTitle:(NSString *)_hiddenFilesRef];
+ [showHiddenFilesButton sizeToFit];
+ if (ConfMan.getBool("gui_browser_show_hidden", Common::ConfigManager::kApplicationDomain)) {
+ [showHiddenFilesButton setState:NSOnState];
+ [panel setShowsHiddenFiles: YES];
+ } else {
+ [showHiddenFilesButton setState:NSOffState];
+ [panel setShowsHiddenFiles: NO];
+ }
+ [panel setAccessoryView:showHiddenFilesButton];
+
+ showHiddenFilesController = [[ShowHiddenFilesController alloc] init];
+ [showHiddenFilesController setOpenPanel:panel];
+ [showHiddenFilesButton setTarget:showHiddenFilesController];
+ [showHiddenFilesButton setAction:@selector(showHiddenFiles:)];
+ }
+
if ([panel runModal] == NSOKButton) {
NSURL *url = [panel URL];
if ([url isFileURL]) {
@@ -91,6 +161,9 @@ int BrowserDialog::runModal() {
}
}
+ [showHiddenFilesButton release];
+ [showHiddenFilesController release];
+
// If we were in fullscreen mode, switch back
if (wasFullscreen) {
g_system->beginGFXTransaction();
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/console.cpp b/gui/console.cpp
index 49e2fccd98..7e88b6dfb5 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -82,8 +82,6 @@ ConsoleDialog::ConsoleDialog(float widthPercent, float heightPercent)
_historyIndex = 0;
_historyLine = 0;
_historySize = 0;
- for (int i = 0; i < kHistorySize; i++)
- _history[i][0] = '\0';
// Display greetings & prompt
print(gScummVMFullVersion);
@@ -274,24 +272,19 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
if (len > 0) {
- // We have to allocate the string buffer with new, since VC++ sadly does not
- // comply to the C++ standard, so we can't use a dynamic sized stack array.
- char *str = new char[len + 1];
+ Common::String str;
// Copy the user input to str
for (i = 0; i < len; i++)
- str[i] = buffer(_promptStartPos + i);
- str[len] = '\0';
+ str.insertChar(buffer(_promptStartPos + i), i);
// Add the input to the history
addToHistory(str);
// Pass it to the input callback, if any
if (_callbackProc)
- keepRunning = (*_callbackProc)(this, str, _callbackRefCon);
+ keepRunning = (*_callbackProc)(this, str.c_str(), _callbackRefCon);
- // Get rid of the string buffer
- delete[] str;
}
print(PROMPT);
@@ -575,8 +568,8 @@ void ConsoleDialog::killLastWord() {
}
}
-void ConsoleDialog::addToHistory(const char *str) {
- strcpy(_history[_historyIndex], str);
+void ConsoleDialog::addToHistory(const Common::String &str) {
+ _history[_historyIndex] = str;
_historyIndex = (_historyIndex + 1) % kHistorySize;
_historyLine = 0;
if (_historySize < kHistorySize)
@@ -590,8 +583,7 @@ void ConsoleDialog::historyScroll(int direction) {
if (_historyLine == 0 && direction > 0) {
int i;
for (i = 0; i < _promptEndPos - _promptStartPos; i++)
- _history[_historyIndex][i] = buffer(_promptStartPos + i);
- _history[_historyIndex][i] = '\0';
+ _history[_historyIndex].insertChar(buffer(_promptStartPos + i), i);
}
// Advance to the next line in the history
@@ -617,7 +609,8 @@ void ConsoleDialog::historyScroll(int direction) {
idx = (_historyIndex - _historyLine + _historySize) % _historySize;
else
idx = _historyIndex;
- for (int i = 0; i < kLineBufferSize && _history[idx][i] != '\0'; i++)
+ int length = _history[idx].size();
+ for (int i = 0; i < length; i++)
printCharIntern(_history[idx][i]);
_promptEndPos = _currentPos;
diff --git a/gui/console.h b/gui/console.h
index 50a00a1ad1..194bfd6fc0 100644
--- a/gui/console.h
+++ b/gui/console.h
@@ -23,6 +23,7 @@
#define CONSOLE_DIALOG_H
#include "gui/dialog.h"
+#include "common/str.h"
namespace GUI {
@@ -69,7 +70,6 @@ protected:
enum {
kBufferSize = 32768,
kCharsPerLine = 128,
- kLineBufferSize = 256,
kHistorySize = 20
};
@@ -112,7 +112,7 @@ protected:
CompletionCallbackProc _completionCallbackProc;
void *_completionCallbackRefCon;
- char _history[kHistorySize][kLineBufferSize];
+ Common::String _history[kHistorySize];
int _historySize;
int _historyIndex;
int _historyLine;
@@ -184,7 +184,7 @@ protected:
void killLastWord();
// History
- void addToHistory(const char *str);
+ void addToHistory(const Common::String &str);
void historyScroll(int direction);
};
diff --git a/gui/credits.h b/gui/credits.h
index 81d46b2b73..a14622e1b1 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -77,6 +77,12 @@ static const char *credits[] = {
"C0""Ludvig Strigeus",
"C2""(retired)",
"",
+"C1""AVALANCHE",
+"A0""Peter Bozso",
+"C0""Peter Bozs\363",
+"A0""Arnaud Boutonne",
+"C0""Arnaud Boutonn\351",
+"",
"C1""CGE",
"A0""Arnaud Boutonne",
"C0""Arnaud Boutonn\351",
@@ -170,6 +176,15 @@ static const char *credits[] = {
"C0""Eugene Sandulenko",
"C0""David Turner",
"",
+"C1""Mortevielle",
+"A0""Arnaud Boutonne",
+"C0""Arnaud Boutonn\351",
+"C0""Paul Gilbert",
+"",
+"C1""Neverhood",
+"C0""Benjamin Haisch",
+"C0""Filippos Karapetis",
+"",
"C1""Parallaction",
"C0""peres",
"",
@@ -288,15 +303,15 @@ static const char *credits[] = {
"A0""Einar Johan T. Somaaen",
"C0""Einar Johan T. S\370m\345en",
"",
+"C1""ZVision",
+"C0""Adrian Astley",
+"",
"",
"C1""Backend Teams",
"C1""Android",
"C0""Andre Heider",
"C0""Angus Lees",
"",
-"C1""BADA",
-"C0""Chris Warren-Smith",
-"",
"C1""Dreamcast",
"C0""Marcus Comstedt",
"",
@@ -352,6 +367,9 @@ static const char *credits[] = {
"C0""Jurgen Braam",
"C0""Lars Persson",
"",
+"C1""Tizen / BADA",
+"C0""Chris Warren-Smith",
+"",
"C1""WebOS",
"C0""Klaus Reimer",
"",
@@ -504,7 +522,7 @@ static const char *credits[] = {
"C0""Johannes Schickel",
"",
"",
-"C1""Translations",
+"C1""GUI Translations",
"C0""Thierry Crozat",
"C2""Translation Lead",
"C1""Basque",
@@ -574,6 +592,28 @@ static const char *credits[] = {
"C0""Lubomyr Lisen",
"",
"",
+"C1""Game Translations",
+"C1""CGE",
+"C0""Dan Serban",
+"C2""Soltys English translation",
+"A0""Victor Gonzalez",
+"C0""V\355ctor Gonz\341lez",
+"C2""Soltys Spanish translation",
+"A0""Alejandro Gomez de la Munoza",
+"C0""Alejandro G\363mez de la Mu\361oza",
+"C2""Soltys Spanish translation",
+"",
+"C1""Drascula",
+"C0""Thierry Crozat",
+"C2""Improve French translation",
+"",
+"C1""Mortevielle",
+"C0""Hugo Labrande",
+"C2""Improve English translation",
+"C0""Thierry Crozat",
+"C2""Improve English translation",
+"",
+"",
"C1""Websites (design)",
"A0""Dobo Balazs",
"C0""Dob\363 Bal\341zs",
@@ -609,6 +649,8 @@ static const char *credits[] = {
"C2""Several fixes for Simon1",
"C0""Jeroen Janssen",
"C2""Numerous readability and bugfix patches",
+"C0""Keith Kaisershot",
+"C2""Several Pegasus Prime patches",
"C0""Andreas Karlsson",
"C2""Initial port for SymbianOS",
"C0""Claudio Matsuoka",
@@ -760,6 +802,8 @@ static const char *credits[] = {
"C2""For additional work on the original MT-32 emulator",
"C0""James Woodcock",
"C2""Soundtrack enhancements",
+"C0""Anton Yartsev",
+"C2""For the original re-implementation of the ZVision engine",
"C0""Tony Warriner and everyone at Revolution Software Ltd. for sharing with us the source of some of their brilliant games, allowing us to release Beneath a Steel Sky as freeware... and generally being supportive above and beyond the call of duty.",
"C0""",
"C0""John Passfield and Steve Stamatiadis for sharing the source of their classic title, Flight of the Amazon Queen and also being incredibly supportive.",
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..999d61e854 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,15 +300,28 @@ 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;
while (eventMan->pollEvent(event)) {
+ // We will need to check whether the screen changed while polling
+ // for an event here. While we do send EVENT_SCREEN_CHANGED
+ // whenever this happens we still cannot be sure that we get such
+ // an event immediately. For example, we might have an mouse move
+ // event queued before an screen changed event. In some rare cases
+ // this would make the GUI redraw (with the code a few lines
+ // below) when it is not yet updated for new overlay dimensions.
+ // As a result ScummVM would crash because it tries to copy data
+ // outside the actual overlay screen.
+ if (event.type != Common::EVENT_SCREEN_CHANGED) {
+ checkScreenChange();
+ }
+
// The top dialog can change during the event loop. In that case, flush all the
// dialog-related events since they were probably generated while the old dialog
// was still visible, and therefore not intended for the new one.
@@ -314,72 +331,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 +375,11 @@ void GuiManager::runLoop() {
restoreState();
_useStdCursor = false;
}
+
+#ifdef ENABLE_EVENTRECORDER
+ // Resume recording once GUI is shown
+ g_eventRec.resumeRecording();
+#endif
}
#pragma mark -
@@ -492,7 +463,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 +508,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/object.cpp b/gui/object.cpp
index 73c4f74d6c..189a286ead 100644
--- a/gui/object.cpp
+++ b/gui/object.cpp
@@ -29,7 +29,7 @@
namespace GUI {
GuiObject::GuiObject(const Common::String &name)
- : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0) {
+ : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) {
reflowLayout();
}
diff --git a/gui/object.h b/gui/object.h
index bce3cd7846..dac3341b5a 100644
--- a/gui/object.h
+++ b/gui/object.h
@@ -24,6 +24,7 @@
#include "common/scummsys.h"
#include "common/str.h"
+#include "common/rect.h"
namespace GUI {
@@ -59,6 +60,8 @@ class Widget;
class GuiObject : public CommandReceiver {
friend class Widget;
protected:
+ Common::Rect _textDrawableArea;
+
int16 _x, _y;
uint16 _w, _h;
const Common::String _name;
@@ -66,10 +69,12 @@ protected:
Widget *_firstWidget;
public:
- GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0) { }
+ GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { }
GuiObject(const Common::String &name);
~GuiObject();
+ virtual void setTextDrawableArea(const Common::Rect &r) { _textDrawableArea = r; }
+
virtual int16 getAbsX() const { return _x; }
virtual int16 getAbsY() const { return _y; }
virtual int16 getChildX() const { return getAbsX(); }
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/options.cpp b/gui/options.cpp
index fb57c15d98..a9fdc19274 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -887,7 +887,7 @@ void OptionsDialog::addMT32Controls(GuiObject *boss, const Common::String &prefi
_mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", _c("True Roland MT-32 (no GM emulation)", "lowres"), _("Check if you want to use your real hardware Roland-compatible sound device connected to your computer"));
// GS Extensions setting
- _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Roland GS Mode (disable GM mapping)"), _("Turns off General MIDI mapping for games with Roland MT-32 soundtrack"));
+ _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Roland GS Device (enable MT-32 mappings)"), _("Check if you want to enable patch mappings to emulate an MT-32 on a Roland GS device"));
const MusicPlugin::List p = MusicMan.getPlugins();
// Make sure the null device is the first one in the list to avoid undesired
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index 5ce093e054..5d45a3060e 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -69,7 +69,7 @@ enum {
PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
new StaticTextWidget(this, "Predictive.Headline", "Enter Text");
- _btns = (ButtonWidget **)calloc(1, sizeof(ButtonWidget *) * 16);
+ _btns = (ButtonWidget **)calloc(16, sizeof(ButtonWidget *));
_btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd);
_btns[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd);
@@ -144,6 +144,7 @@ PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
_currentWord.clear();
_wordNumber = 0;
_numMatchingWords = 0;
+ memset(_predictiveResult, 0, sizeof(_predictiveResult));
_lastbutton = kNoAct;
_mode = kModePre;
@@ -420,6 +421,9 @@ void PredictiveDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 d
case kCancelCmd:
saveUserDictToFile();
close();
+ // When we cancel the dialog no result should be returned. Thus, we
+ // will invalidate any result here.
+ _predictiveResult[0] = 0;
return;
case kOkCmd:
_currBtn = kOkAct;
@@ -614,7 +618,7 @@ void PredictiveDialog::handleTickle() {
void PredictiveDialog::mergeDicts() {
_unitedDict.dictLineCount = _predictiveDict.dictLineCount + _userDict.dictLineCount;
- _unitedDict.dictLine = (char **)calloc(1, sizeof(char *) * _unitedDict.dictLineCount);
+ _unitedDict.dictLine = (char **)calloc(_unitedDict.dictLineCount, sizeof(char *));
if (!_unitedDict.dictLine) {
debug("Predictive Dialog: cannot allocate memory for united dic");
@@ -748,7 +752,8 @@ bool PredictiveDialog::matchWord() {
char tmp[kMaxLineLen];
strncpy(tmp, _unitedDict.dictLine[line], kMaxLineLen);
tmp[kMaxLineLen - 1] = 0;
- char *tok = strtok(tmp, " ");
+ char *tok;
+ strtok(tmp, " ");
tok = strtok(NULL, " ");
_currentWord = Common::String(tok, _currentCode.size());
return true;
@@ -853,7 +858,7 @@ void PredictiveDialog::addWord(Dict &dict, const Common::String &word, const Com
}
// start from here are INSERTING new line to dictionaty ( dict )
- char **newDictLine = (char **)calloc(1, sizeof(char *) * (dict.dictLineCount + 1));
+ char **newDictLine = (char **)calloc(dict.dictLineCount + 1, sizeof(char *));
if (!newDictLine) {
warning("Predictive Dialog: cannot allocate memory for index buffer");
@@ -861,7 +866,6 @@ void PredictiveDialog::addWord(Dict &dict, const Common::String &word, const Com
return;
}
- newDictLine[dict.dictLineCount] = '\0';
int k = 0;
bool inserted = false;
@@ -883,7 +887,7 @@ void PredictiveDialog::addWord(Dict &dict, const Common::String &word, const Com
free(dict.dictLine);
dict.dictLineCount += 1;
- dict.dictLine = (char **)calloc(1, sizeof(char *) * dict.dictLineCount);
+ dict.dictLine = (char **)calloc(dict.dictLineCount, sizeof(char *));
if (!dict.dictLine) {
warning("Predictive Dialog: cannot allocate memory for index buffer");
free(newDictLine);
@@ -935,7 +939,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict
ptr++;
}
- dict.dictLine = (char **)calloc(1, sizeof(char *) * lines);
+ dict.dictLine = (char **)calloc(lines, sizeof(char *));
if (dict.dictLine == NULL) {
warning("Predictive Dialog: Cannot allocate memory for line index buffer");
return;
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..9c5965f56d
--- /dev/null
+++ b/gui/recorderdialog.h
@@ -0,0 +1,83 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef 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 {
+ using GUI::Dialog::runModal;
+
+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..352cc86852 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1,142 +1,142 @@
"<?xml version = '1.0'?>"
-"<render_info> "
-"<palette> "
+"<render_info>"
+"<palette>"
"<color name='black' "
"rgb='0,0,0' "
-"/> "
+"/>"
"<color name='lightgrey' "
"rgb='104,104,104' "
-"/> "
+"/>"
"<color name='darkgrey' "
"rgb='64,64,64' "
-"/> "
+"/>"
"<color name='green' "
"rgb='32,160,32' "
-"/> "
+"/>"
"<color name='green2' "
"rgb='0,255,0' "
-"/> "
-"</palette> "
-"<fonts> "
+"/>"
+"</palette>"
+"<fonts>"
"<font id='text_default' "
"file='helvb12.bdf' "
-"/> "
+"/>"
"<font resolution='y<400' "
"id='text_default' "
"file='clR6x12.bdf' "
-"/> "
+"/>"
"<font id='text_button' "
"file='helvb12.bdf' "
-"/> "
+"/>"
"<font resolution='y<400' "
"id='text_button' "
"file='clR6x12.bdf' "
-"/> "
+"/>"
"<font id='text_normal' "
"file='helvb12.bdf' "
-"/> "
+"/>"
"<font resolution='y<400' "
"id='text_normal' "
"file='clR6x12.bdf' "
-"/> "
+"/>"
"<font id='tooltip_normal' "
"file='fixed5x8.bdf' "
-"/> "
+"/>"
"<text_color id='color_normal' "
"color='green' "
-"/> "
+"/>"
"<text_color id='color_normal_inverted' "
"color='black' "
-"/> "
+"/>"
"<text_color id='color_normal_hover' "
"color='green2' "
-"/> "
+"/>"
"<text_color id='color_normal_disabled' "
"color='lightgrey' "
-"/> "
+"/>"
"<text_color id='color_alternative' "
"color='lightgrey' "
-"/> "
+"/>"
"<text_color id='color_alternative_inverted' "
"color='255,255,255' "
-"/> "
+"/>"
"<text_color id='color_alternative_hover' "
"color='176,176,176' "
-"/> "
+"/>"
"<text_color id='color_alternative_disabled' "
"color='darkgrey' "
-"/> "
+"/>"
"<text_color id='color_button' "
"color='green' "
-"/> "
+"/>"
"<text_color id='color_button_hover' "
"color='green2' "
-"/> "
+"/>"
"<text_color id='color_button_disabled' "
"color='lightgrey' "
-"/> "
-"</fonts> "
-"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> "
-"<drawdata id='text_selection' cache='false'> "
+"/>"
+"</fonts>"
+"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/>"
+"<drawdata id='text_selection' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='text_selection_focus' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='text_selection_focus' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='mainmenu_bg' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='mainmenu_bg' cache='false'>"
"<drawstep func='fill' "
"fill='foreground' "
"fg_color='black' "
-"/> "
-"</drawdata> "
-"<drawdata id='special_bg' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='special_bg' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='tooltip_bg' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='tooltip_bg' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='foreground' "
"fg_color='black' "
-"/> "
-"</drawdata> "
-"<drawdata id='separator' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='separator' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"height='2' "
"ypos='center' "
"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_base' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_base' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_hover' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_handle_hover' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green2' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_idle' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_handle_idle' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_idle' cache='false' resolution='y>399'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_button_idle' cache='false' resolution='y>399'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -146,13 +146,13 @@
"ypos='center' "
"padding='0,0,3,0' "
"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_idle' cache='false' resolution='y<400'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_button_idle' cache='false' resolution='y<400'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -162,13 +162,13 @@
"ypos='center' "
"padding='0,0,2,0' "
"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_hover' cache='false' resolution='y>399'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_button_hover' cache='false' resolution='y>399'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -178,13 +178,13 @@
"ypos='center' "
"padding='0,0,3,0' "
"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_hover' cache='false' resolution='y<400'> "
+"/>"
+"</drawdata>"
+"<drawdata id='scrollbar_button_hover' cache='false' resolution='y<400'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -194,69 +194,69 @@
"ypos='center' "
"padding='0,0,2,0' "
"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_active' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='tab_active' cache='false'>"
"<text font='text_default' "
"text_color='color_normal_hover' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='tab' "
"bevel='2' "
"radius='0' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_inactive' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='tab_inactive' cache='false'>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='tab' "
"bevel='2' "
"radius='0' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_background' cache='false'> "
-"</drawdata> "
-"<drawdata id='widget_slider' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='tab_background' cache='false'>"
+"</drawdata>"
+"<drawdata id='widget_slider' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_disabled' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='slider_disabled' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_full' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='slider_full' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_hover' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='slider_hover' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green2' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_small' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='widget_small' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_idle' cache='false' resolution='y>399'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_idle' cache='false' resolution='y>399'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -266,7 +266,7 @@
"ypos='10' "
"padding='0,0,7,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -276,18 +276,18 @@
"ypos='4' "
"padding='0,0,7,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_idle' cache='false' resolution='y<400'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_idle' cache='false' resolution='y<400'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -297,7 +297,7 @@
"ypos='9' "
"padding='0,0,3,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -307,18 +307,18 @@
"ypos='4' "
"padding='0,0,3,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_disabled' cache='false' resolution='y>399'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_disabled' cache='false' resolution='y>399'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -328,7 +328,7 @@
"ypos='10' "
"padding='0,0,7,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -338,18 +338,18 @@
"ypos='4' "
"padding='0,0,7,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal_disabled' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_disabled' cache='false' resolution='y<400'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_disabled' cache='false' resolution='y<400'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -359,7 +359,7 @@
"ypos='9' "
"padding='0,0,3,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -369,18 +369,18 @@
"ypos='4' "
"padding='0,0,3,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_hover' cache='false' resolution='y>399'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_hover' cache='false' resolution='y>399'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -390,7 +390,7 @@
"ypos='10' "
"padding='0,0,7,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -400,18 +400,18 @@
"ypos='4' "
"padding='0,0,7,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal_hover' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_hover' cache='false' resolution='y<400'> "
+"/>"
+"</drawdata>"
+"<drawdata id='popup_hover' cache='false' resolution='y<400'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -421,7 +421,7 @@
"ypos='9' "
"padding='0,0,3,0' "
"orientation='bottom' "
-"/> "
+"/>"
"<drawstep func='triangle' "
"fg_color='green' "
"fill='foreground' "
@@ -431,123 +431,123 @@
"ypos='4' "
"padding='0,0,3,0' "
"orientation='top' "
-"/> "
+"/>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_textedit' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='widget_textedit' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='plain_bg' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='plain_bg' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='caret' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='caret' cache='false'>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='default_bg' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='default_bg' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_pressed' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='button_pressed' cache='false'>"
"<text font='text_button' "
"text_color='color_alternative_inverted' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='square' "
"fill='foreground' "
"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_idle' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='button_idle' cache='false'>"
"<text font='text_button' "
"text_color='color_button' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_hover' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='button_hover' cache='false'>"
"<text font='text_button' "
"text_color='color_button_hover' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_disabled' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='button_disabled' cache='false'>"
"<text font='text_button' "
"text_color='color_button_disabled' "
"vertical_align='center' "
"horizontal_align='center' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_disabled' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='checkbox_disabled' cache='false'>"
"<text font='text_default' "
"text_color='color_normal_disabled' "
"vertical_align='top' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_selected' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='checkbox_selected' cache='false'>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='top' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
+"/>"
"<drawstep func='cross' "
"fill='foreground' "
"stroke='2' "
"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_default' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='checkbox_default' cache='false'>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='top' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='bevelsq' "
"bevel='2' "
"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='radiobutton_default' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='radiobutton_default' cache='false'>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='circle' "
"width='7' "
"height='7' "
@@ -556,14 +556,14 @@
"bg_color='darkgrey' "
"xpos='0' "
"ypos='0' "
-"/> "
-"</drawdata> "
-"<drawdata id='radiobutton_selected' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='radiobutton_selected' cache='false'>"
"<text font='text_default' "
"text_color='color_normal' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='circle' "
"width='7' "
"height='7' "
@@ -572,7 +572,7 @@
"fill='none' "
"xpos='0' "
"ypos='0' "
-"/> "
+"/>"
"<drawstep func='circle' "
"width='7' "
"height='7' "
@@ -581,14 +581,14 @@
"fill='foreground' "
"xpos='2' "
"ypos='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='radiobutton_disabled' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='radiobutton_disabled' cache='false'>"
"<text font='text_default' "
"text_color='color_normal_disabled' "
"vertical_align='center' "
"horizontal_align='left' "
-"/> "
+"/>"
"<drawstep func='circle' "
"width='7' "
"height='7' "
@@ -597,2286 +597,2510 @@
"fill='background' "
"xpos='0' "
"ypos='0' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_default' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='widget_default' cache='false'>"
"<drawstep func='bevelsq' "
"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_small' cache='false'> "
+"/>"
+"</drawdata>"
+"<drawdata id='widget_small' cache='false'>"
"<drawstep func='square' "
"stroke='0' "
-"/> "
-"</drawdata> "
-"</render_info> "
-"<layout_info resolution='y<400'> "
-"<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='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' "
-"/> "
+"/>"
+"</drawdata>"
+"</render_info>"
+"<layout_info resolution='y>399'>"
+"<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='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='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' "
-"/> "
+"/>"
"<widget name='EditTextWidget' "
"padding='5,5,0,0' "
-"/> "
+"/>"
"<widget name='Console' "
"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' "
-"/> "
-"</globals> "
-"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='6,6,2,2'> "
+"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='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' "
-"/> "
+"/>"
"<widget name='Search' "
"width='150' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SearchClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"<space /> "
-"</layout> "
-"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"/>"
+"<space />"
+"</layout>"
+"<widget name='GameList'/>"
+"<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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"height='20' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
+"height='20' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8'>"
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='Path' "
"height='Globals.Line.Height' "
-"/> "
-"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,8,0'> "
+"/>"
+"<widget name='List'/>"
+"<layout type='vertical' padding='0,0,16,0'>"
"<widget name='Hidden' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0'>"
"<widget name='Up' "
"type='Button' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Choose' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0'> "
-"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='TabWidget'/>"
+"<layout type='horizontal' padding='16,16,16,16'>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</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>"
+"</layout>"
+"</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'>"
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='grModePopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='grRenderPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='grAspectCheckbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='grFullscreenCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auMidiPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auOPLPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auSampleRatePopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'>"
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"/> "
+"/>"
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"/> "
+"/>"
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'>"
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='vcMusicText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcMusicSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcMusicLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0'>"
"<widget name='vcSfxText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSfxSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSfxLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0'>"
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSpeechSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSpeechLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"/>"
+"</layout>"
+"</layout>"
+"<layout type='vertical' padding='24,0,24,0' center='true'>"
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auPrefGmPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='mcFontButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='mcFontPath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='mcFontClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<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' "
-"/> "
+"/>"
"<widget name='mcMidiGainSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='mcMidiGainLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
+"/>"
+"</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>"
+"</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'>"
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auPrefMt32Popup' "
"type='PopUp' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='mcMt32Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='mcGSCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='SaveButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='SavePath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SavePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='ThemeButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ThemePath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ThemePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='ExtraButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ExtraPath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ExtraPathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'>"
"<widget name='PluginsButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='PluginsPath' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</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>"
+"</layout>"
+"</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'>"
"<widget name='ThemeButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='CurTheme' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<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>"
+"<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>"
+"<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' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='KeysButton' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8' center='true'>"
"<widget name='Action' "
"height='Globals.Line.Height' "
-"/> "
-"<widget name='List'/> "
+"/>"
+"<widget name='List'/>"
"<widget name='Mapping' "
"height='Globals.Line.Height' "
-"/> "
-"<space size='Globals.Line.Height'/> "
-"<layout type='horizontal'> "
+"/>"
+"<space size='Globals.Line.Height'/>"
+"<layout type='horizontal'>"
"<widget name='Map' "
"type='Button' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<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='8,8,8,8'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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='16,16,16,4'>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Graphics' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Graphics' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Audio' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Audio' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_MIDI' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_MIDI' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_MT32' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_MT32' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Volume' /> "
-"</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'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Volume' />"
+"</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'>"
"<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>"
+"<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>"
+"<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>"
+"<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' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='Savepath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='SavepathText' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SavePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='Extrapath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ExtrapathText' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ExtraPathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='Gamepath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='GamepathText' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'>"
+"<layout type='vertical' padding='16,16,16,16'>"
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption2Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption3Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption4Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption5Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption6Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption7Checkbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalMenu' overlays='screen_center'>"
+"<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' "
-"/> "
-"<space size='1'/> "
+"width='210' "
+"height='Globals.Line.Height' "
+"/>"
+"<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' "
-"/> "
-"<space size='1'/> "
+"width='150' "
+"height='Globals.Button.Height' "
+"/>"
+"<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' "
-"/> "
-"</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'> "
+"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'>"
+"<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' "
-"/> "
+"/>"
"<widget name='vcMusicSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcMusicLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'>"
"<widget name='vcSfxText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSfxSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSfxLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'>"
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSpeechSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSpeechLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"/>"
+"</layout>"
+"</layout>"
+"<layout type='vertical' padding='24,24,24,24' center='true'>"
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
-"/> "
-"</layout> "
-"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"width='80' "
+"/>"
+"</layout>"
+"</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' "
-"/> "
-"</layout> "
-"</layout> "
-"<space size='2' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"width='100' "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'>"
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<space size='16'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"/>"
+"</layout>"
+"<space size='60'/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'>"
"<widget name='Keys' "
"type='Button' "
-"/> "
-"<space size='Globals.Button.Width' /> "
+"/>"
+"<space size='Globals.Button.Width' />"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<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'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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'>"
+"<space/>"
"<widget name='ResetSettings' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='VoiceCountText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='VoiceCountSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='VoiceCountLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='LevelText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='LevelSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='LevelLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='SpeedText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='SpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='SpeedLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='DepthText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='DepthSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='DepthLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='WaveFormTypeText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='WaveFormType' "
"type='PopUp' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<layout type='vertical' padding='16,16,16,16' spacing='8'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='RoomSizeText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='RoomSizeSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='RoomSizeLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='DampingText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='DampingSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='DampingLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='WidthText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='WidthSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='WidthLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='LevelText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='LevelSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='LevelLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<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' "
-"/> "
+"/>"
"<widget name='Interpolation' "
"type='PopUp' "
-"/> "
-"</layout> "
-"</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'/> "
-"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"/>"
+"</layout>"
+"</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'>"
+"<widget name='List' />"
+"<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' "
-"/> "
+"/>"
"<widget name='GridSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Delete' "
"type='Button' "
-"/> "
-"<space size='16'/> "
+"/>"
+"<space size='32'/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Choose' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='SavenameDialog' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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' "
"height='19' "
-"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"/>"
+"<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='ScummHelp' overlays='screen'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"/>"
+"</layout>"
+"</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' "
+"width='320' "
+"height='Globals.Line.Height' "
+"/>"
"<widget name='HelpText' "
-"height='140' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"height='200' "
+"/>"
+"<layout type='horizontal' padding='0,0,16,0'>"
"<widget name='Prev' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Next' "
"type='Button' "
-"/> "
-"<space size='32'/> "
+"/>"
+"<space size='32'/>"
"<widget name='Close' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='Standard' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Practice' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Expert' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='MassAdd' overlays='screen_center' shading='dim'>"
+"<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' "
-"/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
+"width='480' "
+"height='250' "
+"/>"
+"<layout type='horizontal' padding='8,8,8,8'>"
"<widget name='Ok' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='KeyMapper' overlays='screen_center' shading='dim'>"
+"<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> "
+"/>"
+"</layout>"
"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
-"/> "
+"width='600' "
+"height='280' "
+"/>"
"<widget name='Close' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='1,1,1,1' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='Predictive' overlays='screen_center'>"
+"<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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,0'> "
+"height='Globals.Button.Height' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"<space size='3' /> "
-"<layout type='horizontal' padding='3,3,0,3'> "
+"height='Globals.Button.Height' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"</layout_info> "
-"<layout_info resolution='y>399'> "
-"<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='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' /> "
+"height='Globals.Button.Height' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"</layout_info>"
+"<layout_info resolution='y<400'>"
+"<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='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='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' "
-"/> "
+"/>"
"<widget name='EditTextWidget' "
"padding='5,5,0,0' "
-"/> "
+"/>"
"<widget name='Console' "
"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' "
-"/> "
-"</globals> "
-"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"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='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' "
-"/> "
+"/>"
"<widget name='Search' "
"width='150' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SearchClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"<space /> "
-"</layout> "
-"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"/>"
+"<space />"
+"</layout>"
+"<widget name='GameList'/>"
+"<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' "
-"/> "
-"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"height='12' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"height='12' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'>"
+"<layout type='vertical' padding='8,8,0,4'>"
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='Path' "
"height='Globals.Line.Height' "
-"/> "
-"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,16,0'> "
+"/>"
+"<widget name='List'/>"
+"<layout type='vertical' padding='0,0,8,0'>"
"<widget name='Hidden' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0'>"
"<widget name='Up' "
"type='Button' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Choose' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0'> "
-"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='TabWidget'/>"
+"<layout type='horizontal' padding='8,8,8,8'>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</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>"
+"</layout>"
+"</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'>"
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='grModePopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='grRenderPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='grAspectCheckbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='grFullscreenCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auMidiPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auOPLPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auSampleRatePopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'>"
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"/> "
+"/>"
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"/> "
+"/>"
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='vcMusicText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcMusicSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcMusicLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='vcSfxText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSfxSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSfxLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSpeechSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSpeechLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
+"<space size='110' />"
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auPrefGmPopup' "
"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'>"
"<widget name='mcFontButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='mcFontPath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='mcFontClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<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' "
-"/> "
+"/>"
"<widget name='mcMidiGainSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='mcMidiGainLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
+"/>"
+"</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>"
+"</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'>"
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='auPrefMt32Popup' "
"type='PopUp' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='mcMt32Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='mcGSCheckbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='SaveButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='SavePath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SavePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'>"
"<widget name='ThemeButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ThemePath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ThemePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'>"
"<widget name='ExtraButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ExtraPath' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ExtraPathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'>"
"<widget name='PluginsButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='PluginsPath' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</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>"
+"</layout>"
+"</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'>"
"<widget name='ThemeButton' "
"type='Button' "
-"/> "
+"/>"
"<widget name='CurTheme' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<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>"
+"<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>"
+"<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' "
-"/> "
-"</layout> "
+"/>"
+"</layout>"
"<widget name='KeysButton' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8' center='true'>"
"<widget name='Action' "
"height='Globals.Line.Height' "
-"/> "
-"<widget name='List'/> "
+"/>"
+"<widget name='List'/>"
"<widget name='Mapping' "
"height='Globals.Line.Height' "
-"/> "
-"<space size='Globals.Line.Height'/> "
-"<layout type='horizontal'> "
+"/>"
+"<space size='Globals.Line.Height'/>"
+"<layout type='horizontal'>"
"<widget name='Map' "
"type='Button' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<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='16,16,16,4'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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='8,8,8,8'>"
+"<space/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Graphics' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Graphics' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Audio' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Audio' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_MIDI' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_MIDI' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_MT32' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_MT32' />"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Volume' /> "
-"</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'> "
+"/>"
+"<import layout='Dialog.GlobalOptions_Volume' />"
+"</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'>"
"<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>"
+"<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'> "
+"/>"
+"</layout>"
+"<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>"
+"<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' "
-"/> "
-"</layout> "
-"</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>"
+"</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'>"
"<widget name='Savepath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='SavepathText' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='SavePathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'>"
"<widget name='Extrapath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='ExtrapathText' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='ExtraPathClearButton' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'>"
"<widget name='Gamepath' "
"type='Button' "
-"/> "
+"/>"
"<widget name='GamepathText' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8'>"
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption2Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption3Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption4Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption5Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption6Checkbox' "
"type='Checkbox' "
-"/> "
+"/>"
"<widget name='customOption7Checkbox' "
"type='Checkbox' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalMenu' overlays='screen_center'>"
+"<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' "
-"/> "
-"<space size='10'/> "
+"width='160' "
+"height='4' "
+"/>"
+"<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' "
-"/> "
-"<space size='10'/> "
+"width='120' "
+"height='12' "
+"/>"
+"<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' "
-"/> "
-"<space size='10'/> "
+"width='120' "
+"height='12' "
+"/>"
+"<space size='1'/>"
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
+"/>"
"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
-"/> "
+"width='120' "
+"height='12' "
+"/>"
"<widget name='Quit' "
-"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'> "
-"<layout type='vertical' padding='0,0,0,0' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"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' spacing='6' center='true'>"
"<widget name='vcMusicText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcMusicSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcMusicLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='vcSfxText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSfxSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSfxLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='vcSpeechSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='vcSpeechLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
+"<space size='110' />"
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
-"/> "
-"</layout> "
-"</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"width='80' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"width='90' "
+"/>"
+"</layout>"
+"</layout>"
+"<space size='2' />"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>"
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='subSubtitleSpeedLabel' "
"type='SmallLabel' "
-"/> "
-"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"/>"
+"</layout>"
+"<space size='16'/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'>"
"<widget name='Keys' "
"type='Button' "
-"/> "
-"<space size='Globals.Button.Width' /> "
+"/>"
+"<space size='Globals.Button.Width' />"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<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'> "
-"<space/> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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'>"
+"<space/>"
"<widget name='ResetSettings' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Ok' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='VoiceCountText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='VoiceCountSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='VoiceCountLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='LevelText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='LevelSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='LevelLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='SpeedText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='SpeedSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='SpeedLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='DepthText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='DepthSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='DepthLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='WaveFormTypeText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='WaveFormType' "
"type='PopUp' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<layout type='vertical' padding='8,8,8,8' spacing='6'>"
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='RoomSizeText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='RoomSizeSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='RoomSizeLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='DampingText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='DampingSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='DampingLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='WidthText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='WidthSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='WidthLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>"
"<widget name='LevelText' "
"type='OptionsLabel' "
-"/> "
+"/>"
"<widget name='LevelSlider' "
"type='Slider' "
-"/> "
+"/>"
"<widget name='LevelLabel' "
"width='32' "
"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'>"
+"<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' "
-"/> "
+"/>"
"<widget name='Interpolation' "
"type='PopUp' "
-"/> "
-"</layout> "
-"</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'> "
-"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"/>"
+"</layout>"
+"</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'/>"
+"<widget name='List' />"
+"<layout type='horizontal' padding='0,0,16,0'>"
"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='GridSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
-"/> "
-"<space/> "
+"/>"
+"<space/>"
"<widget name='Delete' "
"type='Button' "
-"/> "
-"<space size='32'/> "
+"/>"
+"<space size='16'/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Choose' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='SavenameDialog' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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' "
"height='19' "
-"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"/>"
+"<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='ScummHelp' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"/>"
+"</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' "
-"width='320' "
"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' "
+"width='180' "
+"height='Globals.Line.Height' "
+"/>"
"<widget name='HelpText' "
-"height='200' "
-"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"height='140' "
+"/>"
+"<layout type='horizontal' padding='0,0,0,0'>"
"<widget name='Prev' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Next' "
"type='Button' "
-"/> "
-"<space size='32'/> "
+"/>"
+"<space size='32'/>"
"<widget name='Close' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<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' "
"height='Globals.Line.Height' "
-"/> "
+"/>"
"<widget name='Standard' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Practice' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Expert' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='MassAdd' overlays='screen_center' shading='dim'>"
+"<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' "
-"/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"width='280' "
+"height='100' "
+"/>"
+"<layout type='horizontal' padding='4,4,4,4'>"
"<widget name='Ok' "
"type='Button' "
-"/> "
+"/>"
"<widget name='Cancel' "
"type='Button' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='KeyMapper' overlays='screen_center' shading='dim'>"
+"<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> "
+"/>"
+"</layout>"
"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
-"/> "
+"width='300' "
+"height='120' "
+"/>"
"<widget name='Close' "
"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='5,5,5,5' center='true'> "
+"/>"
+"</layout>"
+"</dialog>"
+"<dialog name='Predictive' overlays='screen_center'>"
+"<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' "
-"/> "
-"</layout> "
-"<space size='5' /> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"height='Globals.Predictive.Button.Height' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"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' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"height='Globals.Predictive.Button.Height' "
+"/>"
+"</layout>"
+"<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' "
-"/> "
-"</layout> "
-"<space size='5' /> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"height='Globals.Predictive.Button.Height' "
+"/>"
+"</layout>"
+"<space size='3' />"
+"<layout type='horizontal' padding='3,3,0,3'>"
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
-"/> "
-"<space size='22'/> "
+"height='Globals.Predictive.Button.Height' "
+"/>"
"<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' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"</layout_info> "
+"height='Globals.Predictive.Button.Height' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"</layout_info>"
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 297ff20344..1085aa64a4 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..e40e8b1e26 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..3a1ec5a5f0 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -38,6 +38,14 @@
rgb = '203, 126, 107'
/>
+ <color name = 'brightredborder'
+ rgb = '238, 213, 207'
+ />
+
+ <color name = 'darkredborder'
+ rgb = '30, 7, 1'
+ />
+
<!-- Disabled button/slider -->
<color name = 'darkeneddarkred'
rgb = '120, 28, 0'
@@ -73,7 +81,7 @@
rgb = '255, 255, 255'
/>
<color name = 'shadowcolor'
- rgb = '63, 60, 17'
+ rgb = '105, 101, 86'
/>
<color name = 'darkgray'
rgb = '176, 168, 144'
@@ -103,6 +111,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>
@@ -162,6 +178,10 @@
color = '128, 128, 128'
/>
+ <text_color id = 'color_button_hover'
+ color = 'white'
+ />
+
<text_color id = 'color_alternative_inverted'
color = 'white'
/>
@@ -178,10 +198,6 @@
color = 'white'
/>
- <text_color id = 'color_button_hover'
- color = '255, 214, 84'
- />
-
<text_color id = 'color_button_disabled'
color = '192, 192, 192'
/>
@@ -224,7 +240,7 @@
stroke = '0'
gradient_start = 'darkorange'
gradient_end = 'brightorange'
- shadow = '3'
+ shadow = '7'
gradient_factor = '3'
/>
</drawdata>
@@ -458,7 +474,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
- shadow = '2'
+ shadow = '1'
/>
<drawstep func = 'triangle'
@@ -497,7 +513,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
- shadow = '2'
+ shadow = '1'
/>
<drawstep func = 'triangle'
@@ -655,7 +671,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
- shadow = '2'
+ shadow = '1'
/>
<drawstep func = 'triangle'
@@ -708,7 +724,7 @@
gradient_start = 'blandyellow'
gradient_end = 'xtrabrightred'
fill = 'gradient'
- shadow = '3'
+ shadow = '7'
/>
</drawdata>
@@ -729,7 +745,7 @@
gradient_start = 'blandyellow'
gradient_end = 'xtrabrightred'
gradient_factor = '4'
- shadow = '3'
+ shadow = '7'
/>
</drawdata>
@@ -775,18 +791,18 @@
stroke = '1'
fill = 'gradient'
shadow = '0'
- fg_color = 'shadowcolor'
+ fg_color = 'darkredborder'
gradient_start = 'brightred'
gradient_end = 'darkred'
bevel = '1'
- bevel_color = '237, 169, 72'
+ bevel_color = 'brightredborder'
/>
</drawdata>
<!-- Hovered button -->
<drawdata id = 'button_hover' cache = 'false'>
<text font = 'text_button'
- text_color = 'color_button_hover'
+ text_color = 'color_button'
vertical_align = 'center'
horizontal_align = 'center'
/>
@@ -795,11 +811,11 @@
stroke = '1'
fill = 'gradient'
shadow = '0'
- fg_color = 'shadowcolor'
+ fg_color = 'darkredborder'
gradient_start = 'brightpink'
gradient_end = 'darkpink'
bevel = '1'
- bevel_color = 'xtrabrightred'
+ bevel_color = 'brightredborder'
/>
</drawdata>
@@ -907,7 +923,7 @@
gradient_factor = '6'
fill = 'gradient'
bg_color = 'xtrabrightred'
- shadow = '3'
+ shadow = '7'
/>
</drawdata>
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/themes/scummtheme.py b/gui/themes/scummtheme.py
index 4c55fd79de..524e91468e 100755
--- a/gui/themes/scummtheme.py
+++ b/gui/themes/scummtheme.py
@@ -37,9 +37,13 @@ def parseSTX(theme_file, def_file):
comm = re.compile("<!--(.*?)-->", re.DOTALL)
head = re.compile("<\?(.*?)\?>")
+ strlitcount = 0
output = ""
for line in theme_file:
- output += line.rstrip("\r\n\t ").lstrip() + " \n"
+ output += line.rstrip("\r\n\t ").lstrip()
+ if not output.endswith('>'):
+ output += ' '
+ output += "\n"
output = re.sub(comm, "", output)
output = re.sub(head, "", output)
@@ -48,7 +52,9 @@ def parseSTX(theme_file, def_file):
for line in output.splitlines():
if line and not line.isspace():
+ strlitcount += len(line)
def_file.write("\"" + line + "\"\n")
+ return strlitcount
def buildDefTheme(themeName):
def_file = open("default.inc", "w")
@@ -57,16 +63,23 @@ def buildDefTheme(themeName):
print ("Cannot open default theme dir.")
def_file.write(""" "<?xml version = '1.0'?>"\n""")
+ strlitcount = 24
for filename in os.listdir(themeName):
filename = os.path.join(themeName, filename)
if os.path.isfile(filename) and filename.endswith(".stx"):
theme_file = open(filename, "r")
- parseSTX(theme_file, def_file)
+ strlitcount += parseSTX(theme_file, def_file)
theme_file.close()
def_file.close()
+ if strlitcount > 65535:
+ print("WARNING: default.inc string literal is of length %d which exceeds the" % strlitcount)
+ print(" maximum length of 65536 that C++ compilers are required to support.")
+ print(" It is likely that bugs will occur dependent on compiler behaviour.")
+ print(" To avoid this, reduce the size of the theme.")
+
def printUsage():
print ("===============================")
print ("ScummVM Theme Generation Script")
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index ddd7fde91c..7bd1316208 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/gui/widget.cpp b/gui/widget.cpp
index c3f10a861f..e96b62e359 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -287,7 +287,7 @@ ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Co
ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
: StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss),
- _cmd(cmd), _lastTime(0) {
+ _cmd(cmd), _hotkey(hotkey), _lastTime(0) {
if (hotkey == 0)
_hotkey = parseHotkey(label);
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
@@ -396,7 +396,7 @@ PicButtonWidget::~PicButtonWidget() {
void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
_gfx.free();
- if (!gfx || !gfx->pixels)
+ if (!gfx || !gfx->getPixels())
return;
if (gfx->format.bytesPerPixel == 1) {
@@ -429,7 +429,7 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
void PicButtonWidget::drawWidget() {
g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
- if (_gfx.pixels) {
+ if (_gfx.getPixels()) {
// Check whether the set up surface needs to be converted to the GUI
// color format.
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
@@ -646,7 +646,7 @@ GraphicsWidget::~GraphicsWidget() {
void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
_gfx.free();
- if (!gfx || !gfx->pixels)
+ if (!gfx || !gfx->getPixels())
return;
if (gfx->format.bytesPerPixel == 1) {
@@ -676,7 +676,7 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
}
void GraphicsWidget::drawWidget() {
- if (_gfx.pixels) {
+ if (_gfx.getPixels()) {
// Check whether the set up surface needs to be converted to the GUI
// color format.
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 6fae9346b2..6f550b5642 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -261,23 +261,45 @@ void EditableWidget::drawCaret(bool erase) {
int x = editRect.left;
int y = editRect.top;
- x += getCaretOffset();
+ const int caretOffset = getCaretOffset();
+ x += caretOffset;
- if (y < 0 || y + editRect.height() - 2 >= _h)
+ if (y < 0 || y + editRect.height() > _h)
return;
x += getAbsX();
y += getAbsY();
- g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height() - 2), erase);
+ g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
if (erase) {
+ GUI::EditableWidget::String character;
+ int width;
+
if ((uint)_caretPos < _editString.size()) {
- GUI::EditableWidget::String chr(_editString[_caretPos]);
- int chrWidth = g_gui.getCharWidth(_editString[_caretPos], _font);
+ const byte chr = _editString[_caretPos];
+ width = g_gui.getCharWidth(chr, _font);
+ character = chr;
+
const uint last = (_caretPos > 0) ? _editString[_caretPos - 1] : 0;
- x += g_gui.getKerningOffset(last, _editString[_caretPos], _font);
- g_gui.theme()->drawText(Common::Rect(x, y, x + chrWidth, y + editRect.height() - 2), chr, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font);
+ x += g_gui.getKerningOffset(last, chr, _font);
+ } else {
+ // We draw a fake space here to assure that removing the caret
+ // does not result in color glitches in case the edit rect is
+ // drawn with an inversion.
+ width = g_gui.getCharWidth(' ', _font);
+ character = " ";
+ }
+
+ // TODO: Right now we manually prevent text from being drawn outside
+ // the edit area here. We might want to consider to use
+ // setTextDrawableArea for this. However, it seems that only
+ // EditTextWidget uses that but not ListWidget. Thus, one should check
+ // whether we can unify the drawing in the text area first to avoid
+ // possible glitches due to different methods used.
+ width = MIN(editRect.width() - caretOffset, width);
+ if (width > 0) {
+ g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
}
diff --git a/gui/widgets/editable.h b/gui/widgets/editable.h
index 4a18d5e689..63a1942311 100644
--- a/gui/widgets/editable.h
+++ b/gui/widgets/editable.h
@@ -78,6 +78,11 @@ protected:
virtual void startEditMode() = 0;
virtual void endEditMode() = 0;
virtual void abortEditMode() = 0;
+ /**
+ * The area where text input is being made. This should exactly match the
+ * rect with which the actual edit string is drawn otherwise nasty
+ * graphics glitches when redrawing the caret can occur.
+ */
virtual Common::Rect getEditRect() const = 0;
virtual int getCaretOffset() const;
void drawCaret(bool erase);
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 4b266e8194..c54ca573ba 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,19 +80,28 @@ 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);
// Draw the text
adjustOffset();
- g_gui.theme()->drawText(Common::Rect(_x+2+ _leftPadding,_y+2, _x+_leftPadding+getEditRect().width()+2, _y+_h-2), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font);
+
+ const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
+ setTextDrawableArea(r);
+
+ g_gui.theme()->drawText(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
Common::Rect EditTextWidget::getEditRect() const {
- Common::Rect r(2 + _leftPadding, 2, _w - 2 - _leftPadding - _rightPadding, _h-1);
+ Common::Rect r(2 + _leftPadding, 2, _w - 2 - _leftPadding - _rightPadding, _h);
return r;
}
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 473d5f04df..8b8eb31db9 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -91,6 +91,9 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *too
// FIXME: This flag should come from widget definition
_editable = true;
+
+ _quickSelect = true;
+ _editColor = ThemeEngine::kFontColorNormal;
}
ListWidget::~ListWidget() {
@@ -538,7 +541,7 @@ void ListWidget::drawWidget() {
}
Common::Rect ListWidget::getEditRect() const {
- Common::Rect r(_hlLeftPadding, 0, _w - _hlLeftPadding - _hlRightPadding, kLineHeight - 1);
+ Common::Rect r(_hlLeftPadding, 0, _w - _hlLeftPadding - _hlRightPadding, kLineHeight - 2);
const int offset = (_selectedItem - _currentPos) * kLineHeight + _topPadding;
r.top += offset;
r.bottom += offset;
diff --git a/po/POTFILES b/po/POTFILES
index c2f67e288b..a33c8e3a83 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -24,45 +24,6 @@ common/util.cpp
engines/advancedDetector.cpp
engines/dialogs.cpp
engines/engine.cpp
-engines/agi/detection.cpp
-engines/agi/saveload.cpp
-engines/drascula/detection.cpp
-engines/drascula/saveload.cpp
-engines/dreamweb/detection.cpp
-engines/sci/detection.cpp
-engines/scumm/dialogs.cpp
-engines/scumm/help.cpp
-engines/scumm/scumm.cpp
-engines/mohawk/dialogs.cpp
-engines/mohawk/myst.cpp
-engines/mohawk/riven.cpp
-engines/cruise/menu.cpp
-engines/sci/engine/kfile.cpp
-engines/agos/saveload.cpp
-engines/agos/animation.cpp
-engines/gob/inter_playtoons.cpp
-engines/gob/inter_v2.cpp
-engines/gob/inter_v5.cpp
-engines/groovie/detection.cpp
-engines/groovie/script.cpp
-engines/kyra/detection.cpp
-engines/kyra/lol.cpp
-engines/kyra/sound_midi.cpp
-engines/queen/queen.cpp
-engines/sky/compact.cpp
-engines/sky/detection.cpp
-engines/sword1/animation.cpp
-engines/sword1/control.cpp
-engines/sword1/logic.cpp
-engines/sword1/sword1.cpp
-engines/sword2/animation.cpp
-engines/sword2/sword2.cpp
-engines/teenagent/resources.cpp
-engines/tinsel/saveload.cpp
-engines/toltecs/detection.cpp
-engines/toltecs/menu.cpp
-engines/parallaction/saveload.cpp
-engines/pegasus/pegasus.cpp
audio/fmopl.cpp
audio/mididrv.cpp
@@ -97,5 +58,5 @@ backends/events/default/default-events.cpp
backends/events/gph/gph-events.cpp
backends/events/openpandora/op-events.cpp
backends/updates/macosx/macosx-updates.mm
-backends/platform/bada/form.cpp
+backends/platform/tizen/form.cpp
backends/events/maemosdl/maemosdl-events.cpp
diff --git a/po/module.mk b/po/module.mk
index a9295656db..88bf7d5d12 100644
--- a/po/module.mk
+++ b/po/module.mk
@@ -2,8 +2,10 @@ POTFILE := $(srcdir)/po/scummvm.pot
POFILES := $(wildcard $(srcdir)/po/*.po)
CPFILES := $(wildcard $(srcdir)/po/*.cp)
+ENGINE_INPUT_POTFILES := $(wildcard $(srcdir)/engines/*/POTFILES)
updatepot:
- xgettext -f $(srcdir)/po/POTFILES -D $(srcdir) -d scummvm --c++ -k_ -k_s -k_c:1,2c -k_sc:1,2c --add-comments=I18N\
+ cat $(srcdir)/po/POTFILES $(ENGINE_INPUT_POTFILES) | \
+ xgettext -f - -D $(srcdir) -d scummvm --c++ -k_ -k_s -k_c:1,2c -k_sc:1,2c --add-comments=I18N\
-kDECLARE_TRANSLATION_ADDITIONAL_CONTEXT:1,2c -o $(POTFILE) \
--copyright-holder="ScummVM Team" --package-name=ScummVM \
--package-version=$(VERSION) --msgid-bugs-address=scummvm-devel@lists.sf.net -o $(POTFILE)_
diff --git a/po/pl_PL.po b/po/pl_PL.po
index 720a55daca..38cedb55d7 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: ScummVM 1.3.0\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
"POT-Creation-Date: 2013-04-24 13:35+0100\n"
-"PO-Revision-Date: 2012-07-29 15:49+0100\n"
+"PO-Revision-Date: 2013-05-22 14:26+0100\n"
"Last-Translator: Micha³ Zi±bkowski <mziab@o2.pl>\n"
"Language-Team: Grajpopolsku.pl <grajpopolsku@gmail.com>\n"
"Language: Polski\n"
@@ -34,13 +34,12 @@ msgid "Available engines:"
msgstr "Dostêpne silniki:"
#: gui/browser.cpp:67
-#, fuzzy
msgid "Show hidden files"
-msgstr "Schowaj / poka¿ konsolê"
+msgstr "Poka¿ ukryte pliki"
#: gui/browser.cpp:67
msgid "Show files marked with the hidden attribute"
-msgstr ""
+msgstr "Poka¿ pliki oznaczone atrybutem ukryty"
#: gui/browser.cpp:71
msgid "Go up"
@@ -724,7 +723,7 @@ msgstr "Wzm. MIDI:"
#: gui/options.cpp:873
msgid "FluidSynth Settings"
-msgstr ""
+msgstr "Ustawienia FluidSynth"
#: gui/options.cpp:880
msgid "MT-32 Device:"
@@ -753,9 +752,8 @@ msgid "True Roland MT-32 (no GM emulation)"
msgstr "Prawdziwy Roland MT-32 (brak emulacji GM)"
#: gui/options.cpp:890
-#, fuzzy
msgid "Roland GS Mode (disable GM mapping)"
-msgstr "Prawdziwy Roland MT-32 (wy³±cz emulacjê GM)"
+msgstr "Roland w trybie GS (wy³±cz mapowanie GM)"
#: gui/options.cpp:890
msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
@@ -942,11 +940,11 @@ msgstr ""
#: gui/saveload-dialog.cpp:166
msgid "List view"
-msgstr ""
+msgstr "Widok listy"
#: gui/saveload-dialog.cpp:167
msgid "Grid view"
-msgstr ""
+msgstr "Widok siatki"
#: gui/saveload-dialog.cpp:210 gui/saveload-dialog.cpp:358
msgid "No date saved"
@@ -986,31 +984,28 @@ msgstr "Zapis bez nazwy"
#: gui/saveload-dialog.cpp:546
msgid "Next"
-msgstr ""
+msgstr "Nastêpny"
#: gui/saveload-dialog.cpp:549
msgid "Prev"
-msgstr ""
+msgstr "Poprzedni"
#: gui/saveload-dialog.cpp:736
-#, fuzzy
msgid "New Save"
-msgstr "Zapisz"
+msgstr "Nowy zapis"
#: gui/saveload-dialog.cpp:736
-#, fuzzy
msgid "Create a new save game"
-msgstr "Nie uda³o siê zapisaæ stanu gry"
+msgstr "Stwórz nowy zapis"
#: gui/saveload-dialog.cpp:865
-#, fuzzy
msgid "Name: "
-msgstr "Nazwa:"
+msgstr "Nazwa: "
#: gui/saveload-dialog.cpp:937
#, c-format
msgid "Enter a description for slot %d:"
-msgstr ""
+msgstr "Podaj opis dla slotu %d:"
#: gui/themebrowser.cpp:44
msgid "Select a Theme"
@@ -1046,93 +1041,90 @@ msgid "Clear value"
msgstr "Wyczy¶æ"
#: gui/fluidsynth-dialog.cpp:67
-#, fuzzy
msgid "Reverb"
-msgstr "Nigdy"
+msgstr "Pog³os"
#: gui/fluidsynth-dialog.cpp:69 gui/fluidsynth-dialog.cpp:101
-#, fuzzy
msgid "Active"
-msgstr " (Aktywny)"
+msgstr "Aktywny"
#: gui/fluidsynth-dialog.cpp:71
msgid "Room:"
-msgstr ""
+msgstr "Przestrzeñ:"
#: gui/fluidsynth-dialog.cpp:78
msgid "Damp:"
-msgstr ""
+msgstr "T³umienie:"
#: gui/fluidsynth-dialog.cpp:85
msgid "Width:"
-msgstr ""
+msgstr "Szeroko¶æ:"
#: gui/fluidsynth-dialog.cpp:92 gui/fluidsynth-dialog.cpp:110
msgid "Level:"
-msgstr ""
+msgstr "Poziom:"
#: gui/fluidsynth-dialog.cpp:99
msgid "Chorus"
-msgstr ""
+msgstr "Chorus"
#: gui/fluidsynth-dialog.cpp:103
msgid "N:"
-msgstr ""
+msgstr "N:"
#: gui/fluidsynth-dialog.cpp:117
-#, fuzzy
msgid "Speed:"
-msgstr "Mowa"
+msgstr "Szybko¶æ:"
#: gui/fluidsynth-dialog.cpp:124
msgid "Depth:"
-msgstr ""
+msgstr "G³êbia:"
#: gui/fluidsynth-dialog.cpp:131
msgid "Type:"
-msgstr ""
+msgstr "Typ:"
#: gui/fluidsynth-dialog.cpp:134
msgid "Sine"
-msgstr ""
+msgstr "Sinus"
#: gui/fluidsynth-dialog.cpp:135
msgid "Triangle"
-msgstr ""
+msgstr "Trójk±t"
#: gui/fluidsynth-dialog.cpp:139
msgid "Interpolation:"
-msgstr ""
+msgstr "Interpolacja:"
#: gui/fluidsynth-dialog.cpp:142
msgid "None (fastest)"
-msgstr ""
+msgstr "Brak (najszybsze)"
#: gui/fluidsynth-dialog.cpp:143
msgid "Linear"
-msgstr ""
+msgstr "Liniowa"
#: gui/fluidsynth-dialog.cpp:144
msgid "Fourth-order"
-msgstr ""
+msgstr "Czterostopniowa"
#: gui/fluidsynth-dialog.cpp:145
msgid "Seventh-order"
-msgstr ""
+msgstr "Siedmiostopniowa"
#: gui/fluidsynth-dialog.cpp:149
msgid "Reset"
-msgstr ""
+msgstr "Reset"
#: gui/fluidsynth-dialog.cpp:149
msgid "Reset all FluidSynth settings to their default values."
-msgstr ""
+msgstr "Przywróæ domy¶lne warto¶ci wszystkich ustawieñ FluidSynth."
#: gui/fluidsynth-dialog.cpp:216
-#, fuzzy
msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
-msgstr "Na pewno chcesz powróciæ do launchera?"
+msgstr ""
+"Na pewno chcesz przywróciæ domy¶lne warto¶ci wszystkich ustawieñ FluidSynth?"
#: base/main.cpp:210
#, c-format
@@ -1317,7 +1309,7 @@ msgstr ""
#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:109
#: engines/mohawk/dialogs.cpp:170
msgid "~O~K"
-msgstr ""
+msgstr "~O~K"
#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:110
#: engines/mohawk/dialogs.cpp:171
@@ -1414,7 +1406,6 @@ msgid "Restore"
msgstr "Wznów"
#: engines/drascula/saveload.cpp:49
-#, fuzzy
msgid ""
"ScummVM found that you have old savefiles for Drascula that should be "
"converted.\n"
@@ -1424,8 +1415,7 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
-"ScummVM znalaz³ stare zapisy z Broken Sword 1, które nale¿y "
-"przekonwertowaæ.\n"
+"ScummVM znalaz³ stare zapisy z Drascula, które nale¿y przekonwertowaæ.\n"
"Stary format zapisu nie jest ju¿ obs³ugiwany. Nie bêdziesz móg³ wczytaæ "
"zapisów, je¶li ich nie przekonwertujesz.\n"
"\n"
@@ -2097,7 +2087,7 @@ msgstr "Kiedy Indy jest po prawej,"
#: engines/scumm/help.cpp:308
msgid "7, 4, and 1 are switched with"
-msgstr "7, 4, i 1 zostaj± zamienione"
+msgstr "7, 4 i 1 zostaj± zamienione"
#: engines/scumm/help.cpp:309
msgid "9, 6, and 3, respectively."
@@ -2240,13 +2230,12 @@ msgid "Failed to delete file."
msgstr "Nie uda³o siê usun±æ pliku."
#: engines/groovie/detection.cpp:312
-#, fuzzy
msgid "Fast movie speed"
-msgstr "Tryb szybki"
+msgstr "Przy¶pieszone filmy"
#: engines/groovie/detection.cpp:313
msgid "Play movies at an increased speed"
-msgstr ""
+msgstr "Odtwarzaj filmy ze zwiêkszon± prêdko¶ci±"
#: engines/groovie/script.cpp:420
msgid "Failed to save game"
@@ -2373,12 +2362,11 @@ msgstr ""
#: engines/queen/queen.cpp:59
msgid "Alternative intro"
-msgstr ""
+msgstr "Alternatywne intro"
#: engines/queen/queen.cpp:60
-#, fuzzy
msgid "Use an alternative game intro (CD version only)"
-msgstr "U¿yj intra z wersji dyskietkowej (tylko dla wersji CD)"
+msgstr "U¿yj alternatywnego intra (tylko dla wersji CD)"
#: engines/sky/compact.cpp:130
msgid ""
@@ -2483,13 +2471,15 @@ msgstr "Poka¿ etykiety obiektów przy najechaniu myszk±"
#: engines/teenagent/resources.cpp:94
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
-msgstr ""
+msgstr "Nie masz pliku 'teenagent.dat'. Pobierz go ze strony ScummVM"
#: engines/teenagent/resources.cpp:115
msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
+"Plik teenagent.dat jest skompresowany, a ScummVM nie zawiera obs³ugi zlib. "
+"Rozpakuj plik."
#: engines/parallaction/saveload.cpp:133
#, c-format
@@ -2542,44 +2532,43 @@ msgstr ""
#: engines/pegasus/pegasus.cpp:679
msgid "Invalid save file name"
-msgstr ""
+msgstr "Nieprawid³owa nazwa pliku zapisu"
#: engines/pegasus/pegasus.cpp:2445
msgid "Up/Zoom In/Move Forward/Open Doors"
-msgstr ""
+msgstr "Góra/Przybli¿/Ruch naprzód/Otwórz drzwi"
#: engines/pegasus/pegasus.cpp:2446
-#, fuzzy
msgid "Down/Zoom Out"
-msgstr "Przybli¿"
+msgstr "Dó³/Oddal"
#: engines/pegasus/pegasus.cpp:2449
msgid "Display/Hide Inventory Tray"
-msgstr ""
+msgstr "Poka¿/schowaj przedmioty"
#: engines/pegasus/pegasus.cpp:2450
msgid "Display/Hide Biochip Tray"
-msgstr ""
+msgstr "Poka¿/schowaj biochipy"
#: engines/pegasus/pegasus.cpp:2451
msgid "Action/Select"
-msgstr ""
+msgstr "Akcja/Wybór"
#: engines/pegasus/pegasus.cpp:2452
msgid "Toggle Center Data Display"
-msgstr ""
+msgstr "W³±cz/wy³±cz widok danych"
#: engines/pegasus/pegasus.cpp:2453
msgid "Display/Hide Info Screen"
-msgstr ""
+msgstr "Poka¿/schowaj ekran informacji"
#: engines/pegasus/pegasus.cpp:2454
msgid "Display/Hide Pause Menu"
-msgstr ""
+msgstr "Poka¿/schowaj menu pauzy"
#: engines/pegasus/pegasus.cpp:2455
msgid "???"
-msgstr ""
+msgstr "???"
#: audio/fmopl.cpp:49
msgid "MAME OPL emulator"
@@ -2856,15 +2845,15 @@ msgstr "Okno"
#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Normal"
-msgstr "OpenGL - normalny"
+msgstr "OpenGL (normalny)"
#: backends/graphics/opengl/opengl-graphics.cpp:136
msgid "OpenGL Conserve"
-msgstr "OpenGL - zachowanie proporcji"
+msgstr "OpenGL (zachowanie proporcji)"
#: backends/graphics/opengl/opengl-graphics.cpp:137
msgid "OpenGL Original"
-msgstr "OpenGL - oryginalny rozmiar"
+msgstr "OpenGL (oryginalny rozmiar)"
#: backends/graphics/openglsdl/openglsdl-graphics.cpp:415
msgid "Current display mode"
@@ -3194,7 +3183,7 @@ msgstr "Na pewno chcesz powróciæ do launchera?"
#: backends/events/default/default-events.cpp:193
msgid "Launcher"
-msgstr ""
+msgstr "Launcher"
#: backends/events/default/default-events.cpp:215
msgid "Do you really want to quit?"
@@ -3216,7 +3205,7 @@ msgstr "Dotkniêcie ekranu - klikniêcie PPM"
#: backends/events/gph/gph-events.cpp:433
#: backends/events/openpandora/op-events.cpp:172
msgid "Touchscreen 'Tap Mode' - Hover (No Click)"
-msgstr "Dotkniêcie ekranu - brak klikniêcia"
+msgstr "Dotkniêcie ekranu - przytrzymanie (brak klikniêcia)"
#: backends/events/gph/gph-events.cpp:410
msgid "Maximum Volume"
@@ -3235,9 +3224,8 @@ msgid "Decreasing Volume"
msgstr "Zmniejszenie g³o¶no¶ci"
#: backends/events/openpandora/op-events.cpp:174
-#, fuzzy
msgid "Touchscreen 'Tap Mode' - Hover (DPad Clicks)"
-msgstr "Dotkniêcie ekranu - brak klikniêcia"
+msgstr "Dotkniêcie ekranu - przytrzymanie (krzy¿ak klika)"
#: backends/updates/macosx/macosx-updates.mm:67
msgid "Check for Updates..."
diff --git a/ports.mk b/ports.mk
index 7a3bf0fabd..9b54b3533b 100644
--- a/ports.mk
+++ b/ports.mk
@@ -139,6 +139,14 @@ ifdef USE_FAAD
OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libfaad.a
endif
+ifdef USE_MPEG2
+OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libmpeg2.a
+endif
+
+ifdef USE_JPEG
+OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libjpeg.a
+endif
+
ifdef USE_ZLIB
OSX_ZLIB ?= $(STATICLIBPATH)/lib/libz.a
endif
@@ -310,15 +318,15 @@ else ifeq "$(CUR_BRANCH)" ""
$(error You must be on a release branch)
endif
@echo Creating Code::Blocks project files...
- @cd $(srcdir)/dists/codeblocks && ../../devtools/create_project/create_project ../.. --codeblocks >/dev/null && git add -f *.workspace *.cbp
+ @cd $(srcdir)/dists/codeblocks && ../../devtools/create_project/create_project ../.. --codeblocks >/dev/null && git add -f engines/plugins_table.h *.workspace *.cbp
@echo Creating MSVC8 project files...
- @cd $(srcdir)/dists/msvc8 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 8 >/dev/null && git add -f *.sln *.vcproj *.vsprops
+ @cd $(srcdir)/dists/msvc8 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 8 >/dev/null && git add -f engines/plugins_table.h *.sln *.vcproj *.vsprops
@echo Creating MSVC9 project files...
- @cd $(srcdir)/dists/msvc9 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 9 >/dev/null && git add -f *.sln *.vcproj *.vsprops
+ @cd $(srcdir)/dists/msvc9 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 9 >/dev/null && git add -f engines/plugins_table.h *.sln *.vcproj *.vsprops
@echo Creating MSVC10 project files...
- @cd $(srcdir)/dists/msvc10 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 10 >/dev/null && git add -f *.sln *.vcxproj *.vcxproj.filters *.props
+ @cd $(srcdir)/dists/msvc10 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 10 >/dev/null && git add -f engines/plugins_table.h *.sln *.vcxproj *.vcxproj.filters *.props
@echo Creating MSVC11 project files...
- @cd $(srcdir)/dists/msvc11 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 11 >/dev/null && git add -f *.sln *.vcxproj *.vcxproj.filters *.props
+ @cd $(srcdir)/dists/msvc11 && ../../devtools/create_project/create_project ../.. --msvc --msvc-version 11 >/dev/null && git add -f engines/plugins_table.h *.sln *.vcxproj *.vcxproj.filters *.props
@echo
@echo All is done.
@echo Now run
diff --git a/test/audio/raw.h b/test/audio/raw.h
index e7cb42ac44..3792f82674 100644
--- a/test/audio/raw.h
+++ b/test/audio/raw.h
@@ -1,6 +1,7 @@
#include <cxxtest/TestSuite.h>
#include "audio/decoders/raw.h"
+#include "audio/audiostream.h"
#include "helper.h"
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..36fe83fa19 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,11 @@ 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_INFO MKTAG('I','N','F','O')
+#define ID_ISFT MKTAG('I','S','F','T')
+#define ID_DISP MKTAG('D','I','S','P')
+#define ID_PRMI MKTAG('P','R','M','I')
+#define ID_STRN MKTAG('s','t','r','n')
// Codec tags
#define ID_RLE MKTAG('R','L','E',' ')
@@ -75,49 +79,63 @@ 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);
- return (c >= 'a' && c <= 'f') ? c - 'a' + 10 : c - '0';
+// Stream Types
+enum {
+ kStreamTypePaletteChange = MKTAG16('p', 'c'),
+ kStreamTypeRawVideo = MKTAG16('d', 'b'),
+ kStreamTypeAudio = MKTAG16('w', 'b')
+};
+
+
+AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) {
+ initCommon();
}
-static byte getStreamIndex(uint32 tag) {
- return char2num((tag >> 24) & 0xFF) << 4 | char2num((tag >> 16) & 0xFF);
+AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType)
+ : _frameRateOverride(frameRateOverride), _soundType(soundType) {
+ initCommon();
+}
+
+AVIDecoder::~AVIDecoder() {
+ close();
}
-static uint16 getStreamType(uint32 tag) {
- return tag & 0xffff;
+AVIDecoder::AVIAudioTrack *AVIDecoder::createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo) {
+ return new AVIAudioTrack(sHeader, wvInfo, _soundType);
}
-AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) {
+void AVIDecoder::initCommon() {
_decodedHeader = false;
+ _foundMovieList = false;
+ _movieListStart = 0;
+ _movieListEnd = 0;
_fileStream = 0;
- memset(&_ixInfo, 0, sizeof(_ixInfo));
memset(&_header, 0, sizeof(_header));
}
-AVIDecoder::~AVIDecoder() {
- close();
+bool AVIDecoder::isSeekable() const {
+ // Only videos with an index can seek
+ // Anyone else who wants to seek is crazy.
+ return isVideoLoaded() && !_indexEntries.empty();
}
-void AVIDecoder::runHandle(uint32 tag) {
- assert(_fileStream);
+bool AVIDecoder::parseNextChunk() {
+ uint32 tag = _fileStream->readUint32BE();
+ uint32 size = _fileStream->readUint32LE();
+
if (_fileStream->eos())
- return;
+ return false;
debug(3, "Decoding tag %s", tag2str(tag));
switch (tag) {
- case ID_RIFF:
- /*_filesize = */_fileStream->readUint32LE();
- if (_fileStream->readUint32BE() != ID_AVI)
- error("RIFF file is not an AVI video");
- break;
case ID_LIST:
- handleList();
+ handleList(size);
break;
case ID_AVIH:
- _header.size = _fileStream->readUint32LE();
+ _header.size = size;
_header.microSecondsPerFrame = _fileStream->readUint32LE();
_header.maxBytesPerSecond = _fileStream->readUint32LE();
_header.padding = _fileStream->readUint32LE();
@@ -132,50 +150,67 @@ void AVIDecoder::runHandle(uint32 tag) {
_fileStream->skip(16);
break;
case ID_STRH:
- handleStreamHeader();
+ handleStreamHeader(size);
break;
case ID_STRD: // Extra stream info, safe to ignore
case ID_VEDT: // Unknown, safe to ignore
case ID_JUNK: // Alignment bytes, should be ignored
- {
- uint32 junkSize = _fileStream->readUint32LE();
- _fileStream->skip(junkSize + (junkSize & 1)); // Alignment
- } break;
+ case ID_ISFT: // Metadata, safe to ignore
+ case ID_DISP: // Metadata, should be safe to ignore
+ case ID_STRN: // Metadata, safe to ignore
+ skipChunk(size);
+ break;
case ID_IDX1:
- _ixInfo.size = _fileStream->readUint32LE();
- _ixInfo.indices = new OldIndex::Index[_ixInfo.size / 16];
- debug(0, "%d Indices", (_ixInfo.size / 16));
- for (uint32 i = 0; i < (_ixInfo.size / 16); i++) {
- _ixInfo.indices[i].id = _fileStream->readUint32BE();
- _ixInfo.indices[i].flags = _fileStream->readUint32LE();
- _ixInfo.indices[i].offset = _fileStream->readUint32LE();
- _ixInfo.indices[i].size = _fileStream->readUint32LE();
- debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size);
- }
+ readOldIndex(size);
break;
default:
error("Unknown tag \'%s\' found", tag2str(tag));
}
+
+ return true;
}
-void AVIDecoder::handleList() {
- uint32 listSize = _fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes
+void AVIDecoder::skipChunk(uint32 size) {
+ // Make sure we're aligned on a word boundary
+ _fileStream->skip(size + (size & 1));
+}
+
+void AVIDecoder::handleList(uint32 listSize) {
uint32 listType = _fileStream->readUint32BE();
+ listSize -= 4; // Subtract away listType's 4 bytes
uint32 curPos = _fileStream->pos();
debug(0, "Found LIST of type %s", tag2str(listType));
- while ((_fileStream->pos() - curPos) < listSize)
- runHandle(_fileStream->readUint32BE());
-
- // We now have all the header data
- if (listType == ID_HDRL)
+ switch (listType) {
+ case ID_MOVI: // Movie List
+ // We found the movie block
+ _foundMovieList = true;
+ _movieListStart = curPos;
+ _movieListEnd = _movieListStart + listSize + (listSize & 1);
+ _fileStream->skip(listSize);
+ return;
+ case ID_HDRL: // Header List
+ // Mark the header as decoded
_decodedHeader = true;
+ break;
+ case ID_INFO: // Metadata
+ case ID_PRMI: // Unknown metadata, should be safe to ignore
+ // Ignore metadata
+ _fileStream->skip(listSize);
+ return;
+ case ID_STRL: // Stream list
+ default: // (Just hope we can parse it!)
+ break;
+ }
+
+ while ((_fileStream->pos() - curPos) < listSize)
+ parseNextChunk();
}
-void AVIDecoder::handleStreamHeader() {
+void AVIDecoder::handleStreamHeader(uint32 size) {
AVIStreamHeader sHeader;
- sHeader.size = _fileStream->readUint32LE();
+ sHeader.size = size;
sHeader.streamType = _fileStream->readUint32BE();
if (sHeader.streamType == ID_MIDS || sHeader.streamType == ID_TXTS)
@@ -203,6 +238,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();
@@ -222,21 +262,22 @@ void AVIDecoder::handleStreamHeader() {
if (sHeader.streamHandler == 0)
sHeader.streamHandler = bmInfo.compression;
- AVIVideoTrack *track = new AVIVideoTrack(_header.totalFrames, sHeader, bmInfo);
+ byte *initialPalette = 0;
if (bmInfo.bitCount == 8) {
- byte *palette = const_cast<byte *>(track->getPalette());
+ initialPalette = new byte[256 * 3];
+ memset(initialPalette, 0, 256 * 3);
+
+ byte *palette = initialPalette;
for (uint32 i = 0; i < bmInfo.clrUsed; i++) {
palette[i * 3 + 2] = _fileStream->readByte();
palette[i * 3 + 1] = _fileStream->readByte();
palette[i * 3] = _fileStream->readByte();
_fileStream->readByte();
}
-
- track->markPaletteDirty();
}
- addTrack(track);
+ addTrack(new AVIVideoTrack(_header.totalFrames, sHeader, bmInfo, initialPalette));
} else if (sHeader.streamType == ID_AUDS) {
PCMWaveFormat wvInfo;
wvInfo.tag = _fileStream->readUint16LE();
@@ -251,7 +292,7 @@ void AVIDecoder::handleStreamHeader() {
if (wvInfo.channels == 2)
sHeader.sampleSize /= 2;
- addTrack(new AVIAudioTrack(sHeader, wvInfo, _soundType));
+ addTrack(createAudioTrack(sHeader, wvInfo));
}
// Ensure that we're at the end of the chunk
@@ -261,30 +302,41 @@ void AVIDecoder::handleStreamHeader() {
bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
close();
- _fileStream = stream;
- _decodedHeader = false;
+ uint32 riffTag = stream->readUint32BE();
+ if (riffTag != ID_RIFF) {
+ warning("Failed to find RIFF header");
+ return false;
+ }
- // Read chunks until we have decoded the header
- while (!_decodedHeader)
- runHandle(_fileStream->readUint32BE());
+ /* uint32 fileSize = */ stream->readUint32LE();
+ uint32 riffType = stream->readUint32BE();
- uint32 nextTag = _fileStream->readUint32BE();
+ if (riffType != ID_AVI) {
+ warning("RIFF not an AVI file");
+ return false;
+ }
- // Throw out any JUNK section
- if (nextTag == ID_JUNK) {
- runHandle(ID_JUNK);
- nextTag = _fileStream->readUint32BE();
+ _fileStream = stream;
+
+ // Go through all chunks in the file
+ while (parseNextChunk())
+ ;
+
+ if (!_decodedHeader) {
+ warning("Failed to parse AVI header");
+ close();
+ 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");
+ if (!_foundMovieList) {
+ warning("Failed to find 'MOVI' list");
+ close();
+ return false;
}
+ // Seek back to the start of the MOVI list
+ _fileStream->seek(_movieListStart);
+
return true;
}
@@ -294,33 +346,46 @@ void AVIDecoder::close() {
delete _fileStream;
_fileStream = 0;
_decodedHeader = false;
+ _foundMovieList = false;
+ _movieListStart = 0;
+ _movieListEnd = 0;
- delete[] _ixInfo.indices;
- memset(&_ixInfo, 0, sizeof(_ixInfo));
+ _indexEntries.clear();
memset(&_header, 0, sizeof(_header));
}
void AVIDecoder::readNextPacket() {
+ if ((uint32)_fileStream->pos() >= _movieListEnd) {
+ // Ugh, reached the end premature.
+ forceVideoEnd();
+ return;
+ }
+
uint32 nextTag = _fileStream->readUint32BE();
+ uint32 size = _fileStream->readUint32LE();
- if (_fileStream->eos())
+ if (_fileStream->eos()) {
+ // Also premature end.
+ forceVideoEnd();
return;
+ }
if (nextTag == ID_LIST) {
// A list of audio/video chunks
- uint32 listSize = _fileStream->readUint32LE() - 4;
int32 startPos = _fileStream->pos();
if (_fileStream->readUint32BE() != ID_REC)
error("Expected 'rec ' LIST");
+ size -= 4; // subtract list type
+
// Decode chunks in the list
- while (_fileStream->pos() < startPos + (int32)listSize)
+ while (_fileStream->pos() < startPos + (int32)size)
readNextPacket();
return;
} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
- runHandle(nextTag);
+ skipChunk(size);
return;
}
@@ -329,16 +394,15 @@ void AVIDecoder::readNextPacket() {
if (!track)
error("Cannot get track from tag '%s'", tag2str(nextTag));
- uint32 chunkSize = _fileStream->readUint32LE();
Common::SeekableReadStream *chunk = 0;
- if (chunkSize != 0) {
- chunk = _fileStream->readStream(chunkSize);
- _fileStream->skip(chunkSize & 1);
+ if (size != 0) {
+ chunk = _fileStream->readStream(size);
+ _fileStream->skip(size & 1);
}
if (track->getTrackType() == Track::kTrackTypeAudio) {
- if (getStreamType(nextTag) != MKTAG16('w', 'b'))
+ if (getStreamType(nextTag) != kStreamTypeAudio)
error("Invalid audio track tag '%s'", tag2str(nextTag));
assert(chunk);
@@ -346,29 +410,10 @@ void AVIDecoder::readNextPacket() {
} else {
AVIVideoTrack *videoTrack = (AVIVideoTrack *)track;
- if (getStreamType(nextTag) == MKTAG16('p', 'c')) {
+ if (getStreamType(nextTag) == kStreamTypePaletteChange) {
// Palette Change
- assert(chunk);
- byte firstEntry = chunk->readByte();
- uint16 numEntries = chunk->readByte();
- chunk->readUint16LE(); // Reserved
-
- // 0 entries means all colors are going to be changed
- if (numEntries == 0)
- numEntries = 256;
-
- byte *palette = const_cast<byte *>(videoTrack->getPalette());
-
- for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) {
- palette[i * 3] = chunk->readByte();
- palette[i * 3 + 1] = chunk->readByte();
- palette[i * 3 + 2] = chunk->readByte();
- chunk->readByte(); // Flags that don't serve us any purpose
- }
-
- delete chunk;
- videoTrack->markPaletteDirty();
- } else if (getStreamType(nextTag) == MKTAG16('d', 'b')) {
+ videoTrack->loadPaletteFromChunk(chunk);
+ } else if (getStreamType(nextTag) == kStreamTypeRawVideo) {
// TODO: Check if this really is uncompressed. Many videos
// falsely put compressed data in here.
error("Uncompressed AVI frame found");
@@ -379,17 +424,273 @@ void AVIDecoder::readNextPacket() {
}
}
-AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader)
- : _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader) {
- memset(_palette, 0, sizeof(_palette));
+bool AVIDecoder::rewind() {
+ if (!VideoDecoder::rewind())
+ return false;
+
+ _fileStream->seek(_movieListStart);
+ return true;
+}
+
+bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
+ // Can't seek beyond the end
+ if (time > getDuration())
+ return false;
+
+ // Track down our video track (optionally audio too).
+ // We only support seeking with one track right now.
+ AVIVideoTrack *videoTrack = 0;
+ AVIAudioTrack *audioTrack = 0;
+ int videoIndex = -1;
+ int audioIndex = -1;
+ uint trackID = 0;
+
+ for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, trackID++) {
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
+ if (videoTrack) {
+ // Already have one
+ // -> Not supported
+ return false;
+ }
+
+ videoTrack = (AVIVideoTrack *)*it;
+ videoIndex = trackID;
+ } else if ((*it)->getTrackType() == Track::kTrackTypeAudio) {
+ if (audioTrack) {
+ // Already have one
+ // -> Not supported
+ return false;
+ }
+
+ audioTrack = (AVIAudioTrack *)*it;
+ audioIndex = trackID;
+ }
+ }
+
+ // Need a video track to go forwards
+ // If there isn't a video track, why would anyone be using AVI then?
+ if (!videoTrack)
+ return false;
+
+ // If we seek directly to the end, just mark the tracks as over
+ if (time == getDuration()) {
+ videoTrack->setCurFrame(videoTrack->getFrameCount() - 1);
+
+ if (audioTrack)
+ audioTrack->resetStream();
+
+ return true;
+ }
+
+ // Get the frame we should be on at this time
+ uint frame = videoTrack->getFrameAtTime(time);
+
+ // Reset any palette, if necessary
+ videoTrack->useInitialPalette();
+
+ int lastKeyFrame = -1;
+ int frameIndex = -1;
+ int lastRecord = -1;
+ uint curFrame = 0;
+
+ // Go through and figure out where we should be
+ // If there's a palette, we need to find the palette too
+ for (uint32 i = 0; i < _indexEntries.size(); i++) {
+ const OldIndex &index = _indexEntries[i];
+
+ if (index.id == ID_REC) {
+ // Keep track of any records we find
+ lastRecord = i;
+ } else {
+ if (getStreamIndex(index.id) != videoIndex)
+ continue;
+
+ uint16 streamType = getStreamType(index.id);
+
+ if (streamType == kStreamTypePaletteChange) {
+ // We need to handle any palette change we see since there's no
+ // flag to tell if this is a "key" palette.
+ // Decode the palette
+ _fileStream->seek(_indexEntries[i].offset + 8);
+ Common::SeekableReadStream *chunk = 0;
+
+ if (_indexEntries[i].size != 0)
+ chunk = _fileStream->readStream(_indexEntries[i].size);
+
+ videoTrack->loadPaletteFromChunk(chunk);
+ } else {
+ // Check to see if this is a keyframe
+ // The first frame has to be a keyframe
+ if ((_indexEntries[i].flags & AVIIF_INDEX) || curFrame == 0)
+ lastKeyFrame = i;
+
+ // Did we find the target frame?
+ if (frame == curFrame) {
+ frameIndex = i;
+ break;
+ }
+
+ curFrame++;
+ }
+ }
+ }
+
+ if (frameIndex < 0) // This shouldn't happen.
+ return false;
+
+ if (audioTrack) {
+ // We need to find where the start of audio should be.
+ // Which is exactly 'initialFrames' audio chunks back from where
+ // our found frame is.
+
+ // Recreate the audio stream
+ audioTrack->resetStream();
+
+ uint framesNeeded = _header.initialFrames;
+ uint startAudioChunk = 0;
+ int startAudioSearch = (lastRecord < 0) ? (frameIndex - 1) : (lastRecord - 1);
+
+ for (int i = startAudioSearch; i >= 0; i--) {
+ if (getStreamIndex(_indexEntries[i].id) != audioIndex)
+ continue;
+
+ assert(getStreamType(_indexEntries[i].id) == kStreamTypeAudio);
+
+ framesNeeded--;
+
+ if (framesNeeded == 0) {
+ startAudioChunk = i;
+ break;
+ }
+ }
+
+ // Now go forward and queue them all
+ for (int i = startAudioChunk; i <= startAudioSearch; i++) {
+ if (_indexEntries[i].id == ID_REC)
+ continue;
+
+ if (getStreamIndex(_indexEntries[i].id) != audioIndex)
+ continue;
+
+ assert(getStreamType(_indexEntries[i].id) == kStreamTypeAudio);
+
+ _fileStream->seek(_indexEntries[i].offset + 8);
+ Common::SeekableReadStream *chunk = _fileStream->readStream(_indexEntries[i].size);
+ audioTrack->queueSound(chunk);
+ }
+
+ // Skip any audio to bring us to the right time
+ audioTrack->skipAudio(time, videoTrack->getFrameTime(frame));
+ }
+
+ // Decode from keyFrame to curFrame - 1
+ for (int i = lastKeyFrame; i < frameIndex; i++) {
+ if (_indexEntries[i].id == ID_REC)
+ continue;
+
+ if (getStreamIndex(_indexEntries[i].id) != videoIndex)
+ continue;
+
+ uint16 streamType = getStreamType(_indexEntries[i].id);
+
+ // Ignore palettes, they were already handled
+ if (streamType == kStreamTypePaletteChange)
+ continue;
+
+ // Frame, hopefully
+ _fileStream->seek(_indexEntries[i].offset + 8);
+ Common::SeekableReadStream *chunk = 0;
+
+ if (_indexEntries[i].size != 0)
+ chunk = _fileStream->readStream(_indexEntries[i].size);
+
+ videoTrack->decodeFrame(chunk);
+ }
+
+ // Seek to the right spot
+ // To the beginning of the last record, or frame if that doesn't exist
+ if (lastRecord >= 0)
+ _fileStream->seek(_indexEntries[lastRecord].offset);
+ else
+ _fileStream->seek(_indexEntries[frameIndex].offset);
+
+ videoTrack->setCurFrame((int)frame - 1);
+
+ return true;
+}
+
+byte AVIDecoder::getStreamIndex(uint32 tag) const {
+ char string[3];
+ WRITE_BE_UINT16(string, tag >> 16);
+ string[2] = 0;
+ return strtol(string, 0, 16);
+}
+
+void AVIDecoder::readOldIndex(uint32 size) {
+ uint32 entryCount = size / 16;
+
+ debug(0, "Old Index: %d entries", entryCount);
+
+ if (entryCount == 0)
+ return;
+
+ // Read the first index separately
+ OldIndex firstEntry;
+ firstEntry.id = _fileStream->readUint32BE();
+ firstEntry.flags = _fileStream->readUint32LE();
+ firstEntry.offset = _fileStream->readUint32LE();
+ firstEntry.size = _fileStream->readUint32LE();
+
+ // Check if the offset is already absolute
+ // If it's absolute, the offset will equal the start of the movie list
+ bool isAbsolute = firstEntry.offset == _movieListStart;
+
+ debug(1, "Old index is %s", isAbsolute ? "absolute" : "relative");
+
+ if (!isAbsolute)
+ firstEntry.offset += _movieListStart - 4;
+
+ debug(0, "Index 0: Tag '%s', Offset = %d, Size = %d (Flags = %d)", tag2str(firstEntry.id), firstEntry.offset, firstEntry.size, firstEntry.flags);
+ _indexEntries.push_back(firstEntry);
+
+ for (uint32 i = 1; i < entryCount; i++) {
+ OldIndex indexEntry;
+ indexEntry.id = _fileStream->readUint32BE();
+ indexEntry.flags = _fileStream->readUint32LE();
+ indexEntry.offset = _fileStream->readUint32LE();
+ indexEntry.size = _fileStream->readUint32LE();
+
+ // Adjust to absolute, if necessary
+ if (!isAbsolute)
+ indexEntry.offset += _movieListStart - 4;
+
+ _indexEntries.push_back(indexEntry);
+ debug(0, "Index %d: Tag '%s', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags);
+ }
+}
+
+void AVIDecoder::forceVideoEnd() {
+ // Horrible AVI video has a premature end
+ // Force the frame to be the last frame
+ debug(0, "Forcing end of AVI video");
+
+ for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo)
+ ((AVIVideoTrack *)*it)->forceTrackEnd();
+}
+
+AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader, byte *initialPalette)
+ : _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader), _initialPalette(initialPalette) {
_videoCodec = createCodec();
- _dirtyPalette = false;
_lastFrame = 0;
_curFrame = -1;
+
+ useInitialPalette();
}
AVIDecoder::AVIVideoTrack::~AVIVideoTrack() {
delete _videoCodec;
+ delete[] _initialPalette;
}
void AVIDecoder::AVIVideoTrack::decodeFrame(Common::SeekableReadStream *stream) {
@@ -412,6 +713,47 @@ Graphics::PixelFormat AVIDecoder::AVIVideoTrack::getPixelFormat() const {
return Graphics::PixelFormat();
}
+void AVIDecoder::AVIVideoTrack::loadPaletteFromChunk(Common::SeekableReadStream *chunk) {
+ assert(chunk);
+ byte firstEntry = chunk->readByte();
+ uint16 numEntries = chunk->readByte();
+ chunk->readUint16LE(); // Reserved
+
+ // 0 entries means all colors are going to be changed
+ if (numEntries == 0)
+ numEntries = 256;
+
+ for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) {
+ _palette[i * 3] = chunk->readByte();
+ _palette[i * 3 + 1] = chunk->readByte();
+ _palette[i * 3 + 2] = chunk->readByte();
+ chunk->readByte(); // Flags that don't serve us any purpose
+ }
+
+ delete chunk;
+ _dirtyPalette = true;
+}
+
+void AVIDecoder::AVIVideoTrack::useInitialPalette() {
+ _dirtyPalette = false;
+
+ if (_initialPalette) {
+ memcpy(_palette, _initialPalette, sizeof(_palette));
+ _dirtyPalette = true;
+ }
+}
+
+bool AVIDecoder::AVIVideoTrack::rewind() {
+ _curFrame = -1;
+
+ useInitialPalette();
+
+ delete _videoCodec;
+ _videoCodec = createCodec();
+ _lastFrame = 0;
+ return true;
+}
+
Codec *AVIDecoder::AVIVideoTrack::createCodec() {
switch (_vidsHeader.streamHandler) {
case ID_CRAM:
@@ -428,6 +770,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));
}
@@ -435,6 +781,10 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() {
return 0;
}
+void AVIDecoder::AVIVideoTrack::forceTrackEnd() {
+ _curFrame = _frameCount - 1;
+}
+
AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType)
: _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType) {
_audStream = createAudioStream();
@@ -469,6 +819,31 @@ void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
}
}
+void AVIDecoder::AVIAudioTrack::skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime) {
+ Audio::Timestamp timeDiff = time.convertToFramerate(_wvInfo.samplesPerSec) - frameTime.convertToFramerate(_wvInfo.samplesPerSec);
+ int skipFrames = timeDiff.totalNumberOfFrames();
+
+ if (skipFrames <= 0)
+ return;
+
+ if (_audStream->isStereo())
+ skipFrames *= 2;
+
+ int16 *tempBuffer = new int16[skipFrames];
+ _audStream->readBuffer(tempBuffer, skipFrames);
+ delete[] tempBuffer;
+}
+
+void AVIDecoder::AVIAudioTrack::resetStream() {
+ delete _audStream;
+ _audStream = createAudioStream();
+}
+
+bool AVIDecoder::AVIAudioTrack::rewind() {
+ resetStream();
+ return true;
+}
+
Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const {
return _audStream;
}
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 34a67f4c28..882cce30de 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -20,10 +20,10 @@
*
*/
-#ifndef VIDEO_AVI_PLAYER_H
-#define VIDEO_AVI_PLAYER_H
+#ifndef VIDEO_AVI_DECODER_H
+#define VIDEO_AVI_DECODER_H
-#include "common/endian.h"
+#include "common/array.h"
#include "common/rational.h"
#include "common/rect.h"
#include "common/str.h"
@@ -52,10 +52,14 @@ class Codec;
*
* Video decoder used in engines:
* - sci
+ * - sword1
+ * - sword2
+ * - zvision
*/
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);
@@ -63,10 +67,14 @@ public:
uint16 getWidth() const { return _header.width; }
uint16 getHeight() const { return _header.height; }
+ bool rewind();
+ bool isRewindable() const { return true; }
+ bool isSeekable() const;
+
protected:
void readNextPacket();
+ bool seekIntern(const Audio::Timestamp &time);
-private:
struct BitmapInfoHeader {
uint32 size;
uint32 width;
@@ -99,13 +107,10 @@ private:
};
struct OldIndex {
+ uint32 id;
+ uint32 flags;
+ uint32 offset;
uint32 size;
- struct Index {
- uint32 id;
- uint32 flags;
- uint32 offset;
- uint32 size;
- } *indices;
};
// Index Flags
@@ -157,10 +162,11 @@ private:
class AVIVideoTrack : public FixedRateVideoTrack {
public:
- AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader);
+ AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader, byte *initialPalette = 0);
~AVIVideoTrack();
void decodeFrame(Common::SeekableReadStream *stream);
+ void forceTrackEnd();
uint16 getWidth() const { return _bmInfo.width; }
uint16 getHeight() const { return _bmInfo.height; }
@@ -170,7 +176,12 @@ private:
const Graphics::Surface *decodeNextFrame() { return _lastFrame; }
const byte *getPalette() const { _dirtyPalette = false; return _palette; }
bool hasDirtyPalette() const { return _dirtyPalette; }
- void markPaletteDirty() { _dirtyPalette = true; }
+ void setCurFrame(int frame) { _curFrame = frame; }
+ void loadPaletteFromChunk(Common::SeekableReadStream *chunk);
+ void useInitialPalette();
+
+ bool isRewindable() const { return true; }
+ bool rewind();
protected:
Common::Rational getFrameRate() const { return Common::Rational(_vidsHeader.rate, _vidsHeader.scale); }
@@ -179,6 +190,7 @@ private:
AVIStreamHeader _vidsHeader;
BitmapInfoHeader _bmInfo;
byte _palette[3 * 256];
+ byte *_initialPalette;
mutable bool _dirtyPalette;
int _frameCount, _curFrame;
@@ -192,13 +204,17 @@ private:
AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType);
~AVIAudioTrack();
- void queueSound(Common::SeekableReadStream *stream);
+ virtual void queueSound(Common::SeekableReadStream *stream);
Audio::Mixer::SoundType getSoundType() const { return _soundType; }
+ void skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime);
+ void resetStream();
+
+ bool isRewindable() const { return true; }
+ bool rewind();
protected:
Audio::AudioStream *getAudioStream() const;
- private:
// Audio Codecs
enum {
kWaveFormatNone = 0,
@@ -215,17 +231,30 @@ private:
Audio::QueuingAudioStream *createAudioStream();
};
- OldIndex _ixInfo;
AVIHeader _header;
+ void readOldIndex(uint32 size);
+ Common::Array<OldIndex> _indexEntries;
+
Common::SeekableReadStream *_fileStream;
bool _decodedHeader;
+ bool _foundMovieList;
+ uint32 _movieListStart, _movieListEnd;
Audio::Mixer::SoundType _soundType;
+ Common::Rational _frameRateOverride;
+ void initCommon();
- void runHandle(uint32 tag);
- void handleList();
- void handleStreamHeader();
+ bool parseNextChunk();
+ void skipChunk(uint32 size);
+ void handleList(uint32 listSize);
+ void handleStreamHeader(uint32 size);
+ uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; }
+ byte getStreamIndex(uint32 tag) const;
+ void forceVideoEnd();
+
+public:
+ virtual AVIAudioTrack *createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo);
};
} // End of namespace Video
diff --git a/video/codecs/cdtoons.cpp b/video/codecs/cdtoons.cpp
index 528cee8094..68925ed0db 100644
--- a/video/codecs/cdtoons.cpp
+++ b/video/codecs/cdtoons.cpp
@@ -298,7 +298,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
for (uint i = 0; i < actions.size(); i++) {
CDToonsAction &action = actions[i];
if (i == 0 && action.blockId == 0)
- memset(_surface->pixels, backgroundColor, _surface->w * _surface->h);
+ memset(_surface->getPixels(), backgroundColor, _surface->w * _surface->h);
if (!_blocks.contains(action.blockId))
continue;
if (!action.rect.right)
diff --git a/video/codecs/cinepak.cpp b/video/codecs/cinepak.cpp
index bcf0cf1180..a7782f4192 100644
--- a/video/codecs/cinepak.cpp
+++ b/video/codecs/cinepak.cpp
@@ -41,11 +41,11 @@ namespace Video {
byte b = _clipTable[lum + (u << 1)]; \
\
if (_pixelFormat.bytesPerPixel == 2) \
- *((uint16 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ *((uint16 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
else \
- *((uint32 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ *((uint32 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
} else \
- *((byte *)_curFrame.surface->pixels + offset) = lum
+ *((byte *)_curFrame.surface->getPixels() + offset) = lum
CinepakDecoder::CinepakDecoder(int bitsPerPixel) : Codec() {
_curFrame.surface = NULL;
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..3560f4b8b7
--- /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) || defined (__SYMBIAN32__)
+ 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/codecs/msrle.cpp b/video/codecs/msrle.cpp
index fa03a59efd..2f2ac0334f 100644
--- a/video/codecs/msrle.cpp
+++ b/video/codecs/msrle.cpp
@@ -53,7 +53,7 @@ void MSRLEDecoder::decode8(Common::SeekableReadStream *stream) {
int x = 0;
int y = _surface->h - 1;
- byte *data = (byte *) _surface->pixels;
+ byte *data = (byte *) _surface->getPixels();
uint16 width = _surface->w;
uint16 height = _surface->h;
diff --git a/video/codecs/msvideo1.cpp b/video/codecs/msvideo1.cpp
index 06e4640025..409d588ddf 100644
--- a/video/codecs/msvideo1.cpp
+++ b/video/codecs/msvideo1.cpp
@@ -48,7 +48,7 @@ MSVideo1Decoder::~MSVideo1Decoder() {
void MSVideo1Decoder::decode8(Common::SeekableReadStream *stream) {
byte colors[8];
- byte *pixels = (byte *)_surface->pixels;
+ byte *pixels = (byte *)_surface->getPixels();
uint16 stride = _surface->w;
int skipBlocks = 0;
diff --git a/video/codecs/qtrle.cpp b/video/codecs/qtrle.cpp
index d2cdea27de..1f1fee7997 100644
--- a/video/codecs/qtrle.cpp
+++ b/video/codecs/qtrle.cpp
@@ -61,7 +61,7 @@ QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Cod
void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
while (linesToChange) {
CHECK_STREAM_PTR(2);
@@ -105,7 +105,7 @@ void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, ui
void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
byte numPixels = (bpp == 4) ? 8 : 16;
while (linesToChange--) {
@@ -165,7 +165,7 @@ void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr,
void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -210,7 +210,7 @@ void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, ui
void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint16 *rgb = (uint16 *)_surface->pixels;
+ uint16 *rgb = (uint16 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -248,7 +248,7 @@ void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, u
void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint32 *rgb = (uint32 *)_surface->pixels;
+ uint32 *rgb = (uint32 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -294,7 +294,7 @@ void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, u
void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint32 *rgb = (uint32 *)_surface->pixels;
+ uint32 *rgb = (uint32 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
diff --git a/video/codecs/rpza.cpp b/video/codecs/rpza.cpp
index 0a9f87747e..17a2c53d9b 100644
--- a/video/codecs/rpza.cpp
+++ b/video/codecs/rpza.cpp
@@ -58,7 +58,7 @@ RPZADecoder::~RPZADecoder() {
#define PUT_PIXEL(color) \
if ((int32)blockPtr < _surface->w * _surface->h) \
- WRITE_UINT16((uint16 *)_surface->pixels + blockPtr, color); \
+ WRITE_UINT16((uint16 *)_surface->getPixels() + blockPtr, color); \
blockPtr++
const Graphics::Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) {
diff --git a/video/codecs/smc.cpp b/video/codecs/smc.cpp
index 2eedb62a0f..c0f8152547 100644
--- a/video/codecs/smc.cpp
+++ b/video/codecs/smc.cpp
@@ -56,7 +56,7 @@ SMCDecoder::~SMCDecoder() {
}
const Graphics::Surface *SMCDecoder::decodeImage(Common::SeekableReadStream *stream) {
- byte *pixels = (byte *)_surface->pixels;
+ byte *pixels = (byte *)_surface->getPixels();
uint32 numBlocks = 0;
uint32 colorFlags = 0;
diff --git a/video/codecs/truemotion1.cpp b/video/codecs/truemotion1.cpp
index e475c8426c..720e86a4ff 100644
--- a/video/codecs/truemotion1.cpp
+++ b/video/codecs/truemotion1.cpp
@@ -400,11 +400,14 @@ void TrueMotion1Decoder::decode16() {
const Graphics::Surface *TrueMotion1Decoder::decodeImage(Common::SeekableReadStream *stream) {
decodeHeader(stream);
- if (compressionTypes[_header.compression].algorithm == ALGO_NOP)
+ if (compressionTypes[_header.compression].algorithm == ALGO_NOP) {
+ delete[] _buf;
return 0;
+ }
if (compressionTypes[_header.compression].algorithm == ALGO_RGB24H) {
warning("Unhandled TrueMotion1 24bpp frame");
+ delete[] _buf;
return 0;
} else
decode16();
diff --git a/video/codecs/truemotion1.h b/video/codecs/truemotion1.h
index b2a35cf873..6ac09af24b 100644
--- a/video/codecs/truemotion1.h
+++ b/video/codecs/truemotion1.h
@@ -22,8 +22,8 @@
// Based on the TrueMotion 1 decoder by Alex Beregszaszi & Mike Melanson in FFmpeg
-// Only compile if SCI32 is enabled or if we're building dynamic modules
-#if defined(ENABLE_SCI32) || defined(DYNAMIC_MODULES)
+// Only compile if SCI32 is enabled, ZVISION is enabled, or if we're building dynamic modules
+#if defined(ENABLE_SCI32) || defined(ENABLE_ZVISION) || defined(DYNAMIC_MODULES)
#ifndef VIDEO_CODECS_TRUEMOTION1_H
#define VIDEO_CODECS_TRUEMOTION1_H
diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp
index d24a021f3b..024e479bf7 100644
--- a/video/coktel_decoder.cpp
+++ b/video/coktel_decoder.cpp
@@ -97,12 +97,8 @@ void CoktelDecoder::setSurfaceMemory(void *mem, uint16 width, uint16 height, uin
assert(bpp == getPixelFormat().bytesPerPixel);
// Create a surface over this memory
- _surface.w = width;
- _surface.h = height;
- _surface.pitch = width * bpp;
- _surface.pixels = mem;
// TODO: Check whether it is fine to assume we want the setup PixelFormat.
- _surface.format = getPixelFormat();
+ _surface.init(width, height, width * bpp, mem, getPixelFormat());
_ownSurface = false;
}
@@ -122,7 +118,7 @@ const Graphics::Surface *CoktelDecoder::getSurface() const {
}
bool CoktelDecoder::hasSurface() {
- return _surface.pixels != 0;
+ return _surface.getPixels();
}
void CoktelDecoder::createSurface() {
@@ -143,7 +139,7 @@ void CoktelDecoder::freeSurface() {
_surface.w = 0;
_surface.h = 0;
_surface.pitch = 0;
- _surface.pixels = 0;
+ _surface.setPixels(0);
_surface.format = Graphics::PixelFormat();
} else
_surface.free();
@@ -473,7 +469,7 @@ void CoktelDecoder::renderBlockWhole(Graphics::Surface &dstSurf, const byte *src
rect.clip(dstSurf.w, dstSurf.h);
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left * dstSurf.format.bytesPerPixel;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
for (int i = 0; i < rect.height(); i++) {
memcpy(dst, src, rect.width() * dstSurf.format.bytesPerPixel);
@@ -488,7 +484,7 @@ void CoktelDecoder::renderBlockWhole4X(Graphics::Surface &dstSurf, const byte *s
rect.clip(dstSurf.w, dstSurf.h);
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
for (int i = 0; i < rect.height(); i++) {
byte *dstRow = dst;
const byte *srcRow = src;
@@ -515,7 +511,7 @@ void CoktelDecoder::renderBlockWhole2Y(Graphics::Surface &dstSurf, const byte *s
int16 height = rect.height();
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
while (height > 1) {
memcpy(dst , src, rect.width());
memcpy(dst + dstSurf.pitch, src, rect.width());
@@ -535,7 +531,7 @@ void CoktelDecoder::renderBlockSparse(Graphics::Surface &dstSurf, const byte *sr
rect.clip(dstSurf.w, dstSurf.h);
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
for (int i = 0; i < rect.height(); i++) {
byte *dstRow = dst;
int16 pixWritten = 0;
@@ -572,7 +568,7 @@ void CoktelDecoder::renderBlockSparse2Y(Graphics::Surface &dstSurf, const byte *
rect.clip(dstSurf.w, dstSurf.h);
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
for (int i = 0; i < rect.height(); i += 2) {
byte *dstRow = dst;
int16 pixWritten = 0;
@@ -604,7 +600,7 @@ void CoktelDecoder::renderBlockRLE(Graphics::Surface &dstSurf, const byte *src,
rect.clip(dstSurf.w, dstSurf.h);
- byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
+ byte *dst = (byte *)dstSurf.getBasePtr(rect.left, rect.top);
for (int i = 0; i < rect.height(); i++) {
byte *dstRow = dst;
int16 pixWritten = 0;
@@ -865,7 +861,7 @@ void PreIMDDecoder::renderFrame() {
uint16 h = CLIP<int32>(_surface.h - _y, 0, _height);
const byte *src = _videoBuffer;
- byte *dst = (byte *)_surface.pixels + (_y * _surface.pitch) + _x;
+ byte *dst = (byte *)_surface.getBasePtr(_x, _y);
uint32 frameDataSize = _videoBufferSize;
@@ -1458,7 +1454,7 @@ bool IMDDecoder::renderFrame(Common::Rect &rect) {
const int offsetY = (_y + rect.top) * _surface.pitch;
const int offset = offsetX + offsetY;
- if (deLZ77((byte *)_surface.pixels + offset, dataPtr, dataSize,
+ if (deLZ77((byte *)_surface.getPixels() + offset, dataPtr, dataSize,
_surface.w * _surface.h * _surface.format.bytesPerPixel - offset))
return true;
}
@@ -1879,11 +1875,8 @@ bool VMDDecoder::assessVideoProperties() {
_videoBuffer[i] = new byte[_videoBufferSize];
memset(_videoBuffer[i], 0, _videoBufferSize);
- _8bppSurface[i].w = _width * _bytesPerPixel;
- _8bppSurface[i].h = _height;
- _8bppSurface[i].pitch = _width * _bytesPerPixel;
- _8bppSurface[i].pixels = _videoBuffer[i];
- _8bppSurface[i].format = Graphics::PixelFormat::createFormatCLUT8();
+ _8bppSurface[i].init(_width * _bytesPerPixel, _height, _width * _bytesPerPixel,
+ _videoBuffer[i], Graphics::PixelFormat::createFormatCLUT8());
}
}
@@ -2277,7 +2270,7 @@ bool VMDDecoder::renderFrame(Common::Rect &rect) {
rect = Common::Rect(_x, _y, _x + codecSurf->w, _y + codecSurf->h);
rect.clip(Common::Rect(_x, _y, _x + _width, _y + _height));
- renderBlockWhole(_surface, (const byte *) codecSurf->pixels, rect);
+ renderBlockWhole(_surface, (const byte *)codecSurf->getPixels(), rect);
return true;
}
@@ -2298,7 +2291,7 @@ bool VMDDecoder::renderFrame(Common::Rect &rect) {
const int offsetY = (_y + rect.top) * _surface.pitch;
const int offset = offsetX + offsetY;
- if (deLZ77((byte *)_surface.pixels + offset, dataPtr, dataSize,
+ if (deLZ77((byte *)_surface.getPixels() + offset, dataPtr, dataSize,
_surface.w * _surface.h * _surface.format.bytesPerPixel - offset))
return true;
}
@@ -2406,10 +2399,11 @@ void VMDDecoder::blit16(const Graphics::Surface &srcSurf, Common::Rect &rect) {
Graphics::PixelFormat pixelFormat = getPixelFormat();
- const byte *src = (byte *)srcSurf.pixels +
+ // We cannot use getBasePtr here because srcSurf.format.bytesPerPixel is
+ // different from _bytesPerPixel.
+ const byte *src = (const byte *)srcSurf.getPixels() +
(srcRect.top * srcSurf.pitch) + srcRect.left * _bytesPerPixel;
- byte *dst = (byte *)_surface.pixels +
- ((_y + rect.top) * _surface.pitch) + (_x + rect.left) * _surface.format.bytesPerPixel;
+ byte *dst = (byte *)_surface.getBasePtr(_x + rect.left, _y + rect.top);
for (int i = 0; i < rect.height(); i++) {
const byte *srcRow = src;
@@ -2426,8 +2420,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;
@@ -2444,10 +2440,11 @@ void VMDDecoder::blit24(const Graphics::Surface &srcSurf, Common::Rect &rect) {
Graphics::PixelFormat pixelFormat = getPixelFormat();
- const byte *src = (byte *)srcSurf.pixels +
+ // We cannot use getBasePtr here because srcSurf.format.bytesPerPixel is
+ // different from _bytesPerPixel.
+ const byte *src = (const byte *)srcSurf.getPixels() +
(srcRect.top * srcSurf.pitch) + srcRect.left * _bytesPerPixel;
- byte *dst = (byte *)_surface.pixels +
- ((_y + rect.top) * _surface.pitch) + (_x + rect.left) * _surface.format.bytesPerPixel;
+ byte *dst = (byte *)_surface.getBasePtr(_x + rect.left, _y + rect.top);
for (int i = 0; i < rect.height(); i++) {
const byte *srcRow = src;
@@ -2462,8 +2459,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/dxa_decoder.cpp b/video/dxa_decoder.cpp
index 5ac9bd2088..27b1664b07 100644
--- a/video/dxa_decoder.cpp
+++ b/video/dxa_decoder.cpp
@@ -521,17 +521,17 @@ const Graphics::Surface *DXADecoder::DXAVideoTrack::decodeNextFrame() {
memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width);
}
- _surface->pixels = _scaledBuffer;
+ _surface->setPixels(_scaledBuffer);
break;
case S_DOUBLE:
for (int cy = 0; cy < _curHeight; cy++) {
memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width);
}
- _surface->pixels = _scaledBuffer;
+ _surface->setPixels(_scaledBuffer);
break;
case S_NONE:
- _surface->pixels = _frameBuffer1;
+ _surface->setPixels(_frameBuffer1);
break;
}
diff --git a/video/flic_decoder.cpp b/video/flic_decoder.cpp
index de545366b1..317dc14691 100644
--- a/video/flic_decoder.cpp
+++ b/video/flic_decoder.cpp
@@ -244,7 +244,7 @@ void FlicDecoder::FlicVideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch)
for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
for (int y = (*it).top; y < (*it).bottom; ++y) {
const int x = (*it).left;
- memcpy(dst + y * pitch + x, (byte *)_surface->pixels + y * getWidth() + x, (*it).right - x);
+ memcpy(dst + y * pitch + x, (byte *)_surface->getBasePtr(x, y), (*it).right - x);
}
}
@@ -252,7 +252,7 @@ void FlicDecoder::FlicVideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch)
}
void FlicDecoder::FlicVideoTrack::copyFrame(uint8 *data) {
- memcpy((byte *)_surface->pixels, data, getWidth() * getHeight());
+ memcpy((byte *)_surface->getPixels(), data, getWidth() * getHeight());
// Redraw
_dirtyRects.clear();
@@ -260,8 +260,8 @@ void FlicDecoder::FlicVideoTrack::copyFrame(uint8 *data) {
}
void FlicDecoder::FlicVideoTrack::decodeByteRun(uint8 *data) {
- byte *ptr = (byte *)_surface->pixels;
- while ((int32)(ptr - (byte *)_surface->pixels) < (getWidth() * getHeight())) {
+ byte *ptr = (byte *)_surface->getPixels();
+ while ((int32)(ptr - (byte *)_surface->getPixels()) < (getWidth() * getHeight())) {
int chunks = *data++;
while (chunks--) {
int count = (int8)*data++;
@@ -305,7 +305,7 @@ void FlicDecoder::FlicVideoTrack::decodeDeltaFLC(uint8 *data) {
case OP_UNDEFINED:
break;
case OP_LASTPIXEL:
- *((byte *)_surface->pixels + currentLine * getWidth() + getWidth() - 1) = (opcode & 0xFF);
+ *((byte *)_surface->getBasePtr(getWidth() - 1, currentLine)) = (opcode & 0xFF);
_dirtyRects.push_back(Common::Rect(getWidth() - 1, currentLine, getWidth(), currentLine + 1));
break;
case OP_LINESKIPCOUNT:
@@ -321,14 +321,14 @@ void FlicDecoder::FlicVideoTrack::decodeDeltaFLC(uint8 *data) {
column += *data++;
int rleCount = (int8)*data++;
if (rleCount > 0) {
- memcpy((byte *)_surface->pixels + (currentLine * getWidth()) + column, data, rleCount * 2);
+ memcpy((byte *)_surface->getBasePtr(column, currentLine), data, rleCount * 2);
data += rleCount * 2;
_dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1));
} else if (rleCount < 0) {
rleCount = -rleCount;
uint16 dataWord = READ_UINT16(data); data += 2;
for (int i = 0; i < rleCount; ++i) {
- WRITE_UINT16((byte *)_surface->pixels + currentLine * getWidth() + column + i * 2, dataWord);
+ WRITE_UINT16((byte *)_surface->getBasePtr(column + i * 2, currentLine), dataWord);
}
_dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1));
} else { // End of cutscene ?
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
diff --git a/video/smk_decoder.cpp b/video/smk_decoder.cpp
index 4e18268e72..3dbcebcde4 100644
--- a/video/smk_decoder.cpp
+++ b/video/smk_decoder.cpp
@@ -580,7 +580,7 @@ void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStream &bs) {
while (run-- && block < blocks) {
clr = _MClrTree->getCode(bs);
map = _MMapTree->getCode(bs);
- out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
+ out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
hi = clr >> 8;
lo = clr & 0xff;
for (i = 0; i < 4; i++) {
@@ -613,7 +613,7 @@ void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStream &bs) {
}
while (run-- && block < blocks) {
- out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
+ out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
switch (mode) {
case 0:
for (i = 0; i < 4; ++i) {
@@ -679,7 +679,7 @@ void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStream &bs) {
uint32 col;
mode = type >> 8;
while (run-- && block < blocks) {
- out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
+ out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
col = mode * 0x01010101;
for (i = 0; i < 4 * doubleY; ++i) {
out[0] = out[1] = out[2] = out[3] = col;
@@ -821,8 +821,9 @@ void SmackerDecoder::SmackerAudioTrack::queueCompressedBuffer(byte *buffer, uint
// (the exact opposite to the base values)
if (!is16Bits) {
for (int k = 0; k < (isStereo ? 2 : 1); k++) {
- bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS));
- *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80;
+ int8 delta = (int8) ((int16) audioTrees[k]->getCode(audioBS));
+ bases[k] = (bases[k] + delta) & 0xFF;
+ *curPointer++ = bases[k] ^ 0x80;
curPos++;
}
} else {
diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp
index 63aa93e2f5..a0ee0a36b4 100644
--- a/video/theora_decoder.cpp
+++ b/video/theora_decoder.cpp
@@ -262,11 +262,8 @@ TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(const Graphics::PixelFormat &f
_surface.create(theoraInfo.frame_width, theoraInfo.frame_height, format);
// Set up a display surface
- _displaySurface.pixels = _surface.getBasePtr(theoraInfo.pic_x, theoraInfo.pic_y);
- _displaySurface.w = theoraInfo.pic_width;
- _displaySurface.h = theoraInfo.pic_height;
- _displaySurface.format = format;
- _displaySurface.pitch = _surface.pitch;
+ _displaySurface.init(theoraInfo.pic_width, theoraInfo.pic_height, _surface.pitch,
+ _surface.getBasePtr(theoraInfo.pic_x, theoraInfo.pic_y), format);
// Set the frame rate
_frameRate = Common::Rational(theoraInfo.fps_numerator, theoraInfo.fps_denominator);
@@ -280,7 +277,7 @@ TheoraDecoder::TheoraVideoTrack::~TheoraVideoTrack() {
th_decode_free(_theoraDecode);
_surface.free();
- _displaySurface.pixels = 0;
+ _displaySurface.setPixels(0);
}
bool TheoraDecoder::TheoraVideoTrack::decodePacket(ogg_packet &oggPacket) {
@@ -338,7 +335,7 @@ TheoraDecoder::VorbisAudioTrack::VorbisAudioTrack(Audio::Mixer::SoundType soundT
vorbis_block_init(&_vorbisDSP, &_vorbisBlock);
info = &vorbisInfo;
- _audStream = Audio::makeQueuingAudioStream(vorbisInfo.rate, vorbisInfo.channels);
+ _audStream = Audio::makeQueuingAudioStream(vorbisInfo.rate, vorbisInfo.channels != 1);
_audioBufferFill = 0;
_audioBuffer = 0;
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 5df811008c..0ab1478727 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -62,6 +62,8 @@ void VideoDecoder::close() {
delete *it;
_tracks.clear();
+ _internalTracks.clear();
+ _externalTracks.clear();
_dirtyPalette = false;
_palette = 0;
_startTime = 0;
@@ -336,7 +338,12 @@ bool VideoDecoder::seek(const Audio::Timestamp &time) {
if (isPlaying())
stopAudio();
- for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++)
+ // Do the actual seeking
+ if (!seekIntern(time))
+ return false;
+
+ // Seek any external track too
+ for (TrackListIterator it = _externalTracks.begin(); it != _externalTracks.end(); it++)
if (!(*it)->seek(time))
return false;
@@ -356,12 +363,12 @@ bool VideoDecoder::seek(const Audio::Timestamp &time) {
}
bool VideoDecoder::seekToFrame(uint frame) {
+ if (!isSeekable())
+ return false;
+
VideoTrack *track = 0;
for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) {
- if (!(*it)->isSeekable())
- return false;
-
if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
// We only allow seeking by frame when one video track
// is present
@@ -471,6 +478,14 @@ Audio::Timestamp VideoDecoder::getDuration() const {
return maxDuration;
}
+bool VideoDecoder::seekIntern(const Audio::Timestamp &time) {
+ for (TrackList::iterator it = _internalTracks.begin(); it != _internalTracks.end(); it++)
+ if (!(*it)->seek(time))
+ return false;
+
+ return true;
+}
+
VideoDecoder::Track::Track() {
_paused = false;
}
@@ -516,10 +531,9 @@ Audio::Timestamp VideoDecoder::FixedRateVideoTrack::getFrameTime(uint frame) con
if (frameRate == frameRate.toInt()) // The nice case (a whole number)
return Audio::Timestamp(0, frame, frameRate.toInt());
- // Just convert to milliseconds.
- Common::Rational time = frame * 1000;
- time /= frameRate;
- return Audio::Timestamp(time.toInt(), 1000);
+ // Convert as best as possible
+ Common::Rational time = frameRate.getInverse() * frame;
+ return Audio::Timestamp(0, time.getNumerator(), time.getDenominator());
}
uint VideoDecoder::FixedRateVideoTrack::getFrameAtTime(const Audio::Timestamp &time) const {
@@ -529,8 +543,10 @@ uint VideoDecoder::FixedRateVideoTrack::getFrameAtTime(const Audio::Timestamp &t
if (frameRate == time.framerate())
return time.totalNumberOfFrames();
- // Default case
- return (time.totalNumberOfFrames() * frameRate / time.framerate()).toInt();
+ // Create the rational based on the time first to hopefully cancel out
+ // *something* when multiplying by the frameRate (which can be large in
+ // some AVI videos).
+ return (Common::Rational(time.totalNumberOfFrames(), time.framerate()) * frameRate).toInt();
}
Audio::Timestamp VideoDecoder::FixedRateVideoTrack::getDuration() const {
@@ -641,9 +657,14 @@ bool VideoDecoder::StreamFileAudioTrack::loadFromFile(const Common::String &base
return _stream != 0;
}
-void VideoDecoder::addTrack(Track *track) {
+void VideoDecoder::addTrack(Track *track, bool isExternal) {
_tracks.push_back(track);
+ if (isExternal)
+ _externalTracks.push_back(track);
+ else
+ _internalTracks.push_back(track);
+
if (track->getTrackType() == Track::kTrackTypeAudio) {
// Update volume settings if it's an audio track
((AudioTrack *)track)->setVolume(_audioVolume);
@@ -673,7 +694,7 @@ bool VideoDecoder::addStreamFileTrack(const Common::String &baseName) {
bool result = track->loadFromFile(baseName);
if (result)
- addTrack(track);
+ addTrack(track, true);
else
delete track;
@@ -704,17 +725,17 @@ void VideoDecoder::setEndTime(const Audio::Timestamp &endTime) {
}
VideoDecoder::Track *VideoDecoder::getTrack(uint track) {
- if (track > _tracks.size())
+ if (track > _internalTracks.size())
return 0;
- return _tracks[track];
+ return _internalTracks[track];
}
const VideoDecoder::Track *VideoDecoder::getTrack(uint track) const {
- if (track > _tracks.size())
+ if (track > _internalTracks.size())
return 0;
- return _tracks[track];
+ return _internalTracks[track];
}
bool VideoDecoder::endOfVideoTracks() const {
diff --git a/video/video_decoder.h b/video/video_decoder.h
index d0a6e08005..ac6586d8dd 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -168,14 +168,15 @@ public:
/**
* Seek to a given time in the video.
*
- * If the video is playing, it will continue to play. The default
- * implementation will seek each track and must still be called
- * from any other implementation.
+ * If the video is playing, it will continue to play. This calls
+ * seekIntern(), which can be overriden. By default, seekIntern()
+ * will call Track::seek() on all tracks with the time passed to
+ * this function.
*
* @param time The time to seek to
* @return true on success, false otherwise
*/
- virtual bool seek(const Audio::Timestamp &time);
+ bool seek(const Audio::Timestamp &time);
/**
* Seek to a given frame.
@@ -593,17 +594,17 @@ protected:
virtual Audio::Timestamp getDuration() const;
Audio::Timestamp getFrameTime(uint frame) const;
- protected:
- /**
- * Get the rate at which this track is played.
- */
- virtual Common::Rational getFrameRate() const = 0;
-
/**
* Get the frame that should be displaying at the given time. This is
* helpful for someone implementing seek().
*/
uint getFrameAtTime(const Audio::Timestamp &time) const;
+
+ protected:
+ /**
+ * Get the rate at which this track is played.
+ */
+ virtual Common::Rational getFrameRate() const = 0;
};
/**
@@ -760,8 +761,11 @@ protected:
* Define a track to be used by this class.
*
* The pointer is then owned by this base class.
+ *
+ * @param track The track to add
+ * @param isExternal Is this an external track not found by loadStream()?
*/
- void addTrack(Track *track);
+ void addTrack(Track *track, bool isExternal = false);
/**
* Whether or not getTime() will sync with a playing audio track.
@@ -813,16 +817,27 @@ protected:
/**
* Get the begin iterator of the tracks
*/
- TrackListIterator getTrackListBegin() { return _tracks.begin(); }
+ TrackListIterator getTrackListBegin() { return _internalTracks.begin(); }
/**
* Get the end iterator of the tracks
*/
- TrackListIterator getTrackListEnd() { return _tracks.end(); }
+ TrackListIterator getTrackListEnd() { return _internalTracks.end(); }
+
+ /**
+ * The internal seek function that does the actual seeking.
+ *
+ * @see seek()
+ *
+ * @return true on success, false otherwise
+ */
+ virtual bool seekIntern(const Audio::Timestamp &time);
private:
// Tracks owned by this VideoDecoder
TrackList _tracks;
+ TrackList _internalTracks;
+ TrackList _externalTracks;
// Current playback status
bool _needsUpdate;